Compare commits

..

2 Commits

Author SHA1 Message Date
Rui Matos
b9d798c213 cursor-tracker: Properly handle invisible cursors
We might be asked to not display the cursor ourselves but we should
still emit cursor-changed signals and hand out the correct sprite and
hot point information when asked so that consumers can still draw an
updated cursor themselves.

This fixes the cursor not showing up in gnome-shell's zoom mode.
2014-04-07 19:23:35 +02:00
Rui Matos
5abf41ab5a split cursor_tracker 2014-04-07 19:20:14 +02:00
153 changed files with 30787 additions and 20780 deletions

8
.gitignore vendored
View File

@@ -22,7 +22,7 @@ missing
src/50-mutter-navigation.xml src/50-mutter-navigation.xml
src/50-mutter-system.xml src/50-mutter-system.xml
src/50-mutter-windows.xml src/50-mutter-windows.xml
src/mutter.desktop src/mutter-wm.desktop
src/mutter-wayland.desktop src/mutter-wayland.desktop
*.o *.o
*.a *.a
@@ -46,8 +46,8 @@ POTFILES
po/*.pot po/*.pot
50-metacity-desktop-key.xml 50-metacity-desktop-key.xml
50-metacity-key.xml 50-metacity-key.xml
libmutter.pc libmutter-wayland.pc
mutter mutter-wayland
mutter-launch mutter-launch
org.gnome.mutter.gschema.valid org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml org.gnome.mutter.gschema.xml
@@ -56,7 +56,6 @@ org.gnome.mutter.wayland.gschema.xml
testasyncgetprop testasyncgetprop
testboxes testboxes
testgradient testgradient
m4/*
mutter-grayscale mutter-grayscale
mutter-mag mutter-mag
mutter-message mutter-message
@@ -78,6 +77,7 @@ src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h src/stamp-mutter-marshal.h
src/meta-dbus-display-config.[ch] src/meta-dbus-display-config.[ch]
src/meta-dbus-idle-monitor.[ch] src/meta-dbus-idle-monitor.[ch]
src/mutter-plugins.pc
src/gtk-shell-protocol.c src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c src/xdg-shell-protocol.c

View File

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

30
NEWS
View File

@@ -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 3.12.0
====== ======
* Fix grab issue with SSD xwayland windows [Rui; #726123] * Fix grab issue with SSD xwayland windows [Rui; #726123]

View File

@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3]) m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13]) m4_define([mutter_minor_version], [12])
m4_define([mutter_micro_version], [1]) m4_define([mutter_micro_version], [0])
m4_define([mutter_version], m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version]) [mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -13,7 +13,6 @@ m4_define([mutter_plugin_api_version], [3])
AC_INIT([mutter], [mutter_version], AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter]) [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/core/display.c) AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)
@@ -21,6 +20,10 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable]) AM_MAINTAINER_MODE([enable])
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
PACKAGE="mutter-wayland"
AC_SUBST([PACKAGE], [$PACKAGE])
MUTTER_MAJOR_VERSION=mutter_major_version MUTTER_MAJOR_VERSION=mutter_major_version
MUTTER_MINOR_VERSION=mutter_minor_version MUTTER_MINOR_VERSION=mutter_minor_version
MUTTER_MICRO_VERSION=mutter_micro_version MUTTER_MICRO_VERSION=mutter_micro_version
@@ -36,7 +39,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
# Honor aclocal flags # Honor aclocal flags
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}") AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
GETTEXT_PACKAGE=mutter GETTEXT_PACKAGE=mutter-wayland
AC_SUBST(GETTEXT_PACKAGE) AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain]) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
@@ -69,12 +72,12 @@ CANBERRA_GTK_VERSION=0.26
CLUTTER_PACKAGE=clutter-1.0 CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES=" MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11 gtk+-3.0 >= 3.3.7
gio-2.0 >= 2.25.10 gio-2.0 >= 2.25.10
pango >= 1.2.0 pango >= 1.2.0
cairo >= 1.10.0 cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3 gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0 xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.17.5 $CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1 cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0 upower-glib >= 0.99.0
@@ -130,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
AC_ARG_WITH([xwayland-path], AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])], [AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"], [XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"]) [XWAYLAND_PATH="$bindir/Xorg"])
AM_GLIB_GNU_GETTEXT AM_GLIB_GNU_GETTEXT
@@ -249,6 +252,28 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found]) AC_MSG_ERROR([Xinerama extension was not found])
fi fi
SHAPE_LIBS=
found_shape=no
AC_CHECK_LIB(Xext, XShapeQueryExtension,
[AC_CHECK_HEADER(X11/extensions/shape.h,
SHAPE_LIBS=-lXext found_shape=yes)],
, $ALL_X_LIBS)
if test x$enable_shape = xno; then
found_shape=no
fi
if test x$enable_shape = xyes; then
if test "$found_shape" = "no"; then
AC_MSG_ERROR([--enable-shape forced and Shape not found])
exit 1
fi
fi
if test "x$found_shape" = "xyes"; then
AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library])
fi
found_xkb=no found_xkb=no
AC_CHECK_LIB(X11, XkbQueryExtension, AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h, [AC_CHECK_HEADER(X11/XKBlib.h,
@@ -266,13 +291,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
[AC_CHECK_HEADER(X11/extensions/Xrandr.h, [AC_CHECK_HEADER(X11/extensions/Xrandr.h,
RANDR_LIBS=-lXrandr found_randr=yes,, RANDR_LIBS=-lXrandr found_randr=yes,,
[#include <X11/Xlib.h>])], [#include <X11/Xlib.h>])],
, -lXext $ALL_X_LIBS) , -lXrender -lXext $ALL_X_LIBS)
if test "x$found_randr" = "xyes"; then if test "x$found_randr" = "xyes"; then
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
fi fi
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" XSYNC_LIBS=
found_xsync=no
AC_CHECK_LIB(Xext, XSyncQueryExtension,
[AC_CHECK_HEADER(X11/extensions/sync.h,
found_xsync=yes,,
[#include <X11/Xlib.h>])],
, $ALL_X_LIBS)
if test x$enable_xsync = xno; then
found_xsync=no
fi
if test x$enable_xsync = xyes; then
if test "$found_xsync" = "no"; then
AC_MSG_ERROR([--enable-xsync forced and XSync not found])
exit 1
fi
fi
if test "x$found_xsync" = "xyes"; then
XSYNC_LIBS=-lXext
AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library])
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
found_sm=no found_sm=no
case "$MUTTER_LIBS" in case "$MUTTER_LIBS" in
@@ -402,7 +451,7 @@ doc/man/Makefile
doc/reference/Makefile doc/reference/Makefile
doc/reference/meta-docs.sgml doc/reference/meta-docs.sgml
src/Makefile src/Makefile
src/libmutter.pc src/libmutter-wayland.pc
src/compositor/plugins/Makefile src/compositor/plugins/Makefile
po/Makefile.in po/Makefile.in
]) ])
@@ -419,7 +468,7 @@ fi
dnl ========================================================================== dnl ==========================================================================
echo " echo "
mutter-$VERSION mutter-wayland-$VERSION
prefix: ${prefix} prefix: ${prefix}
source code location: ${srcdir} source code location: ${srcdir}
@@ -429,6 +478,8 @@ mutter-$VERSION
libcanberra: ${have_libcanberra} libcanberra: ${have_libcanberra}
Introspection: ${found_introspection} Introspection: ${found_introspection}
Session management: ${found_sm} Session management: ${found_sm}
Shape extension: ${found_shape}
Xsync: ${found_xsync}
" "

View File

@@ -1,3 +0,0 @@
defaultcursordir = $(datadir)/mutter/cursors
dist_defaultcursor_DATA = left_ptr.png

View File

@@ -140,7 +140,7 @@ expand_content_files= \
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(MUTTER_CFLAGS) GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
# This includes the standard gtk-doc make rules, copied by gtkdocize. # This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make include $(top_srcdir)/gtk-doc.make

View File

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

View File

@@ -3,7 +3,6 @@
src/50-mutter-navigation.xml.in src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in src/50-mutter-windows.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c src/compositor/compositor.c
src/compositor/meta-background.c src/compositor/meta-background.c
src/core/bell.c src/core/bell.c
@@ -13,12 +12,16 @@ src/core/display.c
src/core/errors.c src/core/errors.c
src/core/keybindings.c src/core/keybindings.c
src/core/main.c src/core/main.c
src/core/monitor.c
src/core/mutter.c src/core/mutter.c
src/core/prefs.c src/core/prefs.c
src/core/screen.c src/core/screen.c
src/x11/session.c
src/core/util.c src/core/util.c
src/core/window.c src/core/window.c
src/mutter.desktop.in src/x11/window-props.c
src/x11/xprops.c
src/mutter-wayland.desktop.in
src/org.gnome.mutter.gschema.xml.in src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c src/ui/frames.c
@@ -27,6 +30,3 @@ src/ui/metaaccellabel.c
src/ui/resizepopup.c src/ui/resizepopup.c
src/ui/theme.c src/ui/theme.c
src/ui/theme-parser.c src/ui/theme-parser.c
src/x11/session.c
src/x11/window-props.c
src/x11/xprops.c

733
po/ar.po

File diff suppressed because it is too large Load Diff

2680
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

735
po/cs.po

File diff suppressed because it is too large Load Diff

771
po/da.po

File diff suppressed because it is too large Load Diff

3597
po/el.po

File diff suppressed because it is too large Load Diff

1703
po/es.po

File diff suppressed because it is too large Load Diff

787
po/eu.po

File diff suppressed because it is too large Load Diff

756
po/fr.po

File diff suppressed because it is too large Load Diff

3214
po/ga.po

File diff suppressed because it is too large Load Diff

1234
po/gl.po

File diff suppressed because it is too large Load Diff

1583
po/he.po

File diff suppressed because it is too large Load Diff

790
po/hu.po

File diff suppressed because it is too large Load Diff

951
po/id.po

File diff suppressed because it is too large Load Diff

737
po/it.po

File diff suppressed because it is too large Load Diff

2012
po/kn.po

File diff suppressed because it is too large Load Diff

531
po/ko.po

File diff suppressed because it is too large Load Diff

730
po/lt.po

File diff suppressed because it is too large Load Diff

528
po/lv.po

File diff suppressed because it is too large Load Diff

716
po/nb.po

File diff suppressed because it is too large Load Diff

1194
po/nl.po

File diff suppressed because it is too large Load Diff

524
po/pa.po

File diff suppressed because it is too large Load Diff

725
po/pl.po

File diff suppressed because it is too large Load Diff

797
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

992
po/ru.po

File diff suppressed because it is too large Load Diff

417
po/sk.po
View File

@@ -13,9 +13,9 @@ msgstr ""
"Project-Id-Version: mutter\n" "Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n" "product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-08-21 17:41+0000\n" "POT-Creation-Date: 2013-05-24 21:44+0000\n"
"PO-Revision-Date: 2013-08-02 14:46+0200\n" "PO-Revision-Date: 2013-05-18 16:53+0100\n"
"Last-Translator: Ján Kyselica <kyselica.jan@gmail.com>\n" "Last-Translator: Jan Kyselica <kyselica.jan@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n" "Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"Language: sk\n" "Language: sk\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -87,8 +87,9 @@ msgstr "Prepnúť okná aplikácie"
# PK: zisti co to robi # PK: zisti co to robi
# description # description
#: ../src/50-mutter-navigation.xml.in.h:13 #: ../src/50-mutter-navigation.xml.in.h:13
#, fuzzy
msgid "Switch system controls" msgid "Switch system controls"
msgstr "Prepnúť medzi ovládacími prvkami systému" msgstr "Prepnúť medzi systémovými ovládacími prvkami"
# description # description
#: ../src/50-mutter-navigation.xml.in.h:14 #: ../src/50-mutter-navigation.xml.in.h:14
@@ -103,8 +104,9 @@ msgstr "Prepnúť okná aplikácie priamo"
# MČ: podobne ako vyššie: „cycle-panels“ # MČ: podobne ako vyššie: „cycle-panels“
# description # description
#: ../src/50-mutter-navigation.xml.in.h:16 #: ../src/50-mutter-navigation.xml.in.h:16
#, fuzzy
msgid "Switch system controls directly" msgid "Switch system controls directly"
msgstr "Prepnúť medzi ovládacími prvkami systému priamo" msgstr "Prepnúť medzi systémovými ovládacími prvkami priamo"
# description # description
#: ../src/50-mutter-navigation.xml.in.h:17 #: ../src/50-mutter-navigation.xml.in.h:17
@@ -265,13 +267,13 @@ msgstr "Zobraziť rozdelenie napravo"
# PK: je %i cislo obrazovky? ak ano tak "č. %i" # PK: je %i cislo obrazovky? ak ano tak "č. %i"
#. This probably means that a non-WM compositor like xcompmgr is running; #. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit #. * we have no way to get it to exit
#: ../src/compositor/compositor.c:596 #: ../src/compositor/compositor.c:571
#, c-format #, fuzzy, c-format
msgid "" msgid ""
"Another compositing manager is already running on screen %i on display \"%s" "Another compositing manager is already running on screen %i on display \"%s"
"\"." "\"."
msgstr "" msgstr ""
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia." "Pre obrazovku %i na displeji „%s“ je spustený už iný správca rozloženia."
#: ../src/compositor/meta-background.c:1076 #: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file" msgid "background texture could not be created from file"
@@ -311,18 +313,18 @@ msgstr "_Počkať"
msgid "_Force Quit" msgid "_Force Quit"
msgstr "_Vynútiť ukončenie" msgstr "_Vynútiť ukončenie"
#: ../src/core/display.c:421 #: ../src/core/display.c:401
#, c-format #, c-format
msgid "Missing %s extension required for compositing" msgid "Missing %s extension required for compositing"
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba" msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
# X window system preloz, napr. system na spravu okien X # X window system preloz, napr. system na spravu okien X
#: ../src/core/display.c:513 #: ../src/core/display.c:493
#, c-format #, c-format
msgid "Failed to open X Window System display '%s'\n" msgid "Failed to open X Window System display '%s'\n"
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n" msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
#: ../src/core/keybindings.c:1136 #: ../src/core/keybindings.c:970
#, c-format #, c-format
msgid "" msgid ""
"Some other program is already using the key %s with modifiers %x as a " "Some other program is already using the key %s with modifiers %x as a "
@@ -330,7 +332,7 @@ msgid ""
msgstr "" msgstr ""
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n" "Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
#: ../src/core/keybindings.c:1333 #: ../src/core/keybindings.c:1151
#, c-format #, c-format
msgid "\"%s\" is not a valid accelerator\n" msgid "\"%s\" is not a valid accelerator\n"
msgstr "„%s“ nie je platný akcelerátor\n" msgstr "„%s“ nie je platný akcelerátor\n"
@@ -376,20 +378,6 @@ msgid ""
msgstr "" msgstr ""
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n" "Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
#: ../src/core/monitor.c:702
msgid "Built-in display"
msgstr "Vstavaný displej"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:730
#, c-format
#| msgid "Unknown element %s"
msgid "Unknown %s"
msgstr "Neznámy %s"
#: ../src/core/mutter.c:40 #: ../src/core/mutter.c:40
#, c-format #, c-format
msgid "" msgid ""
@@ -415,7 +403,7 @@ msgstr "Zobrazí verziu"
msgid "Mutter plugin to use" msgid "Mutter plugin to use"
msgstr "Použije zásuvný modul Mutter" msgstr "Použije zásuvný modul Mutter"
#: ../src/core/prefs.c:1202 #: ../src/core/prefs.c:1193
msgid "" msgid ""
"Workarounds for broken applications disabled. Some applications may not " "Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n" "behave properly.\n"
@@ -423,12 +411,12 @@ msgstr ""
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie " "Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
"sa nemusia správať správne.\n" "sa nemusia správať správne.\n"
#: ../src/core/prefs.c:1277 #: ../src/core/prefs.c:1268
#, c-format #, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n" msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n" msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
#: ../src/core/prefs.c:1343 #: ../src/core/prefs.c:1334
#, c-format #, c-format
msgid "" msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button " "\"%s\" found in configuration database is not a valid value for mouse button "
@@ -437,7 +425,7 @@ msgstr ""
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre " "V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
"modifikátor tlačidla myši\n" "modifikátor tlačidla myši\n"
#: ../src/core/prefs.c:1909 #: ../src/core/prefs.c:1881
#, c-format #, c-format
msgid "" msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding " "\"%s\" found in configuration database is not a valid value for keybinding "
@@ -446,17 +434,17 @@ msgstr ""
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre " "V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
"klávesovú skratku „%s“\n" "klávesovú skratku „%s“\n"
#: ../src/core/prefs.c:1999 #: ../src/core/prefs.c:1945
#, c-format #, c-format
msgid "Workspace %d" msgid "Workspace %d"
msgstr "Pracovný priestor č. %d" msgstr "Pracovný priestor č. %d"
#: ../src/core/screen.c:537 #: ../src/core/screen.c:691
#, c-format #, c-format
msgid "Screen %d on display '%s' is invalid\n" msgid "Screen %d on display '%s' is invalid\n"
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n" msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
#: ../src/core/screen.c:553 #: ../src/core/screen.c:707
#, c-format #, c-format
msgid "" msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --" "Screen %d on display \"%s\" already has a window manager; try using the --"
@@ -465,7 +453,7 @@ msgstr ""
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač " "Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
"--replace, aby sa aktuálny správca nahradil.\n" "--replace, aby sa aktuálny správca nahradil.\n"
#: ../src/core/screen.c:580 #: ../src/core/screen.c:734
#, c-format #, c-format
msgid "" msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n" "Could not acquire window manager selection on screen %d display \"%s\"\n"
@@ -473,12 +461,12 @@ msgstr ""
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji " "Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
"„%s“\n" "„%s“\n"
#: ../src/core/screen.c:658 #: ../src/core/screen.c:812
#, c-format #, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n" msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n" msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
#: ../src/core/screen.c:850 #: ../src/core/screen.c:998
#, c-format #, c-format
msgid "Could not release screen %d on display \"%s\"\n" msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n" msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
@@ -554,7 +542,8 @@ msgstr "Zlyhalo otvorenie súboru so záznamom pomocou fdopen() %s: %s\n"
msgid "Opened log file %s\n" msgid "Opened log file %s\n"
msgstr "Otvorený súbor so záznamom %s\n" msgstr "Otvorený súbor so záznamom %s\n"
#: ../src/core/util.c:119 #: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n" msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n" msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
@@ -562,20 +551,20 @@ msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
msgid "Window manager: " msgid "Window manager: "
msgstr "Správca okien: " msgstr "Správca okien: "
#: ../src/core/util.c:414 #: ../src/core/util.c:412
msgid "Bug in window manager: " msgid "Bug in window manager: "
msgstr "Chyba v správcovi okien: " msgstr "Chyba v správcovi okien: "
#: ../src/core/util.c:445 #: ../src/core/util.c:443
msgid "Window manager warning: " msgid "Window manager warning: "
msgstr "Varovanie správcu okien: " msgstr "Varovanie správcu okien: "
#: ../src/core/util.c:473 #: ../src/core/util.c:471
msgid "Window manager error: " msgid "Window manager error: "
msgstr "Chyba správcu okien: " msgstr "Chyba správcu okien: "
#. first time through #. first time through
#: ../src/core/window.c:7533 #: ../src/core/window.c:7505
#, c-format #, c-format
msgid "" msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@@ -591,7 +580,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain #. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work. #. * about these apps but make them work.
#. #.
#: ../src/core/window.c:8257 #: ../src/core/window.c:8229
#, c-format #, c-format
msgid "" msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size " "Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@@ -601,7 +590,7 @@ msgstr ""
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva " "nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
"zmysel.\n" "zmysel.\n"
#: ../src/core/window-props.c:347 #: ../src/core/window-props.c:318
#, c-format #, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n" msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n" msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
@@ -609,18 +598,18 @@ msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
# PK: co je toto? # PK: co je toto?
# JK: nedokazem zistit # JK: nedokazem zistit
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom # PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
#: ../src/core/window-props.c:463 #: ../src/core/window-props.c:434
#, fuzzy, c-format #, fuzzy, c-format
msgid "%s (on %s)" msgid "%s (on %s)"
msgstr "%s (na %s)" msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546 #: ../src/core/window-props.c:1517
#, c-format #, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n" msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
# MČ: zacykliť sa, alebo vytvoriť slučku. # MČ: zacykliť sa, alebo vytvoriť slučku.
#: ../src/core/window-props.c:1557 #: ../src/core/window-props.c:1528
#, c-format #, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n" msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
@@ -708,9 +697,9 @@ msgid ""
"vertically and resizes them horizontally to cover half of the available " "vertically and resizes them horizontally to cover half of the available "
"area. Dropping windows on the top screen edge maximizes them completely." "area. Dropping windows on the top screen edge maximizes them completely."
msgstr "" msgstr ""
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich zvislo " "Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich "
"maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej plochy. " "zvislo maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej "
"Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne." "plochy. Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
# summary # summary
#: ../src/org.gnome.mutter.gschema.xml.in.h:7 #: ../src/org.gnome.mutter.gschema.xml.in.h:7
@@ -746,8 +735,9 @@ msgstr ""
# PM: ja by som dal Bez vyvovlávania tabulátorom # PM: ja by som dal Bez vyvovlávania tabulátorom
# summary # summary
#: ../src/org.gnome.mutter.gschema.xml.in.h:11 #: ../src/org.gnome.mutter.gschema.xml.in.h:11
#, fuzzy
msgid "No tab popup" msgid "No tab popup"
msgstr "Bez vyvolávania tabulátorom" msgstr "Nepoužívať prekryvnú ponuku tabulátora"
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“ # MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
# description # description
@@ -816,104 +806,109 @@ msgstr "Vybrať okno z rozbaľovacej ponuky tabulátoru"
msgid "Cancel tab popup" msgid "Cancel tab popup"
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru" msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Použitie: %s\n"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67 #: ../src/ui/menu.c:69
msgid "Mi_nimize" msgid "Mi_nimize"
msgstr "Mi_nimalizovať" msgstr "Mi_nimalizovať"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69 #: ../src/ui/menu.c:71
msgid "Ma_ximize" msgid "Ma_ximize"
msgstr "Ma_ximalizovať" msgstr "Ma_ximalizovať"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71 #: ../src/ui/menu.c:73
msgid "Unma_ximize" msgid "Unma_ximize"
msgstr "Zrušiť ma_ximalizáciu" msgstr "Zrušiť ma_ximalizáciu"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73 #: ../src/ui/menu.c:75
msgid "Roll _Up" msgid "Roll _Up"
msgstr "_Zabaliť" msgstr "_Zabaliť"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75 #: ../src/ui/menu.c:77
msgid "_Unroll" msgid "_Unroll"
msgstr "_Rozbaliť" msgstr "_Rozbaliť"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77 #: ../src/ui/menu.c:79
msgid "_Move" msgid "_Move"
msgstr "Pre_miestniť" msgstr "Pre_miestniť"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79 #: ../src/ui/menu.c:81
msgid "_Resize" msgid "_Resize"
msgstr "Zmeniť veľko_sť" msgstr "Zmeniť veľko_sť"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81 #: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen" msgid "Move Titlebar On_screen"
msgstr "Presunúť titulok na _obrazovku" msgstr "Presunúť titulok na _obrazovku"
#. separator #. separator
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86 #: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top" msgid "Always on _Top"
msgstr "Vždy na_vrchu" msgstr "Vždy na_vrchu"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88 #: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace" msgid "_Always on Visible Workspace"
msgstr "Vž_dy na viditeľnom pracovnom priestore" msgstr "Vž_dy na viditeľnom pracovnom priestore"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90 #: ../src/ui/menu.c:92
msgid "_Only on This Workspace" msgid "_Only on This Workspace"
msgstr "_Len na tomto pracovnom priestore" msgstr "_Len na tomto pracovnom priestore"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92 #: ../src/ui/menu.c:94
msgid "Move to Workspace _Left" msgid "Move to Workspace _Left"
msgstr "Presunúť na pracovný priestor vľav_o" msgstr "Presunúť na pracovný priestor vľav_o"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94 #: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight" msgid "Move to Workspace R_ight"
msgstr "Presunúť na pracovný priestor v_pravo" msgstr "Presunúť na pracovný priestor v_pravo"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96 #: ../src/ui/menu.c:98
msgid "Move to Workspace _Up" msgid "Move to Workspace _Up"
msgstr "Presunúť na pracovný priestor _hore" msgstr "Presunúť na pracovný priestor _hore"
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98 #: ../src/ui/menu.c:100
msgid "Move to Workspace _Down" msgid "Move to Workspace _Down"
msgstr "Presunúť na pracovný priestor _dole" msgstr "Presunúť na pracovný priestor _dole"
#. separator #. separator
#. Translators: Translate this string the same way as you do in libwnck! #. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102 #: ../src/ui/menu.c:104
msgid "_Close" msgid "_Close"
msgstr "_Zavrieť" msgstr "_Zavrieť"
#: ../src/ui/menu.c:202 #: ../src/ui/menu.c:204
#, c-format #, c-format
msgid "Workspace %d%n" msgid "Workspace %d%n"
msgstr "Pracovná priestor %d%n" msgstr "Pracovná priestor %d%n"
#: ../src/ui/menu.c:212 #: ../src/ui/menu.c:214
#, c-format #, c-format
msgid "Workspace 1_0" msgid "Workspace 1_0"
msgstr "Pracovný priestor 1_0" msgstr "Pracovný priestor 1_0"
#: ../src/ui/menu.c:214 #: ../src/ui/menu.c:216
#, c-format #, c-format
msgid "Workspace %s%d" msgid "Workspace %s%d"
msgstr "Pracovný priestor %s%d" msgstr "Pracovný priestor %s%d"
#: ../src/ui/menu.c:384 #: ../src/ui/menu.c:397
msgid "Move to Another _Workspace" msgid "Move to Another _Workspace"
msgstr "P_resunúť na iný pracovný priestor" msgstr "P_resunúť na iný pracovný priestor"
@@ -1071,21 +1066,21 @@ msgstr ""
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“ # MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky # PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
#: ../src/ui/theme.c:1219 #: ../src/ui/theme.c:1219
#, c-format #, fuzzy, c-format
msgid "" msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid" "_ are valid"
msgstr "" msgstr ""
"V parametri color_name (názov farby) pre gtk:custom je neplatný znak „%c“, platné sú len " "V parametri názov_farby pre gtk:custom je neplatný znak „%c“, platné sú len "
"znaky A-Za-z0-9-_" "znaky A-Za-z0-9-_"
#: ../src/ui/theme.c:1233 #: ../src/ui/theme.c:1233
#, c-format #, fuzzy, c-format
msgid "" msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format" "fit the format"
msgstr "" msgstr ""
"Formát Gtk:custom je „gtk:custom(color_name,fallback)“, „%s“ tomu " "Formát Gtk:custom je „gtk:custom(názov_farby,fallback)“, „%s“ tomu "
"nezodpovedá" "nezodpovedá"
#: ../src/ui/theme.c:1278 #: ../src/ui/theme.c:1278
@@ -1271,20 +1266,20 @@ msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>" msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
#: ../src/ui/theme.c:5082 #: ../src/ui/theme.c:5084
#, c-format #, c-format
msgid "Failed to load theme \"%s\": %s\n" msgid "Failed to load theme \"%s\": %s\n"
msgstr "Zlyhalo načítanie témy „%s“: %s\n" msgstr "Zlyhalo načítanie témy „%s“: %s\n"
# PK: prvok? # PK: prvok?
# JK: XML značka (XML tag) # JK: XML značka (XML tag)
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232 #: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246 #: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
#, c-format #, c-format
msgid "No <%s> set for theme \"%s\"" msgid "No <%s> set for theme \"%s\""
msgstr "Pre tému „%s“ nie je nastavená <%s>" msgstr "Pre tému „%s“ nie je nastavená <%s>"
#: ../src/ui/theme.c:5254 #: ../src/ui/theme.c:5256
#, c-format #, c-format
msgid "" msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window " "No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@@ -1293,13 +1288,13 @@ msgstr ""
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window " "Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
"type=„%s“ style_set=„whatever“/>" "type=„%s“ style_set=„whatever“/>"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786 #: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
#, c-format #, c-format
msgid "" msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not" "User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína" msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794 #: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
#, c-format #, c-format
msgid "Constant \"%s\" has already been defined" msgid "Constant \"%s\" has already been defined"
msgstr "Konštanta „%s“ už je definovaná" msgstr "Konštanta „%s“ už je definovaná"
@@ -1402,7 +1397,7 @@ msgstr "<%s> musí uvádzať buď geometriu alebo rodiča, ktorý má geometriu"
msgid "You must specify a background for an alpha value to be meaningful" msgid "You must specify a background for an alpha value to be meaningful"
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie" msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
#  PM: asi atribút type # PM: asi atribút type
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-parser.c:1264 #: ../src/ui/theme-parser.c:1264
#, fuzzy, c-format #, fuzzy, c-format
@@ -1564,7 +1559,6 @@ msgid "\"%s\" is not a valid value for resize attribute"
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti" msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
# PK: shaded states? to zatvorky daj popis co je resize # PK: shaded states? to zatvorky daj popis co je resize
# PM: skôr "pre stavy maximized (maximalizovaný)/shaded (zatienený)"
#: ../src/ui/theme-parser.c:3147 #: ../src/ui/theme-parser.c:3147
#, fuzzy, c-format #, fuzzy, c-format
msgid "" msgid ""
@@ -1706,172 +1700,221 @@ msgstr "<%s> uvedený dvakrát pre túto tému"
msgid "Failed to find a valid file for theme %s\n" msgid "Failed to find a valid file for theme %s\n"
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n" msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
#~ msgid "Usage: %s\n" #: ../src/ui/theme-viewer.c:99
#~ msgstr "Použitie: %s\n" msgid "_Windows"
msgstr "_Okná"
#~ msgid "_Windows" #: ../src/ui/theme-viewer.c:100
#~ msgstr "_Okná" msgid "_Dialog"
msgstr "_Dialógové okno"
#~ msgid "_Dialog" #: ../src/ui/theme-viewer.c:101
#~ msgstr "_Dialógové okno" msgid "_Modal dialog"
msgstr "_Modálne dialógové okno"
#~ msgid "_Modal dialog" #: ../src/ui/theme-viewer.c:102
#~ msgstr "_Modálne dialógové okno" msgid "_Utility"
msgstr "_Nástroje"
#~ msgid "_Utility" #: ../src/ui/theme-viewer.c:103
#~ msgstr "_Nástroje" msgid "_Splashscreen"
msgstr "Ú_vodná obrazovka"
#~ msgid "_Splashscreen"
#~ msgstr "Ú_vodná obrazovka"
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“? # MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
#~ msgid "_Top dock" #: ../src/ui/theme-viewer.c:104
#~ msgstr "_Horný panel" msgid "_Top dock"
msgstr "_Horný panel"
#~ msgid "_Bottom dock" #: ../src/ui/theme-viewer.c:105
#~ msgstr "_Spodný panel" msgid "_Bottom dock"
msgstr "_Spodný panel"
#~ msgid "_Left dock" #: ../src/ui/theme-viewer.c:106
#~ msgstr "Ľ_avý panel" msgid "_Left dock"
msgstr "Ľ_avý panel"
#~ msgid "_Right dock" #: ../src/ui/theme-viewer.c:107
#~ msgstr "_Pravý panel" msgid "_Right dock"
msgstr "_Pravý panel"
#~ msgid "_All docks" #: ../src/ui/theme-viewer.c:108
#~ msgstr "_Všetky panely" msgid "_All docks"
msgstr "_Všetky panely"
#~ msgid "Des_ktop" #: ../src/ui/theme-viewer.c:109
#~ msgstr "P_racovná plocha" msgid "Des_ktop"
msgstr "P_racovná plocha"
# tooltip # tooltip
#~ msgid "Open another one of these windows" #: ../src/ui/theme-viewer.c:115
#~ msgstr "Otvorí ďalšie z týchto okien" msgid "Open another one of these windows"
msgstr "Otvorí ďalšie z týchto okien"
# PK: prekladat to v uvodzovkach? nahlas bug # PK: prekladat to v uvodzovkach? nahlas bug
# tooltip # tooltip
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-viewer.c:117
#, fuzzy #, fuzzy
#~ msgid "This is a demo button with an 'open' icon" msgid "This is a demo button with an 'open' icon"
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „open“" msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
# tooltip # tooltip
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-viewer.c:119
#, fuzzy #, fuzzy
#~ msgid "This is a demo button with a 'quit' icon" msgid "This is a demo button with a 'quit' icon"
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „quit“" msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
# label # label
#~ msgid "This is a sample message in a sample dialog" #: ../src/ui/theme-viewer.c:248
#~ msgstr "Toto je ukážková správa v ukážkovom dialógovom okne" msgid "This is a sample message in a sample dialog"
msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
# PK: falosna # PK: falosna
#~ msgid "Fake menu item %d\n" #: ../src/ui/theme-viewer.c:328
#~ msgstr "Falošná položka ponuky č. %d\n" #, c-format
msgid "Fake menu item %d\n"
msgstr "Falošná položka ponuky č. %d\n"
#~ msgid "Border-only window" #: ../src/ui/theme-viewer.c:363
#~ msgstr "Okno len s okrajom" msgid "Border-only window"
msgstr "Okno len s okrajom"
#~ msgid "Bar" #: ../src/ui/theme-viewer.c:365
#~ msgstr "Lišta" msgid "Bar"
msgstr "Lišta"
#~ msgid "Normal Application Window" #: ../src/ui/theme-viewer.c:382
#~ msgstr "Normálne aplikačné okno" msgid "Normal Application Window"
msgstr "Normálne aplikačné okno"
#~ msgid "Dialog Box" #: ../src/ui/theme-viewer.c:386
#~ msgstr "Dialógové okno" msgid "Dialog Box"
msgstr "Dialógové okno"
#~ msgid "Modal Dialog Box" #: ../src/ui/theme-viewer.c:390
#~ msgstr "Modálne dialógové okno" msgid "Modal Dialog Box"
msgstr "Modálne dialógové okno"
#~ msgid "Utility Palette" #: ../src/ui/theme-viewer.c:394
#~ msgstr "Paleta nástrojov" msgid "Utility Palette"
msgstr "Paleta nástrojov"
#~ msgid "Torn-off Menu" #: ../src/ui/theme-viewer.c:398
#~ msgstr "Vypnúť ponuku" msgid "Torn-off Menu"
msgstr "Vypnúť ponuku"
#~ msgid "Border" #: ../src/ui/theme-viewer.c:402
#~ msgstr "Okraj" msgid "Border"
msgstr "Okraj"
#~ msgid "Attached Modal Dialog" #: ../src/ui/theme-viewer.c:406
#~ msgstr "Pričlenené modálne okno" msgid "Attached Modal Dialog"
msgstr "Pričlenené modálne okno"
#~ msgid "Button layout test %d" #: ../src/ui/theme-viewer.c:737
#~ msgstr "Test rozloženia tlačidiel č. %d" #, c-format
msgid "Button layout test %d"
msgstr "Test rozloženia tlačidiel č. %d"
# PK: plural forms # PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy #: ../src/ui/theme-viewer.c:766
#~ msgid "%g milliseconds to draw one window frame" #, fuzzy, c-format
#~ msgstr "%g milisekúnd pre vykreslenie jedného rámca okna" msgid "%g milliseconds to draw one window frame"
msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n" #: ../src/ui/theme-viewer.c:811
#~ msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n" #, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
#~ msgid "Error loading theme: %s\n" #: ../src/ui/theme-viewer.c:818
#~ msgstr "Chyba pri načítavaní témy: %s\n" #, c-format
msgid "Error loading theme: %s\n"
msgstr "Chyba pri načítavaní témy: %s\n"
# PK: plural forms # PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy #: ../src/ui/theme-viewer.c:824
#~ msgid "Loaded theme \"%s\" in %g seconds\n" #, fuzzy, c-format
#~ msgstr "Téma „%s“ načítaná za %g send\n" msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Téma „%s“ načítaná za %g sekúnd\n"
# PK: inde titulku, aky je rozdiel # PK: inde titulku, aky je rozdiel
#~ msgid "Normal Title Font" #: ../src/ui/theme-viewer.c:869
#~ msgstr "Obyčajné písmo titulku" msgid "Normal Title Font"
msgstr "Obyčajné písmo titulku"
#~ msgid "Small Title Font" #: ../src/ui/theme-viewer.c:875
#~ msgstr "Malé písmo titulku" msgid "Small Title Font"
msgstr "Malé písmo titulku"
#~ msgid "Large Title Font" #: ../src/ui/theme-viewer.c:881
#~ msgstr "Veľké písmo titulku" msgid "Large Title Font"
msgstr "Veľké písmo titulku"
#~ msgid "Button Layouts" #: ../src/ui/theme-viewer.c:886
#~ msgstr "Rozloženia tlačidiel" msgid "Button Layouts"
msgstr "Rozloženia tlačidiel"
#~ msgid "Benchmark" #: ../src/ui/theme-viewer.c:891
#~ msgstr "Test rýchlosti" msgid "Benchmark"
msgstr "Test rýchlosti"
#~ msgid "Window Title Goes Here" #: ../src/ui/theme-viewer.c:947
#~ msgstr "Sem príde názov okna" msgid "Window Title Goes Here"
msgstr "Sem príde názov okna"
# PK: plural forms # PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy #: ../src/ui/theme-viewer.c:1053
#~ msgid "" #, fuzzy, c-format
#~ "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and " msgid ""
#~ "%g seconds wall clock time including X server resources (%g milliseconds " "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
#~ "per frame)\n" "seconds wall clock time including X server resources (%g milliseconds per "
#~ msgstr "" "frame)\n"
#~ "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na " msgstr ""
#~ "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g " "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
#~ "milisekúnd na rámec)\n" "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g milisekúnd "
"na rámec)\n"
#~ msgid "position expression test returned TRUE but set error" #: ../src/ui/theme-viewer.c:1273
#~ msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu" msgid "position expression test returned TRUE but set error"
msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
#~ msgid "position expression test returned FALSE but didn't set error" #: ../src/ui/theme-viewer.c:1275
#~ msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu" msgid "position expression test returned FALSE but didn't set error"
msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
#~ msgid "Error was expected but none given" #: ../src/ui/theme-viewer.c:1279
#~ msgstr "Bola očakávaná chyba, ale žiadna nenastala" msgid "Error was expected but none given"
msgstr "Bola očakávaná chyba, ale žiadna nenastala"
#~ msgid "Error %d was expected but %d given" #: ../src/ui/theme-viewer.c:1281
#~ msgstr "Bola očakávaná chyba %d, ale nastala %d" #, c-format
msgid "Error %d was expected but %d given"
msgstr "Bola očakávaná chyba %d, ale nastala %d"
#~ msgid "Error not expected but one was returned: %s" #: ../src/ui/theme-viewer.c:1287
#~ msgstr "Chyba nebola očakávaná, ale bola vrátená: %s" #, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
#~ msgid "x value was %d, %d was expected" #: ../src/ui/theme-viewer.c:1291
#~ msgstr "hodnota x bola %d, očakávaná bola %d" #, c-format
msgid "x value was %d, %d was expected"
msgstr "hodnota x bola %d, očakávaná bola %d"
#~ msgid "y value was %d, %d was expected" #: ../src/ui/theme-viewer.c:1294
#~ msgstr "hodnota y bola %d, očakávaná bola %d" #, c-format
msgid "y value was %d, %d was expected"
msgstr "hodnota y bola %d, očakávaná bola %d"
# PK: plural forms # PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987 # JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy #: ../src/ui/theme-viewer.c:1359
#~ msgid "" #, fuzzy, c-format
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n" msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
#~ msgstr "" msgstr ""
#~ "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n" "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"

789
po/sl.po

File diff suppressed because it is too large Load Diff

758
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1132
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,6 @@
<KeyListEntry name="move-to-workspace-4" <KeyListEntry name="move-to-workspace-4"
_description="Move window to workspace 4" /> _description="Move window to workspace 4" />
<KeyListEntry name="move-to-workspace-last"
_description="Move window to last workspace" />
<KeyListEntry name="move-to-workspace-left" <KeyListEntry name="move-to-workspace-left"
_description="Move window one workspace to the left" /> _description="Move window one workspace to the left" />
@@ -80,9 +77,6 @@
<KeyListEntry name="switch-to-workspace-4" <KeyListEntry name="switch-to-workspace-4"
_description="Switch to workspace 4" /> _description="Switch to workspace 4" />
<KeyListEntry name="switch-to-workspace-last"
_description="Switch to last workspace" />
<KeyListEntry name="switch-to-workspace-left" <KeyListEntry name="switch-to-workspace-left"
_description="Move to workspace left" /> _description="Move to workspace left" />

View File

@@ -1,7 +1,7 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905 # Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL: .AUTOPARALLEL:
lib_LTLIBRARIES = libmutter.la lib_LTLIBRARIES = libmutter-wayland.la
SUBDIRS=compositor/plugins SUBDIRS=compositor/plugins
@@ -11,6 +11,7 @@ INCLUDES= \
-DCOGL_ENABLE_EXPERIMENTAL_API \ -DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \ -DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \ $(MUTTER_CFLAGS) \
-I$(top_builddir) \
-I$(srcdir) \ -I$(srcdir) \
-I$(srcdir)/backends \ -I$(srcdir)/backends \
-I$(srcdir)/core \ -I$(srcdir)/core \
@@ -40,24 +41,23 @@ mutter_built_sources = \
gtk-shell-protocol.c \ gtk-shell-protocol.c \
gtk-shell-server-protocol.h \ gtk-shell-server-protocol.h \
xdg-shell-protocol.c \ xdg-shell-protocol.c \
xdg-shell-server-protocol.h xdg-shell-server-protocol.h \
xserver-protocol.c \
xserver-server-protocol.h
wayland_protocols = \ wayland_protocols = \
wayland/protocol/gtk-shell.xml \ wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml wayland/protocol/xdg-shell.xml \
wayland/protocol/xserver.xml
libmutter_la_SOURCES = \ libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \ backends/meta-backend.c \
backends/meta-backend.h \ backends/meta-backend.h \
backends/meta-backend-private.h \
backends/meta-cursor.c \ backends/meta-cursor.c \
backends/meta-cursor.h \ backends/meta-cursor.h \
backends/meta-cursor-private.h \ backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \ backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \ backends/meta-cursor-tracker-private.h \
backends/meta-cursor-renderer.c \
backends/meta-cursor-renderer.h \
backends/meta-display-config-shared.h \
backends/meta-idle-monitor.c \ backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \ backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \ backends/meta-idle-monitor-dbus.c \
@@ -70,24 +70,22 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager-dummy.h \ backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \ backends/edid-parse.c \
backends/edid.h \ backends/edid.h \
backends/native/meta-backend-native.c \ backends/native/meta-cursor-tracker-native.c \
backends/native/meta-backend-native.h \ backends/native/meta-cursor-tracker-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \ backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \ backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \ backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \ backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \ backends/native/meta-weston-launch.c \
backends/native/meta-launcher.h \ backends/native/meta-weston-launch.h \
backends/x11/meta-backend-x11.c \ backends/x11/meta-cursor-tracker-x11.c \
backends/x11/meta-backend-x11.h \ backends/x11/meta-cursor-tracker-x11.h \
backends/x11/meta-idle-monitor-xsync.c \ backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \ backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \ backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \ backends/x11/meta-monitor-manager-xrandr.h \
core/meta-accel-parse.c \ backends/x11/meta-xrandr-shared.h \
core/meta-accel-parse.h \ core/above-tab-keycode.c \
core/barrier.c \ core/barrier.c \
meta/barrier.h \ meta/barrier.h \
core/bell.c \ core/bell.c \
@@ -122,8 +120,6 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor-x11.h \ compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \ compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \ compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-texture-rectangle.c \ compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \ compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \ compositor/meta-texture-tower.c \
@@ -222,9 +218,8 @@ libmutter_la_SOURCES = \
wayland/meta-wayland.c \ wayland/meta-wayland.c \
wayland/meta-wayland.h \ wayland/meta-wayland.h \
wayland/meta-wayland-private.h \ wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \ wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-wayland-data-device.c \ wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \ wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \ wayland/meta-wayland-keyboard.c \
@@ -233,20 +228,20 @@ libmutter_la_SOURCES = \
wayland/meta-wayland-pointer.h \ wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \ wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \ wayland/meta-wayland-seat.h \
wayland/meta-wayland-stage.h \
wayland/meta-wayland-stage.c \
wayland/meta-wayland-surface.c \ wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \ wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \ wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \ wayland/meta-wayland-versions.h \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \ wayland/window-wayland.c \
wayland/window-wayland.h wayland/window-wayland.h
nodist_libmutter_la_SOURCES = \ nodist_libmutter_wayland_la_SOURCES = \
$(mutter_built_sources) $(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined libmutter_wayland_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS) libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will # Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir # be extracted into Mutter-<version>.gir
@@ -284,16 +279,16 @@ libmutterinclude_base_headers = \
libmutterinclude_extra_headers = \ libmutterinclude_extra_headers = \
meta/atomnames.h meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta libmutterincludedir = $(includedir)/mutter-wayland/meta
libmutterinclude_HEADERS = \ libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \ $(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers) $(libmutterinclude_extra_headers)
bin_PROGRAMS=mutter bin_PROGRAMS=mutter-wayland
mutter_SOURCES = core/mutter.c mutter_wayland_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
bin_PROGRAMS+=mutter-launch bin_PROGRAMS+=mutter-launch
@@ -328,15 +323,15 @@ typelib_DATA = Meta-$(api_version).typelib
INTROSPECTION_GIRS = Meta-$(api_version).gir INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la Meta-$(api_version).gir: libmutter-wayland.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0 @META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter @META_GIR@_EXPORT_PACKAGES = libmutter-wayland
@META_GIR@_CFLAGS = $(INCLUDES) @META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la @META_GIR@_LIBS = libmutter-wayland.la
@META_GIR@_FILES = \ @META_GIR@_FILES = \
mutter-enum-types.h \ mutter-enum-types.h \
$(libmutterinclude_base_headers) \ $(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES)) $(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error @META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif endif
@@ -347,14 +342,14 @@ testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
@INTLTOOL_DESKTOP_RULE@ @INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter.desktop.in desktopfiles_in_files=mutter-wayland.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop) desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files) desktopfiles_DATA = $(desktopfiles_files)
@@ -375,7 +370,7 @@ convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert convert_DATA = mutter-schemas.convert
CLEANFILES = \ CLEANFILES = \
mutter.desktop \ mutter-wayland.desktop \
mutter-wm.desktop \ mutter-wm.desktop \
org.gnome.mutter.gschema.xml \ org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \ org.gnome.mutter.wayland.gschema.xml \
@@ -386,7 +381,7 @@ CLEANFILES = \
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc pkgconfig_DATA = libmutter-wayland.pc
EXTRA_DIST=$(desktopfiles_files) \ EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \ $(wmproperties_files) \
@@ -398,7 +393,7 @@ EXTRA_DIST=$(desktopfiles_files) \
org.gnome.mutter.gschema.xml.in \ org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \ org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \ mutter-schemas.convert \
libmutter.pc.in \ libmutter-wayland.pc.in \
mutter-enum-types.h.in \ mutter-enum-types.h.in \
mutter-enum-types.c.in \ mutter-enum-types.c.in \
org.gnome.Mutter.DisplayConfig.xml \ org.gnome.Mutter.DisplayConfig.xml \

View File

@@ -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 */

View File

@@ -25,193 +25,14 @@
#include "config.h" #include "config.h"
#include "meta-backend.h" #include "meta-backend.h"
#include "meta-backend-private.h" #include <meta/main.h>
#include <gdk/gdkx.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include "backends/x11/meta-backend-x11.h" #include "backends/native/meta-weston-launch.h"
#include "backends/native/meta-backend-native.h" #include <meta/util.h>
static MetaBackend *_backend;
MetaBackend *
meta_get_backend (void)
{
return _backend;
}
struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT);
static void
meta_backend_finalize (GObject *object)
{
MetaBackend *backend = META_BACKEND (object);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int i;
g_clear_object (&priv->monitor_manager);
for (i = 0; i <= backend->device_id_max; i++)
{
if (backend->device_monitors[i])
g_object_unref (backend->device_monitors[i]);
}
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->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);
}
/* Mutter is responsible for pulling events off the X queue, so Clutter /* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls * doesn't need (and shouldn't) run its normal event source which polls
@@ -261,12 +82,37 @@ static GSourceFuncs event_funcs = {
event_dispatch event_dispatch
}; };
static MetaLauncher *launcher;
void void
meta_clutter_init (void) meta_clutter_init (void)
{ {
GSource *source; GSource *source;
meta_create_backend (); /* When running as an X11 compositor, we install our own event filter and
* pass events to Clutter explicitly, so we need to prevent Clutter from
* handling our events.
*
* However, when running as a Wayland compostior under X11 nested, Clutter
* Clutter needs to see events related to its own window. We need to
* eventually replace this with a proper frontend / backend split: Clutter
* under nested is connecting to the "host X server" to get its events it
* needs to put up a window, and GTK+ is connecting to the "inner X server".
* The two would the same in the X11 compositor case, but not when running
* XWayland as a Wayland compositor.
*/
if (!meta_is_wayland_compositor ())
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
}
/* If we're running on bare metal, we're a display server,
* so start talking to weston-launch. */
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
launcher = meta_launcher_new ();
#endif
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n"); g_error ("Unable to initialize Clutter.\n");
@@ -274,6 +120,38 @@ meta_clutter_init (void)
source = g_source_new (&event_funcs, sizeof (GSource)); source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL); g_source_attach (source, NULL);
g_source_unref (source); g_source_unref (source);
}
meta_backend_post_init (_backend);
gboolean
meta_activate_vt (int vt, GError **error)
{
if (launcher)
return meta_launcher_activate_vt (launcher, vt, error);
else
{
g_debug ("Ignoring VT switch keybinding, not running as display server");
return TRUE;
}
}
/**
* meta_activate_session:
*
* Tells mutter to activate the session. When mutter is a
* Wayland compositor, this tells logind to switch over to
* the new session.
*/
gboolean
meta_activate_session (void)
{
GError *error = NULL;
if (!meta_launcher_activate_vt (launcher, -1, &error))
{
g_warning ("Could not activate session: %s\n", error->message);
g_error_free (error);
return FALSE;
}
return TRUE;
} }

View File

@@ -27,29 +27,8 @@
#include <glib-object.h> #include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#include "meta-monitor-manager.h"
#include "meta-cursor-renderer.h"
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass;
GType meta_backend_get_type (void);
MetaBackend * meta_get_backend (void);
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_clutter_init (void); void meta_clutter_init (void);
gboolean meta_activate_vt (int vt, GError **error);
#endif /* META_BACKEND_H */ #endif /* META_BACKEND_H */

View File

@@ -27,6 +27,11 @@
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include <gbm.h> #include <gbm.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <wayland-server.h>
typedef struct { typedef struct {
CoglTexture2D *texture; CoglTexture2D *texture;
struct gbm_bo *bo; struct gbm_bo *bo;
@@ -36,7 +41,6 @@ typedef struct {
struct _MetaCursorReference { struct _MetaCursorReference {
int ref_count; int ref_count;
MetaCursor cursor;
MetaCursorImage image; MetaCursorImage image;
}; };
@@ -48,4 +52,26 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x, int *hot_x,
int *hot_y); 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 */ #endif /* META_CURSOR_PRIVATE_H */

View File

@@ -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;
}

View File

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

View File

@@ -24,17 +24,12 @@
#include <meta/meta-cursor-tracker.h> #include <meta/meta-cursor-tracker.h>
#include <wayland-server.h> #include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h" #include "meta-cursor.h"
#include "meta-cursor-renderer.h"
struct _MetaCursorTracker { struct _MetaCursorTracker {
GObject parent_instance; GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing; gboolean is_showing;
/* The cursor tracker stores the cursor for the current grab /* The cursor tracker stores the cursor for the current grab
@@ -51,9 +46,15 @@ struct _MetaCursorTracker {
*/ */
MetaCursorReference *displayed_cursor; 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; MetaCursorReference *grab_cursor;
/* Wayland clients can set a NULL buffer as their cursor /* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything. * explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to * So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean. * determine an unset window cursor; we need an extra boolean.
@@ -62,14 +63,39 @@ struct _MetaCursorTracker {
MetaCursorReference *window_cursor; MetaCursorReference *window_cursor;
MetaCursorReference *root_cursor; MetaCursorReference *root_cursor;
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
}; };
struct _MetaCursorTrackerClass { struct _MetaCursorTrackerClass {
GObjectClass parent_class; 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, void _meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
XEvent *xevent); gboolean has_cursor,
MetaCursorReference *cursor);
void _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker, void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor); 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_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor); MetaCursorReference *cursor);
MetaCursorReference *
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker, meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
int new_x, MetaCursor cursor);
int new_y); MetaCursorReference *
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif #endif

View File

@@ -33,21 +33,12 @@
#include <meta/util.h> #include <meta/util.h>
#include <meta/errors.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-private.h"
#include "meta-cursor-tracker-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 "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum { enum {
@@ -57,43 +48,6 @@ enum {
static guint signals[LAST_SIGNAL]; 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 static void
meta_cursor_tracker_init (MetaCursorTracker *self) meta_cursor_tracker_init (MetaCursorTracker *self)
{ {
@@ -109,15 +63,43 @@ static void
meta_cursor_tracker_finalize (GObject *object) meta_cursor_tracker_finalize (GObject *object)
{ {
MetaCursorTracker *self = META_CURSOR_TRACKER (object); MetaCursorTracker *self = META_CURSOR_TRACKER (object);
int i;
if (self->displayed_cursor) if (self->displayed_cursor)
meta_cursor_reference_unref (self->displayed_cursor); meta_cursor_reference_unref (self->displayed_cursor);
if (self->root_cursor) if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor); meta_cursor_reference_unref (self->root_cursor);
for (i = 0; i < META_CURSOR_LAST; i++)
if (self->theme_cursors[i])
meta_cursor_reference_unref (self->theme_cursors[i]);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object); 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 static void
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass) 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; 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", signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
@@ -133,52 +120,6 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
G_TYPE_NONE, 0); 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: * meta_cursor_tracker_get_for_screen:
* @screen: the #MetaScreen * @screen: the #MetaScreen
@@ -190,123 +131,18 @@ static MetaCursorTracker *_cursor_tracker;
MetaCursorTracker * MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen) meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{ {
if (!_cursor_tracker) MetaCursorTracker *self;
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker; if (screen->cursor_tracker)
} return screen->cursor_tracker;
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 (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
return FALSE; self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL);
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;
}
else else
{ self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL);
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); screen->cursor_tracker = self;
cursor_data = (guint8 *)cursor_words; return self;
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);
} }
/** /**
@@ -319,11 +155,10 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{ {
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL); g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (!meta_is_wayland_compositor ()) META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
ensure_xfixes_cursor (tracker);
if (tracker->displayed_cursor) if (tracker->current_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL); return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL);
else else
return NULL; return NULL;
} }
@@ -342,11 +177,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
{ {
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (!meta_is_wayland_compositor ()) META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
ensure_xfixes_cursor (tracker);
if (tracker->displayed_cursor) if (tracker->current_cursor)
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y); meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y);
else else
{ {
if (x) 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 void
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker, meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor) MetaCursorReference *cursor)
@@ -364,20 +224,7 @@ meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
if (cursor) if (cursor)
tracker->grab_cursor = meta_cursor_reference_ref (cursor); tracker->grab_cursor = meta_cursor_reference_ref (cursor);
sync_cursor (tracker); _meta_cursor_tracker_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);
} }
void void
@@ -388,57 +235,53 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
if (cursor) if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (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 void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker, _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker)
int new_x,
int new_y)
{ {
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 META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker);
get_pointer_position_gdk (int *x, }
int *y,
int *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
GdkScreen *gscreen;
gmanager = gdk_display_get_device_manager (gdk_display_get_default ()); if (tracker->current_cursor != current_cursor)
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); {
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); g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
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);
} }
void void
@@ -447,15 +290,7 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *y, int *y,
ClutterModifierType *mods) ClutterModifierType *mods)
{ {
/* We can't use the clutter interface when not running as a wayland compositor, META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods);
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);
} }
void void
@@ -466,23 +301,51 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
return; return;
tracker->is_showing = visible; tracker->is_showing = visible;
if (meta_is_wayland_compositor ()) _meta_cursor_tracker_sync_cursor (tracker);
{
sync_cursor (tracker);
}
else
{
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
}
} }
MetaCursorReference * 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;
} }

View File

@@ -27,17 +27,23 @@
#include "display-private.h" #include "display-private.h"
#include "screen-private.h" #include "screen-private.h"
#include "meta-backend.h" #include "meta-cursor-tracker-private.h"
#include "backends/native/meta-cursor-renderer-native.h"
#include <string.h> #include <string.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <cogl/cogl-wayland-server.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 * MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self) meta_cursor_reference_ref (MetaCursorReference *self)
{ {
@@ -71,77 +77,141 @@ meta_cursor_reference_unref (MetaCursorReference *self)
meta_cursor_reference_free (self); meta_cursor_reference_free (self);
} }
static const char * static void
translate_meta_cursor (MetaCursor cursor) translate_meta_cursor (MetaCursor cursor,
guint *glyph_out,
const char **name_out)
{ {
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor) switch (cursor)
{ {
case META_CURSOR_DEFAULT: case META_CURSOR_DEFAULT:
return "left_ptr"; glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE: case META_CURSOR_NORTH_RESIZE:
return "top_side"; glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE: case META_CURSOR_SOUTH_RESIZE:
return "bottom_side"; glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE: case META_CURSOR_WEST_RESIZE:
return "left_side"; glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE: case META_CURSOR_EAST_RESIZE:
return "right_side"; glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE: case META_CURSOR_SE_RESIZE:
return "bottom_right_corner"; glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE: case META_CURSOR_SW_RESIZE:
return "bottom_left_corner"; glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE: case META_CURSOR_NE_RESIZE:
return "top_right_corner"; glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE: case META_CURSOR_NW_RESIZE:
return "top_left_corner"; glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW: case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
return "fleur"; glyph = XC_fleur;
break;
case META_CURSOR_BUSY: case META_CURSOR_BUSY:
return "watch"; glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG: case META_CURSOR_DND_IN_DRAG:
return "dnd-none"; name = "dnd-none";
break;
case META_CURSOR_DND_MOVE: case META_CURSOR_DND_MOVE:
return "dnd-move"; name = "dnd-move";
break;
case META_CURSOR_DND_COPY: case META_CURSOR_DND_COPY:
return "dnd-copy"; name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET: case META_CURSOR_DND_UNSUPPORTED_TARGET:
return "dnd-none"; name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND: case META_CURSOR_POINTING_HAND:
return "hand2"; glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR: case META_CURSOR_CROSSHAIR:
return "crosshair"; glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM: case META_CURSOR_IBEAM:
return "xterm"; glyph = XC_xterm;
break;
default: default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break; break;
} }
g_assert_not_reached (); *glyph_out = glyph;
*name_out = name;
}
static Cursor
load_cursor_on_server (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph;
const char *name;
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
} }
Cursor Cursor
meta_cursor_create_x_cursor (Display *xdisplay, meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor) MetaCursor cursor)
{ {
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); return load_cursor_on_server (display, cursor);
} }
static XcursorImage * static XcursorImage *
load_cursor_on_client (MetaCursor cursor) load_cursor_on_client (MetaDisplay *display,
MetaCursor cursor)
{ {
return XcursorLibraryLoadImage (translate_meta_cursor (cursor), XcursorImage *image;
meta_prefs_get_cursor_theme (), guint glyph;
meta_prefs_get_cursor_size ()); const char *name;
const char *theme = XcursorGetTheme (display->xdisplay);
int size = XcursorGetDefaultSize (display->xdisplay);
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
image = XcursorLibraryLoadImage (name, theme, size);
else
image = XcursorShapeLoadImage (glyph, theme, size);
return image;
} }
static void XcursorImage *
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, meta_display_load_x_cursor (MetaDisplay *display,
MetaCursorImage *image, MetaCursor cursor)
uint8_t *pixels, {
int width, return load_cursor_on_client (display, cursor);
int height, }
int rowstride,
uint32_t gbm_format) 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) 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]; uint8_t buf[4 * 64 * 64];
int i; int i;
image->bo = gbm_bo_create (gbm, 64, 64, cursor->image.bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4); 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 else
meta_warning ("HW cursor for format %d not supported\n", gbm_format); meta_warning ("HW cursor for format %d not supported\n", gbm_format);
} }
static struct gbm_device * void
get_gbm_device (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 (); /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); 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)) cursor->image.bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer)); buffer, GBM_BO_USE_CURSOR_64X64);
else if (!cursor->image.bo)
return NULL; meta_warning ("Importing HW cursor from wl_buffer failed\n");
} }
static void MetaCursorReference *
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image, meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image)
XcursorImage *xc_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; int width, height, rowstride;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend; ClutterBackend *clutter_backend;
CoglContext *cogl_context; CoglContext *cogl_context;
struct gbm_device *gbm;
cursor = meta_cursor_reference_new ();
width = xc_image->width; width = xc_image->width;
height = xc_image->height; height = xc_image->height;
rowstride = width * 4; rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN #if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else #else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif #endif
image->hot_x = xc_image->xhot; cursor->image.hot_x = xc_image->xhot;
image->hot_y = xc_image->yhot; cursor->image.hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend (); clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend); cogl_context = clutter_backend_get_cogl_context (clutter_backend);
image->texture = cogl_texture_2d_new_from_data (cogl_context, cursor->image.texture = cogl_texture_2d_new_from_data (cogl_context,
width, height, width, height,
cogl_format, cogl_format,
rowstride, rowstride,
(uint8_t *) xc_image->pixels, (uint8_t *) xc_image->pixels,
NULL); NULL);
return cursor;
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");
}
}
} }
MetaCursorReference * MetaCursorReference *
@@ -332,13 +358,21 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x, int hot_x,
int hot_y) int hot_y)
{ {
MetaCursorReference *self; MetaCursorReference *cursor;
ClutterBackend *backend;
CoglContext *cogl_context;
self = g_slice_new0 (MetaCursorReference); cursor = meta_cursor_reference_new ();
self->ref_count = 1;
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
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 * CoglTexture *
@@ -364,9 +398,3 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
*hot_y = cursor->image.hot_y; *hot_y = cursor->image.hot_y;
return cursor->image.bo; return cursor->image.bo;
} }
MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
{
return cursor->cursor;
}

View File

@@ -27,18 +27,4 @@ typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor); MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor); void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/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 */ #endif /* META_CURSOR_H */

View File

@@ -38,7 +38,8 @@
#include <meta/meta-idle-monitor.h> #include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h" #include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h" #include "meta-idle-monitor-dbus.h"
#include "meta-backend.h" #include "backends/x11/meta-idle-monitor-xsync.h"
#include "backends/native/meta-idle-monitor-native.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
@@ -53,6 +54,9 @@ static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
void void
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
{ {
@@ -156,6 +160,36 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
{ {
} }
static GType
get_idle_monitor_type (void)
{
if (meta_is_wayland_compositor ())
return META_TYPE_IDLE_MONITOR_NATIVE;
else
return META_TYPE_IDLE_MONITOR_XSYNC;
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
"device-id", device_id,
NULL);
device_id_max = MAX (device_id_max, device_id);
}
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (int device_id)
{
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
/** /**
* meta_idle_monitor_get_core: * meta_idle_monitor_get_core:
* *
@@ -166,8 +200,8 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
MetaIdleMonitor * MetaIdleMonitor *
meta_idle_monitor_get_core (void) meta_idle_monitor_get_core (void)
{ {
MetaBackend *backend = meta_get_backend (); ensure_device_monitor (0);
return meta_backend_get_idle_monitor (backend, 0); return device_monitors[0];
} }
/** /**
@@ -181,8 +215,10 @@ meta_idle_monitor_get_core (void)
MetaIdleMonitor * MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id) meta_idle_monitor_get_for_device (int device_id)
{ {
MetaBackend *backend = meta_get_backend (); g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
return meta_backend_get_idle_monitor (backend, device_id);
ensure_device_monitor (device_id);
return device_monitors[device_id];
} }
static MetaIdleMonitorWatch * static MetaIdleMonitorWatch *
@@ -316,3 +352,16 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{ {
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor); return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
} }
void
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
{
int i;
if (meta_is_wayland_compositor ())
return;
for (i = 0; i <= device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}

View File

@@ -840,9 +840,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaConfiguration key; MetaConfiguration key;
MetaConfiguration *stored; MetaConfiguration *stored;
if (n_outputs == 0)
return NULL;
make_config_key (&key, outputs, n_outputs, -1); make_config_key (&key, outputs, n_outputs, -1);
stored = g_hash_table_lookup (self->configs, &key); stored = g_hash_table_lookup (self->configs, &key);
@@ -1250,12 +1247,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height); meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
if (n_outputs == 0)
{
meta_verbose ("No output connected, not applying configuration\n");
return;
}
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height); default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL) if (default_config != NULL)

View File

@@ -36,8 +36,9 @@
#include "util-private.h" #include "util-private.h"
#include <meta/errors.h> #include <meta/errors.h>
#include "meta-monitor-config.h" #include "meta-monitor-config.h"
#include "backends/native/meta-monitor-manager-kms.h"
#include "backends/x11/meta-monitor-manager-xrandr.h" #include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend.h" #include "meta-monitor-manager-dummy.h"
enum { enum {
CONFIRM_DISPLAY_CHANGE, CONFIRM_DISPLAY_CHANGE,
@@ -167,6 +168,58 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE); manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
} }
static GType
get_default_backend (void)
{
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_MONITOR_MANAGER_KMS;
#endif
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
/* If we're a Wayland compositor using the X11 backend,
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return META_TYPE_MONITOR_MANAGER_DUMMY;
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
}
#endif
#if defined(CLUTTER_WINDOWING_WAYLAND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
{
/* Use the dummy implementation on Wayland for now.
* In the future, we should support wl_fullscreen_output
* which will have CRTC management in the protocol. */
return META_TYPE_MONITOR_MANAGER_DUMMY;
}
#endif
g_assert_not_reached ();
}
static MetaMonitorManager *
meta_monitor_manager_new (void)
{
const char *env;
GType type;
env = g_getenv ("META_DEBUG_MULTIMONITOR");
if (env == NULL)
type = get_default_backend ();
else if (strcmp (env, "xrandr") == 0)
type = META_TYPE_MONITOR_MANAGER_XRANDR;
else
type = META_TYPE_MONITOR_MANAGER;
return g_object_new (type, NULL);
}
static void static void
meta_monitor_manager_constructed (GObject *object) meta_monitor_manager_constructed (GObject *object)
{ {
@@ -483,13 +536,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})", g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */ i, /* ID */
(gint64)crtc->crtc_id, crtc->crtc_id,
(int)crtc->rect.x, (int)crtc->rect.x,
(int)crtc->rect.y, (int)crtc->rect.y,
(int)crtc->rect.width, (int)crtc->rect.width,
(int)crtc->rect.height, (int)crtc->rect.height,
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1), (int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
(guint32)crtc->transform, crtc->transform,
&transforms, &transforms,
NULL /* properties */); NULL /* properties */);
} }
@@ -560,7 +613,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */ i, /* ID */
(gint64)output->output_id, output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1), (int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs, &crtcs,
output->name, output->name,
@@ -575,9 +628,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&mode_builder, "(uxuud)", g_variant_builder_add (&mode_builder, "(uxuud)",
i, /* ID */ i, /* ID */
(gint64)mode->mode_id, mode->mode_id,
(guint32)mode->width, mode->width,
(guint32)mode->height, mode->height,
(double)mode->refresh_rate); (double)mode->refresh_rate);
} }
@@ -878,7 +931,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
if (persistent) if (persistent)
{ {
manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager); manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager);
g_source_set_name_by_id (manager->persistent_timeout_id, "[mutter] save_config_timeout");
g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0); g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0);
} }
@@ -1126,12 +1178,20 @@ initialize_dbus_interface (MetaMonitorManager *manager)
g_object_unref); g_object_unref);
} }
static MetaMonitorManager *global_monitor_manager;
void
meta_monitor_manager_initialize (void)
{
global_monitor_manager = meta_monitor_manager_new ();
}
MetaMonitorManager * MetaMonitorManager *
meta_monitor_manager_get (void) meta_monitor_manager_get (void)
{ {
MetaBackend *backend = meta_get_backend (); g_assert (global_monitor_manager != NULL);
return meta_backend_get_monitor_manager (backend); return global_monitor_manager;
} }
MetaMonitorInfo * MetaMonitorInfo *
@@ -1217,3 +1277,16 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
g_free (old_monitor_infos); g_free (old_monitor_infos);
} }
gboolean
meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
{
MetaMonitorManagerClass *klass;
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->handle_xevent)
return klass->handle_xevent (manager, event);
else
return FALSE;
}

View File

@@ -46,7 +46,6 @@
#include "meta-display-config-shared.h" #include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h" #include "meta-dbus-display-config.h"
#include "meta-cursor.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass; typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager; typedef struct _MetaMonitorManager MetaMonitorManager;
@@ -124,7 +123,8 @@ struct _MetaCRTC
/* Used when changing configuration */ /* Used when changing configuration */
gboolean is_dirty; gboolean is_dirty;
MetaCursorReference *cursor; /* Updated by MetaCursorTracker */
gboolean has_hw_cursor;
}; };
struct _MetaMonitorMode struct _MetaMonitorMode
@@ -285,10 +285,14 @@ struct _MetaMonitorManagerClass
unsigned short *, unsigned short *,
unsigned short *, unsigned short *,
unsigned short *); unsigned short *);
gboolean (*handle_xevent) (MetaMonitorManager *,
XEvent *);
}; };
GType meta_monitor_manager_get_type (void); GType meta_monitor_manager_get_type (void);
void meta_monitor_manager_initialize (void);
MetaMonitorManager *meta_monitor_manager_get (void); MetaMonitorManager *meta_monitor_manager_get (void);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager); void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
@@ -309,6 +313,9 @@ void meta_monitor_manager_get_resources (MetaMonitorManager
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager); int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event);
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager, void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
int *width, int *width,
int *height); int *height);

View File

@@ -1,235 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include <meta/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, &current);
/* if we're trying to escape, clamp to the CRTC we're coming from */
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
float nx, ny;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = left + monitor->rect.height;
nx = current.x;
ny = current.y;
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
{
if (*x < left)
*x = left;
if (*x >= right)
*x = right - 1;
if (*y < top)
*y = top;
if (*y >= bottom)
*y = bottom - 1;
return;
}
}
}
static void
pointer_constrain_callback (ClutterInputDevice *device,
guint32 time,
float *new_x,
float *new_y,
gpointer user_data)
{
MetaMonitorManager *monitor_manager;
MetaMonitorInfo *monitors;
unsigned int n_monitors;
gboolean ret;
monitor_manager = meta_monitor_manager_get ();
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
/* if we're moving inside a monitor, we're fine */
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
if (ret == TRUE)
return;
/* if we're trying to escape, clamp to the CRTC we're coming from */
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
}
static void
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;
}

View File

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

View File

@@ -1,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);
}

View File

@@ -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 */

View 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));
}

View 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 */

View File

@@ -17,27 +17,35 @@
* 02111-1307, USA. * 02111-1307, USA.
*/ */
#include "config.h" #include <config.h>
#include "meta-launcher.h"
#include "weston-launch.h"
#include <gio/gio.h>
#include <gio/gunixfdmessage.h> #include <gio/gunixfdmessage.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <clutter/egl/clutter-egl.h> #include <clutter/egl/clutter-egl.h>
#include <clutter/evdev/clutter-evdev.h> #include <clutter/evdev/clutter-evdev.h>
#include <glib.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.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 "wayland/meta-wayland-private.h"
#include "backends/meta-backend.h" #include "meta-cursor-tracker-private.h"
#include "meta-cursor-renderer-native.h" #include "meta-cursor-tracker-native.h"
#include "meta-weston-launch.h"
struct _MetaLauncher struct _MetaLauncher
{ {
@@ -64,11 +72,11 @@ request_vt_switch_idle (gpointer user_data)
static gboolean static gboolean
send_message_to_wl (MetaLauncher *self, send_message_to_wl (MetaLauncher *self,
void *message, void *message,
gsize size, gsize size,
GSocketControlMessage *out_cmsg, GSocketControlMessage *out_cmsg,
GSocketControlMessage **in_cmsg, GSocketControlMessage **in_cmsg,
GError **error) GError **error)
{ {
struct weston_launcher_reply reply; struct weston_launcher_reply reply;
GInputVector in_iov = { &reply, sizeof (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[0] = out_cmsg;
out_all_cmsg[1] = NULL; out_all_cmsg[1] = NULL;
if (g_socket_send_message (self->weston_launch, NULL, if (g_socket_send_message (self->weston_launch, NULL,
&out_iov, 1, &out_iov, 1,
out_all_cmsg, -1, out_all_cmsg, -1,
flags, NULL, error) != (gssize)size) flags, NULL, error) != (gssize)size)
return FALSE; return FALSE;
if (g_socket_receive_message (self->weston_launch, NULL, if (g_socket_receive_message (self->weston_launch, NULL,
&in_iov, 1, &in_iov, 1,
&in_all_cmsg, NULL, &in_all_cmsg, NULL,
&flags, NULL, error) != sizeof (reply)) &flags, NULL, error) != sizeof (reply))
return FALSE; return FALSE;
while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode) while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
{ {
guint id;
/* There were events queued */ /* There were events queued */
g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT); 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); g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
switch (reply.header.opcode) switch (reply.header.opcode)
{ {
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH: case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
id = g_idle_add (request_vt_switch_idle, self); g_idle_add (request_vt_switch_idle, self);
g_source_set_name_by_id (id, "[mutter] request_vt_switch_idle"); break;
break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
if (g_socket_receive_message (self->weston_launch, NULL, if (g_socket_receive_message (self->weston_launch, NULL,
&in_iov, 1, &in_iov, 1,
NULL, NULL, NULL, NULL,
&flags, NULL, error) != sizeof (reply)) &flags, NULL, error) != sizeof (reply))
return FALSE; return FALSE;
} }
if (reply.ret != 0) if (reply.ret != 0)
{ {
if (reply.ret == -1) if (reply.ret == -1)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Got failure from weston-launch"); "Got failure from weston-launch");
else else
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-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)); "Got failure from weston-launch: %s", strerror (-reply.ret));
for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++) 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); g_free (in_all_cmsg);
return FALSE; return FALSE;
@@ -145,7 +150,7 @@ send_message_to_wl (MetaLauncher *self,
if (in_all_cmsg && in_all_cmsg[0]) if (in_all_cmsg && in_all_cmsg[0])
{ {
for (i = 1; in_all_cmsg[i]; i++) 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]; *in_cmsg = in_all_cmsg[0];
} }
@@ -194,7 +199,7 @@ meta_launcher_open_device (MetaLauncher *self,
} }
static void static void
session_unpause (void) meta_launcher_enter (MetaLauncher *launcher)
{ {
ClutterBackend *backend; ClutterBackend *backend;
CoglContext *cogl_context; CoglContext *cogl_context;
@@ -209,29 +214,27 @@ session_unpause (void)
{ {
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); 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 /* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to * in case nothing else queued one for us, and force the cursor to
* update. */ * update. */
clutter_actor_queue_redraw (compositor->stage); 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 static void
session_pause (void) meta_launcher_leave (MetaLauncher *launcher)
{ {
clutter_evdev_release_devices (); clutter_evdev_release_devices ();
} }
static int static int
on_evdev_device_open (const char *path, on_evdev_device_open (const char *path,
int flags, int flags,
gpointer user_data, gpointer user_data,
GError **error) GError **error)
{ {
MetaLauncher *launcher = user_data; MetaLauncher *launcher = user_data;
@@ -239,8 +242,8 @@ on_evdev_device_open (const char *path,
} }
static void static void
on_evdev_device_close (int fd, on_evdev_device_close (int fd,
gpointer user_data) gpointer user_data)
{ {
close (fd); close (fd);
} }
@@ -251,8 +254,6 @@ handle_vt_enter (MetaLauncher *launcher)
g_assert (launcher->vt_switched); g_assert (launcher->vt_switched);
g_main_loop_quit (launcher->nested_loop); g_main_loop_quit (launcher->nested_loop);
session_unpause ();
} }
static void static void
@@ -262,7 +263,7 @@ handle_request_vt_switch (MetaLauncher *launcher)
GError *error; GError *error;
gboolean ok; gboolean ok;
session_pause (); meta_launcher_leave (launcher);
message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH; message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
@@ -286,13 +287,13 @@ handle_request_vt_switch (MetaLauncher *launcher)
g_assert (launcher->vt_switched); g_assert (launcher->vt_switched);
launcher->vt_switched = FALSE; launcher->vt_switched = FALSE;
session_unpause (); meta_launcher_enter (launcher);
} }
static gboolean static gboolean
on_socket_readable (GSocket *socket, on_socket_readable (GSocket *socket,
GIOCondition condition, GIOCondition condition,
gpointer user_data) gpointer user_data)
{ {
MetaLauncher *launcher = user_data; MetaLauncher *launcher = user_data;
struct weston_launcher_event event; struct weston_launcher_event event;
@@ -342,9 +343,7 @@ MetaLauncher *
meta_launcher_new (void) meta_launcher_new (void)
{ {
MetaLauncher *self = g_slice_new0 (MetaLauncher); MetaLauncher *self = g_slice_new0 (MetaLauncher);
GError *error = NULL;
int launch_fd; int launch_fd;
int kms_fd;
launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK"); launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
if (launch_fd < 0) if (launch_fd < 0)
@@ -365,15 +364,22 @@ meta_launcher_new (void)
g_source_attach (self->inner_source, self->nested_context); g_source_attach (self->inner_source, self->nested_context);
g_source_unref (self->inner_source); 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, clutter_evdev_set_device_callbacks (on_evdev_device_open,
on_evdev_device_close, on_evdev_device_close,
self); 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; return self;
} }
@@ -391,17 +397,10 @@ meta_launcher_free (MetaLauncher *launcher)
g_slice_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 gboolean
meta_launcher_activate_vt (MetaLauncher *launcher, meta_launcher_activate_vt (MetaLauncher *launcher,
signed char vt, signed char vt,
GError **error) GError **error)
{ {
struct weston_launcher_activate_vt message; 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); return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
} }

View File

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

View File

@@ -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;
}

View File

@@ -1,56 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_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 */

View 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;
}

View 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 */

View File

@@ -25,7 +25,8 @@
#include "meta-idle-monitor-xsync.h" #include "meta-idle-monitor-xsync.h"
#include "meta-idle-monitor-private.h" #include "meta-idle-monitor-private.h"
#include "meta-backend-x11.h" #include <meta/util.h>
#include "display-private.h"
#include <string.h> #include <string.h>
@@ -190,9 +191,10 @@ static void
meta_idle_monitor_xsync_constructed (GObject *object) meta_idle_monitor_xsync_constructed (GObject *object)
{ {
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object); MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
monitor_xsync->display = meta_backend_x11_get_xdisplay (backend); g_assert (!meta_is_wayland_compositor ());
monitor_xsync->display = meta_get_display ()->xdisplay;
init_xsync (monitor_xsync); init_xsync (monitor_xsync);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object); G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
@@ -289,10 +291,7 @@ meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm); g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec) if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
{ watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
}
} }
else else
{ {

View File

@@ -44,4 +44,6 @@ GType meta_idle_monitor_xsync_get_type (void);
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor, void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *xevent); XSyncAlarmNotifyEvent *xevent);
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
#endif /* META_IDLE_MONITOR_XSYNC_H */ #endif /* META_IDLE_MONITOR_XSYNC_H */

View File

@@ -36,7 +36,6 @@
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h> #include <X11/extensions/dpms.h>
#include "meta-backend-x11.h"
#include <meta/main.h> #include <meta/main.h>
#include <meta/errors.h> #include <meta/errors.h>
#include "edid.h" #include "edid.h"
@@ -142,16 +141,16 @@ static gboolean
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr, output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) MetaOutput *output)
{ {
MetaDisplay *display = meta_get_display ();
gboolean value; gboolean value;
Atom atom, actual_type; Atom actual_type;
int actual_format; int actual_format;
unsigned long nitems, bytes_after; unsigned long nitems, bytes_after;
unsigned char *buffer; unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRGetOutputProperty (manager_xrandr->xdisplay, XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id, (XID)output->output_id,
atom, display->atom__MUTTER_PRESENTATION_OUTPUT,
0, G_MAXLONG, False, False, XA_CARDINAL, 0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format, &actual_type, &actual_format,
&nitems, &bytes_after, &buffer); &nitems, &bytes_after, &buffer);
@@ -178,16 +177,16 @@ static int
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr, output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) MetaOutput *output)
{ {
MetaDisplay *display = meta_get_display ();
gboolean value; gboolean value;
Atom atom, actual_type; Atom actual_type;
int actual_format; int actual_format;
unsigned long nitems, bytes_after; unsigned long nitems, bytes_after;
unsigned char *buffer; unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay, XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id, (XID)output->output_id,
atom, display->atom_BACKLIGHT,
0, G_MAXLONG, False, False, XA_INTEGER, 0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format, &actual_type, &actual_format,
&nitems, &bytes_after, &buffer); &nitems, &bytes_after, &buffer);
@@ -206,13 +205,14 @@ static void
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr, output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) MetaOutput *output)
{ {
Atom atom; MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info; XRRPropertyInfo *info;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id, (XID)output->output_id,
atom); display->atom_BACKLIGHT);
meta_error_trap_pop (display);
if (info == NULL) if (info == NULL)
{ {
@@ -314,13 +314,14 @@ static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr, output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id) XID output_id)
{ {
Atom atom; MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info; XRRPropertyInfo *info;
gboolean result = FALSE; gboolean result = FALSE;
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False); meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id, info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
atom); display->atom_hotplug_mode_update);
meta_error_trap_pop (display);
if (info) if (info)
{ {
@@ -349,7 +350,9 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
XRRFreeScreenResources (manager_xrandr->resources); XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL; manager_xrandr->resources = NULL;
meta_error_trap_push (meta_get_display ());
dpms_capable = DPMSCapable (manager_xrandr->xdisplay); dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
meta_error_trap_pop (meta_get_display ());
if (dpms_capable && if (dpms_capable &&
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) && DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
@@ -449,8 +452,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
XRRFreeCrtcInfo (crtc); XRRFreeCrtcInfo (crtc);
} }
meta_error_trap_push (meta_get_display ());
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay, primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay)); DefaultRootWindow (manager_xrandr->xdisplay));
meta_error_trap_pop (meta_get_display ());
n_actual_outputs = 0; n_actual_outputs = 0;
for (i = 0; i < (unsigned)resources->noutput; i++) for (i = 0; i < (unsigned)resources->noutput; i++)
@@ -632,8 +637,10 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
return; return;
} }
meta_error_trap_push (meta_get_display ());
DPMSForceLevel (manager_xrandr->xdisplay, state); DPMSForceLevel (manager_xrandr->xdisplay, state);
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0); DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
meta_error_trap_pop (meta_get_display ());
} }
static Rotation static Rotation
@@ -667,13 +674,12 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, MetaOutput *output,
gboolean presentation) gboolean presentation)
{ {
Atom atom; MetaDisplay *display = meta_get_display ();
int value = presentation; int value = presentation;
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay, XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id, (XID)output->output_id,
atom, display->atom__MUTTER_PRESENTATION_OUTPUT,
XA_CARDINAL, 32, PropModeReplace, XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1); (unsigned char*) &value, 1);
} }
@@ -686,10 +692,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
unsigned int n_outputs) unsigned int n_outputs)
{ {
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
MetaDisplay *display = meta_get_display ();
unsigned i; unsigned i;
int width, height, width_mm, height_mm; int width, height, width_mm, height_mm;
XGrabServer (manager_xrandr->xdisplay); meta_display_grab (display);
/* First compute the new size of the screen (framebuffer) */ /* First compute the new size of the screen (framebuffer) */
width = 0; height = 0; width = 0; height = 0;
@@ -783,8 +790,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
*/ */
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5; width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5; height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
meta_error_trap_push (display);
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay), XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
width, height, width_mm, height_mm); width, height, width_mm, height_mm);
meta_error_trap_pop (display);
for (i = 0; i < n_crtcs; i++) for (i = 0; i < n_crtcs; i++)
{ {
@@ -841,6 +850,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
goto next; goto next;
} }
meta_error_trap_push (display);
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay, ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources, manager_xrandr->resources,
(XID)crtc->crtc_id, (XID)crtc->crtc_id,
@@ -849,6 +859,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
(XID)mode->mode_id, (XID)mode->mode_id,
wl_transform_to_xrandr (crtc_info->transform), wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs); outputs, n_outputs);
meta_error_trap_pop (display);
if (ok != Success) if (ok != Success)
{ {
@@ -889,9 +900,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (output_info->is_primary) if (output_info->is_primary)
{ {
meta_error_trap_push (display);
XRRSetOutputPrimary (manager_xrandr->xdisplay, XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay), DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->output_id); (XID)output_info->output->output_id);
meta_error_trap_pop (display);
} }
output_set_presentation_xrandr (manager_xrandr, output_set_presentation_xrandr (manager_xrandr,
@@ -917,7 +930,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->is_primary = FALSE; output->is_primary = FALSE;
} }
XUngrabServer (manager_xrandr->xdisplay); meta_display_ungrab (display);
} }
static void static void
@@ -926,17 +939,18 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
gint value) gint value)
{ {
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
Atom atom; MetaDisplay *display = meta_get_display ();
int hw_value; int hw_value;
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min); hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); meta_error_trap_push (display);
XRRChangeOutputProperty (manager_xrandr->xdisplay, XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id, (XID)output->output_id,
atom, display->atom_BACKLIGHT,
XA_INTEGER, 32, PropModeReplace, XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1); (unsigned char *) &hw_value, 1);
meta_error_trap_pop (display);
/* We're not selecting for property notifies, so update the value immediately */ /* We're not selecting for property notifies, so update the value immediately */
output->backlight = normalize_backlight (output, hw_value); output->backlight = normalize_backlight (output, hw_value);
@@ -994,65 +1008,11 @@ meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
meta_monitor_manager_rebuild_derived (manager); meta_monitor_manager_rebuild_derived (manager);
} }
static void static gboolean
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
{ {
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
if (!XRRQueryExtension (manager_xrandr->xdisplay,
&manager_xrandr->rr_event_base,
&manager_xrandr->rr_error_base))
{
return;
}
else
{
/* We only use ScreenChangeNotify, but GDK uses the others,
and we don't want to step on its toes */
XRRSelectInput (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
RRScreenChangeNotifyMask
| RRCrtcChangeNotifyMask
| RROutputPropertyNotifyMask);
}
}
static void
meta_monitor_manager_xrandr_finalize (GObject *object)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
if (manager_xrandr->resources)
XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL;
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
}
static void
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitor_manager_xrandr_finalize;
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
}
gboolean
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
XEvent *event)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
MetaOutput *old_outputs; MetaOutput *old_outputs;
MetaCRTC *old_crtcs; MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes; MetaMonitorMode *old_modes;
@@ -1113,3 +1073,59 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
return TRUE; return TRUE;
} }
static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{
MetaDisplay *display = meta_get_display ();
manager_xrandr->xdisplay = display->xdisplay;
if (!XRRQueryExtension (manager_xrandr->xdisplay,
&manager_xrandr->rr_event_base,
&manager_xrandr->rr_error_base))
{
return;
}
else
{
/* We only use ScreenChangeNotify, but GDK uses the others,
and we don't want to step on its toes */
XRRSelectInput (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
RRScreenChangeNotifyMask
| RRCrtcChangeNotifyMask
| RROutputPropertyNotifyMask);
}
}
static void
meta_monitor_manager_xrandr_finalize (GObject *object)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
if (manager_xrandr->resources)
XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL;
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
}
static void
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitor_manager_xrandr_finalize;
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
}

View File

@@ -37,7 +37,4 @@ typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void); GType meta_monitor_manager_xrandr_get_type (void);
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
XEvent *event);
#endif /* META_MONITOR_MANAGER_XRANDR_H */ #endif /* META_MONITOR_MANAGER_XRANDR_H */

View File

@@ -72,7 +72,6 @@
#include <meta/meta-shadow-factory.h> #include <meta/meta-shadow-factory.h>
#include "meta-window-actor-private.h" #include "meta-window-actor-private.h"
#include "meta-window-group.h" #include "meta-window-group.h"
#include "meta-stage.h"
#include "window-private.h" /* to check window->hidden */ #include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */ #include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h" #include "util-private.h"
@@ -80,9 +79,6 @@
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xcomposite.h>
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
static gboolean static gboolean
@@ -151,13 +147,16 @@ process_damage (MetaCompositor *compositor,
static Window static Window
get_output_window (MetaCompositor *compositor) get_output_window (MetaCompositor *compositor)
{ {
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); MetaDisplay *display = compositor->display;
Display *xdisplay = meta_backend_x11_get_xdisplay (backend); Display *xdisplay = display->xdisplay;
Window output; Window output, xroot;
XWindowAttributes attr;
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay)); xroot = display->screen->xroot;
output = XCompositeGetOverlayWindow (xdisplay, xroot);
meta_core_add_old_event_mask (xdisplay, output, &mask); meta_core_add_old_event_mask (xdisplay, output, &mask);
@@ -172,6 +171,12 @@ get_output_window (MetaCompositor *compositor)
XISetMask (mask.mask, XI_Motion); XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, output, &mask, 1); XISelectEvents (xdisplay, output, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask;
if (XGetWindowAttributes (xdisplay, output, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, output, event_mask);
return output; return output;
} }
@@ -322,16 +327,38 @@ meta_stage_is_focused (MetaScreen *screen)
} }
static gboolean static gboolean
grab_devices (MetaModalOptions options, begin_modal_x11 (MetaCompositor *compositor,
guint32 timestamp) MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{ {
MetaBackend *backend = META_BACKEND (meta_get_backend ()); MetaDisplay *display = compositor->display;
gboolean pointer_grabbed = FALSE; Display *xdpy = meta_display_get_xdisplay (display);
gboolean keyboard_grabbed = FALSE; Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
int result;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{ {
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp)) unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_Motion);
result = XIGrabDevice (xdpy,
META_VIRTUAL_CORE_POINTER_ID,
grab_window,
timestamp,
None,
XIGrabModeAsync, XIGrabModeAsync,
False, /* owner_events */
&mask);
if (result != Success)
goto fail; goto fail;
pointer_grabbed = TRUE; pointer_grabbed = TRUE;
@@ -339,7 +366,22 @@ grab_devices (MetaModalOptions options,
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0) if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{ {
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp)) unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
result = XIGrabDevice (xdpy,
META_VIRTUAL_CORE_KEYBOARD_ID,
grab_window,
timestamp,
None,
XIGrabModeAsync, XIGrabModeAsync,
False, /* owner_events */
&mask);
if (result != Success)
goto fail; goto fail;
keyboard_grabbed = TRUE; keyboard_grabbed = TRUE;
@@ -349,9 +391,9 @@ grab_devices (MetaModalOptions options,
fail: fail:
if (pointer_grabbed) if (pointer_grabbed)
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
if (keyboard_grabbed) if (keyboard_grabbed)
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
return FALSE; return FALSE;
} }
@@ -371,14 +413,9 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE) if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
return FALSE; return FALSE;
/* XXX: why is this needed? */ if (!meta_is_wayland_compositor ())
XIUngrabDevice (display->xdisplay, if (!begin_modal_x11 (compositor, plugin, options, timestamp))
META_VIRTUAL_CORE_POINTER_ID, return FALSE;
timestamp);
XSync (display->xdisplay, False);
if (!grab_devices (options, timestamp))
return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR; display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL; display->grab_window = NULL;
@@ -397,7 +434,7 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
guint32 timestamp) guint32 timestamp)
{ {
MetaDisplay *display = compositor->display; MetaDisplay *display = compositor->display;
MetaBackend *backend = meta_get_backend (); Display *xdpy = meta_display_get_xdisplay (display);
g_return_if_fail (is_modal (display)); g_return_if_fail (is_modal (display));
@@ -406,11 +443,15 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
display->grab_have_pointer = FALSE; display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE; display->grab_have_keyboard = FALSE;
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display); {
meta_display_sync_wayland_input_focus (display);
}
else
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
} }
static void static void
@@ -450,7 +491,7 @@ redirect_windows (MetaScreen *screen)
*/ */
while (TRUE) while (TRUE)
{ {
meta_error_trap_push (display); meta_error_trap_push_with_return (display);
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
XSync (xdisplay, FALSE); XSync (xdisplay, FALSE);
@@ -478,17 +519,16 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaScreen *screen = display->screen; MetaScreen *screen = display->screen;
Window xwin = 0; Window xwin = 0;
gint width, height; gint width, height;
MetaWaylandCompositor *wayland_compositor;
meta_screen_set_cm_selection (display->screen); meta_screen_set_cm_selection (display->screen);
/* We will have already created a stage if running as a wayland
* compositor... */
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
{ {
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default (); wayland_compositor = meta_wayland_compositor_get_default ();
compositor->stage = wayland_compositor->stage;
compositor->stage = meta_stage_new ();
clutter_actor_show (compositor->stage);
wayland_compositor->stage = compositor->stage;
meta_screen_get_size (screen, &width, &height); meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (compositor->stage, width, height); clutter_actor_set_size (compositor->stage, width, height);
@@ -505,12 +545,12 @@ meta_compositor_manage (MetaCompositor *compositor)
XResizeWindow (xdisplay, xwin, width, height); XResizeWindow (xdisplay, xwin, width, height);
{ {
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); long event_mask;
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask); meta_core_add_old_event_mask (xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress); XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease); XISetMask (mask.mask, XI_KeyRelease);
@@ -524,7 +564,13 @@ meta_compositor_manage (MetaCompositor *compositor)
XIClearMask (mask.mask, XI_TouchBegin); XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd); XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate); XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (backend_xdisplay, xwin, &mask, 1); XISelectEvents (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xwin, event_mask);
} }
} }
@@ -708,6 +754,29 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame); meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
} }
static gboolean
is_grabbed_event (MetaDisplay *display,
XEvent *event)
{
if (event->type == GenericEvent &&
event->xcookie.extension == display->xinput_opcode)
{
XIEvent *xev = (XIEvent *) event->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
return TRUE;
}
}
return FALSE;
}
void void
meta_compositor_window_shape_changed (MetaCompositor *compositor, meta_compositor_window_shape_changed (MetaCompositor *compositor,
MetaWindow *window) MetaWindow *window)
@@ -744,6 +813,82 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
meta_window_actor_update_surface (window_actor); meta_window_actor_update_surface (window_actor);
} }
static gboolean
event_is_passive_button_grab (MetaDisplay *display,
XIDeviceEvent *device_event)
{
/* see display.c for which events are passive button
grabs (meta_display_grab_window_buttons() and
meta_display_handle_events())
we need to filter them here because normally they
would be sent to gtk+ (they are on gtk+ frame xwindow),
but we want to redirect them to clutter
*/
if (device_event->evtype != XI_ButtonPress)
return FALSE;
if (display->window_grab_modifiers == 0)
return FALSE;
if ((device_event->mods.effective & display->window_grab_modifiers) !=
display->window_grab_modifiers)
return FALSE;
return device_event->detail < 4;
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
* to the a stage that isn't its X window.
*
* When running as an X window manager, we need to respond to
* events from lots of windows. Trick Clutter into translating
* these events by pretending we got an event on the stage window.
*/
static void
maybe_spoof_event_as_stage_event (MetaCompositor *compositor,
MetaWindow *window,
XEvent *event)
{
MetaDisplay *display = compositor->display;
if (event->type == GenericEvent &&
event->xcookie.extension == display->xinput_opcode)
{
XIEvent *input_event = (XIEvent *) event->xcookie.data;
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
/* If this is a window frame, and we think GTK+ needs to handle the event,
let GTK+ handle it without mangling */
if (window && window->frame && device_event->event == window->frame->xwindow &&
(meta_grab_op_is_clicking (display->grab_op) ||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
break;
case XI_KeyPress:
case XI_KeyRelease:
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
* it as-is without mangling. */
if (meta_ui_window_is_widget (display->screen->ui, device_event->event))
break;
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
break;
default:
break;
}
}
}
/** /**
* meta_compositor_process_event: (skip) * meta_compositor_process_event: (skip)
* @compositor: * @compositor:
@@ -756,6 +901,20 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event, XEvent *event,
MetaWindow *window) MetaWindow *window)
{ {
MetaDisplay *display = compositor->display;
if (is_modal (display) && is_grabbed_event (display, event))
{
meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event);
/* We always consume events even if the plugin says it didn't handle them;
* exclusive is exclusive */
return TRUE;
}
if (!meta_is_wayland_compositor ())
maybe_spoof_event_as_stage_event (compositor, window, event);
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE; return TRUE;

View File

@@ -81,8 +81,18 @@ _meta_plugin_xevent_filter (MetaPlugin *plugin,
{ {
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->xevent_filter) /* When mutter is running as a wayland compositor, things like input
return klass->xevent_filter (plugin, xev); * events just come directly from clutter so it won't have disabled
* clutter's event retrieval and won't need to forward it events (if
* it did it would lead to recursion). Also when running as a
* wayland compositor we shouldn't be assuming that we're running
* with the clutter x11 backend.
*/
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
return TRUE;
else if (!meta_is_wayland_compositor ())
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
else else
return FALSE; return FALSE;
} }

View File

@@ -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);
}

View File

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

View File

@@ -60,7 +60,6 @@ struct _MetaTextureTower
CoglTexture *textures[MAX_TEXTURE_LEVELS]; CoglTexture *textures[MAX_TEXTURE_LEVELS];
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS]; CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
Box invalid[MAX_TEXTURE_LEVELS]; Box invalid[MAX_TEXTURE_LEVELS];
CoglPipeline *pipeline_template;
}; };
/** /**
@@ -92,9 +91,6 @@ meta_texture_tower_free (MetaTextureTower *tower)
{ {
g_return_if_fail (tower != NULL); g_return_if_fail (tower != NULL);
if (tower->pipeline_template != NULL)
cogl_object_unref (tower->pipeline_template);
meta_texture_tower_set_base_texture (tower, NULL); meta_texture_tower_set_base_texture (tower, NULL);
g_slice_free (MetaTextureTower, tower); g_slice_free (MetaTextureTower, tower);
@@ -377,7 +373,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
tower->invalid[level].y2 = height; tower->invalid[level].y2 = height;
} }
static void static gboolean
texture_tower_revalidate_fbo (MetaTextureTower *tower, texture_tower_revalidate_fbo (MetaTextureTower *tower,
int level) int level)
{ {
@@ -388,50 +384,174 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
int dest_texture_width = cogl_texture_get_width (dest_texture); int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture); int dest_texture_height = cogl_texture_get_height (dest_texture);
Box *invalid = &tower->invalid[level]; Box *invalid = &tower->invalid[level];
CoglFramebuffer *fb; CoglMatrix modelview;
CoglError *catch_error = NULL;
CoglPipeline *pipeline;
if (tower->fbos[level] == NULL) if (tower->fbos[level] == NULL)
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture); tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
fb = COGL_FRAMEBUFFER (tower->fbos[level]); if (tower->fbos[level] == NULL)
return FALSE;
if (!cogl_framebuffer_allocate (fb, &catch_error)) cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
cogl_matrix_init_identity (&modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source_texture (tower->textures[level - 1]);
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
cogl_pop_framebuffer ();
return TRUE;
}
static void
fill_copy (guchar *buf,
const guchar *source,
int width)
{
memcpy (buf, source, width * 4);
}
static void
fill_scale_down (guchar *buf,
const guchar *source,
int width)
{
while (width > 1)
{ {
cogl_error_free (catch_error); buf[0] = (source[0] + source[4]) / 2;
return; buf[1] = (source[1] + source[5]) / 2;
buf[2] = (source[2] + source[6]) / 2;
buf[3] = (source[3] + source[7]) / 2;
buf += 4;
source += 8;
width -= 2;
} }
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.); if (width > 0)
if (!tower->pipeline_template)
{ {
CoglContext *ctx = buf[0] = source[0] / 2;
clutter_backend_get_cogl_context (clutter_get_default_backend ()); buf[1] = source[1] / 2;
tower->pipeline_template = cogl_pipeline_new (ctx); buf[2] = source[2] / 2;
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL); buf[3] = source[3] / 2;
}
}
static void
texture_tower_revalidate_client (MetaTextureTower *tower,
int level)
{
CoglTexture *source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
guint source_rowstride;
guchar *source_data;
CoglTexture *dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
int dest_x = tower->invalid[level].x1;
int dest_y = tower->invalid[level].y1;
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
guchar *dest_data;
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
int i, j;
source_rowstride = source_texture_width * 4;
source_data = g_malloc (source_texture_height * source_rowstride);
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
source_data);
dest_data = g_malloc (dest_height * dest_width * 4);
if (dest_texture_height < source_texture_height)
{
source_tmp1 = g_malloc (dest_width * 4);
source_tmp2 = g_malloc (dest_width * 4);
} }
pipeline = cogl_pipeline_copy (tower->pipeline_template); for (i = 0; i < dest_height; i++)
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]); {
guchar *dest_row = dest_data + i * dest_width * 4;
if (dest_texture_height < source_texture_height)
{
guchar *source1, *source2;
guchar *dest;
cogl_framebuffer_draw_textured_rectangle (fb, pipeline, if (dest_texture_width < source_texture_width)
invalid->x1, invalid->y1, {
invalid->x2, invalid->y2, fill_scale_down (source_tmp1,
(2. * invalid->x1) / source_texture_width, source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
(2. * invalid->y1) / source_texture_height, dest_width * 2);
(2. * invalid->x2) / source_texture_width, fill_scale_down (source_tmp2,
(2. * invalid->y2) / source_texture_height); source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
}
else
{
fill_copy (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
dest_width);
fill_copy (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
dest_width);
}
cogl_object_unref (pipeline); source1 = source_tmp1;
source2 = source_tmp2;
dest = dest_row;
for (j = 0; j < dest_width * 4; j++)
*(dest++) = (*(source1++) + *(source2++)) / 2;
}
else
{
if (dest_texture_width < source_texture_width)
fill_scale_down (dest_row,
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
else
fill_copy (dest_row,
source_data + (i + dest_y) * source_rowstride,
dest_width);
}
}
cogl_texture_set_region (dest_texture,
0, 0,
dest_x, dest_y,
dest_width, dest_height,
dest_width, dest_height,
TEXTURE_FORMAT,
4 * dest_width,
dest_data);
if (dest_texture_height < source_texture_height)
{
g_free (source_tmp1);
g_free (source_tmp2);
}
g_free (source_data);
g_free (dest_data);
} }
static void static void
texture_tower_revalidate (MetaTextureTower *tower, texture_tower_revalidate (MetaTextureTower *tower,
int level) int level)
{ {
texture_tower_revalidate_fbo (tower, level); if (!texture_tower_revalidate_fbo (tower, level))
texture_tower_revalidate_client (tower, level);
} }
/** /**

View File

@@ -855,7 +855,6 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
* to be drawn when the timer expires. * to be drawn when the timer expires.
*/ */
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL); priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
g_source_set_name_by_id (priv->send_frame_messages_timer, "[mutter] send_frame_messages_timeout");
} }
void void

View File

@@ -34,6 +34,7 @@
#define DESTROY_TIMEOUT 100 #define DESTROY_TIMEOUT 100
#define MINIMIZE_TIMEOUT 250 #define MINIMIZE_TIMEOUT 250
#define MAXIMIZE_TIMEOUT 250
#define MAP_TIMEOUT 250 #define MAP_TIMEOUT 250
#define SWITCH_TIMEOUT 500 #define SWITCH_TIMEOUT 500
@@ -76,6 +77,18 @@ static void map (MetaPlugin *plugin,
MetaWindowActor *actor); MetaWindowActor *actor);
static void destroy (MetaPlugin *plugin, static void destroy (MetaPlugin *plugin,
MetaWindowActor *actor); MetaWindowActor *actor);
static void maximize (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
static void unmaximize (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
static void switch_workspace (MetaPlugin *plugin, static void switch_workspace (MetaPlugin *plugin,
gint from, gint from,
@@ -122,8 +135,12 @@ typedef struct _ActorPrivate
ClutterActor *orig_parent; ClutterActor *orig_parent;
ClutterTimeline *tml_minimize; ClutterTimeline *tml_minimize;
ClutterTimeline *tml_maximize;
ClutterTimeline *tml_destroy; ClutterTimeline *tml_destroy;
ClutterTimeline *tml_map; ClutterTimeline *tml_map;
gboolean is_minimized : 1;
gboolean is_maximized : 1;
} ActorPrivate; } ActorPrivate;
/* callback data for when animations complete */ /* callback data for when animations complete */
@@ -199,6 +216,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
plugin_class->start = start; plugin_class->start = start;
plugin_class->map = map; plugin_class->map = map;
plugin_class->minimize = minimize; plugin_class->minimize = minimize;
plugin_class->maximize = maximize;
plugin_class->unmaximize = unmaximize;
plugin_class->destroy = destroy; plugin_class->destroy = destroy;
plugin_class->switch_workspace = switch_workspace; plugin_class->switch_workspace = switch_workspace;
plugin_class->show_tile_preview = show_tile_preview; plugin_class->show_tile_preview = show_tile_preview;
@@ -503,6 +522,8 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
EffectCompleteData *data = g_new0 (EffectCompleteData, 1); EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor); ActorPrivate *apriv = get_actor_private (window_actor);
apriv->is_minimized = TRUE;
animation = clutter_actor_animate (actor, animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE, CLUTTER_EASE_IN_SINE,
MINIMIZE_TIMEOUT, MINIMIZE_TIMEOUT,
@@ -523,6 +544,115 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
meta_plugin_minimize_completed (plugin, window_actor); meta_plugin_minimize_completed (plugin, window_actor);
} }
/*
* Minimize effect completion callback; this function restores actor state, and
* calls the manager callback function.
*/
static void
on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
{
/*
* Must reverse the effect of the effect.
*/
MetaPlugin *plugin = data->plugin;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_maximize = NULL;
/* FIXME - don't assume the original scale was 1.0 */
clutter_actor_set_scale (data->actor, 1.0, 1.0);
/* Now notify the manager that we are done with this effect */
meta_plugin_maximize_completed (plugin, window_actor);
g_free (data);
}
/*
* The Nature of Maximize operation is such that it is difficult to do a visual
* effect that would work well. Scaling, the obvious effect, does not work that
* well, because at the end of the effect we end up with window content bigger
* and differently laid out than in the real window; this is a proof concept.
*
* (Something like a sound would be more appropriate.)
*/
static void
maximize (MetaPlugin *plugin,
MetaWindowActor *window_actor,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
type = meta_window_get_window_type (meta_window);
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (window_actor);
gfloat width, height;
gfloat x, y;
apriv->is_maximized = TRUE;
clutter_actor_get_size (actor, &width, &height);
clutter_actor_get_position (actor, &x, &y);
/*
* Work out the scale and anchor point so that the window is expanding
* smoothly into the target size.
*/
scale_x = (gdouble)end_width / (gdouble) width;
scale_y = (gdouble)end_height / (gdouble) height;
animation = clutter_actor_animate (actor,
CLUTTER_EASE_IN_SINE,
MAXIMIZE_TIMEOUT,
"scale-x", scale_x,
"scale-y", scale_y,
NULL);
apriv->tml_maximize = clutter_animation_get_timeline (animation);
data->plugin = plugin;
data->actor = actor;
g_signal_connect (apriv->tml_maximize, "completed",
G_CALLBACK (on_maximize_effect_complete),
data);
return;
}
meta_plugin_maximize_completed (plugin, window_actor);
}
/*
* See comments on the maximize() function.
*
* (Just a skeleton code.)
*/
static void
unmaximize (MetaPlugin *plugin,
MetaWindowActor *window_actor,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
MetaWindowType type = meta_window_get_window_type (meta_window);
if (type == META_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->is_maximized = FALSE;
}
/* Do this conditionally, if the effect requires completion callback. */
meta_plugin_unmaximize_completed (plugin, window_actor);
}
static void static void
on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
{ {
@@ -578,6 +708,9 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
g_signal_connect (apriv->tml_map, "completed", g_signal_connect (apriv->tml_map, "completed",
G_CALLBACK (on_map_effect_complete), G_CALLBACK (on_map_effect_complete),
data); data);
apriv->is_minimized = FALSE;
} }
else else
meta_plugin_map_completed (plugin, window_actor); meta_plugin_map_completed (plugin, window_actor);
@@ -738,6 +871,12 @@ kill_window_effects (MetaPlugin *plugin,
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL); g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
} }
if (apriv->tml_maximize)
{
clutter_timeline_stop (apriv->tml_maximize);
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
}
if (apriv->tml_map) if (apriv->tml_map)
{ {
clutter_timeline_stop (apriv->tml_map); clutter_timeline_stop (apriv->tml_map);

View 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 = &section->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;
}

View File

@@ -120,7 +120,6 @@ bell_unflash_frame (gpointer data)
static void static void
bell_flash_window_frame (MetaWindow *window) bell_flash_window_frame (MetaWindow *window)
{ {
guint id;
g_assert (window->frame != NULL); g_assert (window->frame != NULL);
window->frame->is_flashing = 1; window->frame->is_flashing = 1;
meta_frame_queue_draw (window->frame); meta_frame_queue_draw (window->frame);
@@ -129,9 +128,8 @@ bell_flash_window_frame (MetaWindow *window)
* we are guaranteed to get at least one frame drawn in the * we are guaranteed to get at least one frame drawn in the
* flashed state, no matter how loaded we are. * flashed state, no matter how loaded we are.
*/ */
id = g_timeout_add_full (META_PRIORITY_REDRAW, 100, g_timeout_add_full (META_PRIORITY_REDRAW, 100,
bell_unflash_frame, window->frame, NULL); bell_unflash_frame, window->frame, NULL);
g_source_set_name_by_id (id, "[mutter] bell_unflash_frame");
} }
/** /**

View File

@@ -199,6 +199,14 @@ static void place_window_if_needed (MetaWindow *window,
ConstraintInfo *info); ConstraintInfo *info);
static void update_onscreen_requirements (MetaWindow *window, static void update_onscreen_requirements (MetaWindow *window,
ConstraintInfo *info); ConstraintInfo *info);
static void extend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static void unextend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static inline void get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size,
MetaRectangle *max_size);
typedef gboolean (* ConstraintFunc) (MetaWindow *window, typedef gboolean (* ConstraintFunc) (MetaWindow *window,
ConstraintInfo *info, ConstraintInfo *info,
@@ -492,6 +500,7 @@ place_window_if_needed(MetaWindow *window,
meta_window_get_frame_rect (window, &placed_rect); meta_window_get_frame_rect (window, &placed_rect);
orig_rect = info->orig; orig_rect = info->orig;
extend_by_frame (window, &orig_rect);
meta_window_place (window, orig_rect.x, orig_rect.y, meta_window_place (window, orig_rect.x, orig_rect.y,
&placed_rect.x, &placed_rect.y); &placed_rect.x, &placed_rect.y);
@@ -613,6 +622,11 @@ update_onscreen_requirements (MetaWindow *window,
* problematic case but this may need to be revisited. * problematic case but this may need to be revisited.
*/ */
/* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner
*/
extend_by_frame (window, &info->current);
/* Update whether we want future constraint runs to require the /* Update whether we want future constraint runs to require the
* window to be on fully onscreen. * window to be on fully onscreen.
*/ */
@@ -661,10 +675,28 @@ update_onscreen_requirements (MetaWindow *window,
window->desc, window->desc,
window->require_titlebar_visible ? "TRUE" : "FALSE"); window->require_titlebar_visible ? "TRUE" : "FALSE");
} }
/* Don't forget to restore the position of the window */
unextend_by_frame (window, &info->current);
}
static void
extend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
meta_window_client_rect_to_frame_rect (window, rect, rect);
}
static void
unextend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
meta_window_frame_rect_to_client_rect (window, rect, rect);
} }
static inline void static inline void
get_size_limits (MetaWindow *window, get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size, MetaRectangle *min_size,
MetaRectangle *max_size) MetaRectangle *max_size)
{ {
@@ -677,8 +709,11 @@ get_size_limits (MetaWindow *window,
max_size->width = window->size_hints.max_width; max_size->width = window->size_hints.max_width;
max_size->height = window->size_hints.max_height; max_size->height = window->size_hints.max_height;
meta_window_client_rect_to_frame_rect (window, min_size, min_size); if (include_frame)
meta_window_client_rect_to_frame_rect (window, max_size, max_size); {
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
}
} }
static gboolean static gboolean
@@ -702,11 +737,13 @@ constrain_modal_dialog (MetaWindow *window,
*/ */
child_rect = info->current; child_rect = info->current;
extend_by_frame (window, &child_rect);
meta_window_get_frame_rect (parent, &parent_rect); meta_window_get_frame_rect (parent, &parent_rect);
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2); child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2); child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
unextend_by_frame (window, &child_rect);
x = child_rect.x; x = child_rect.x;
y = child_rect.y; y = child_rect.y;
@@ -773,16 +810,19 @@ constrain_maximization (MetaWindow *window,
active_workspace_struts = window->screen->active_workspace->all_struts; active_workspace_struts = window->screen->active_workspace->all_struts;
target_size = info->current; target_size = info->current;
extend_by_frame (window, &target_size);
meta_rectangle_expand_to_avoiding_struts (&target_size, meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_monitor, &info->entire_monitor,
direction, direction,
active_workspace_struts); active_workspace_struts);
} }
/* Now make target_size = maximized size of client window */
unextend_by_frame (window, &target_size);
/* Check min size constraints; max size constraints are ignored for maximized /* Check min size constraints; max size constraints are ignored for maximized
* windows, as per bug 327543. * windows, as per bug 327543.
*/ */
get_size_limits (window, &min_size, &max_size); get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width && window->maximized_horizontally; hminbad = target_size.width < min_size.width && window->maximized_horizontally;
vminbad = target_size.height < min_size.height && window->maximized_vertically; vminbad = target_size.height < min_size.height && window->maximized_vertically;
if (hminbad || vminbad) if (hminbad || vminbad)
@@ -836,11 +876,12 @@ constrain_tiling (MetaWindow *window,
* use an external function for the actual calculation * use an external function for the actual calculation
*/ */
meta_window_get_current_tile_area (window, &target_size); meta_window_get_current_tile_area (window, &target_size);
unextend_by_frame (window, &target_size);
/* Check min size constraints; max size constraints are ignored as for /* Check min size constraints; max size constraints are ignored as for
* maximized windows. * maximized windows.
*/ */
get_size_limits (window, &min_size, &max_size); get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width; hminbad = target_size.width < min_size.width;
vminbad = target_size.height < min_size.height; vminbad = target_size.height < min_size.height;
if (hminbad || vminbad) if (hminbad || vminbad)
@@ -883,7 +924,7 @@ constrain_fullscreen (MetaWindow *window,
monitor = info->entire_monitor; monitor = info->entire_monitor;
get_size_limits (window, &min_size, &max_size); get_size_limits (window, FALSE, &min_size, &max_size);
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size); too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor); too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
if (too_big || too_small) if (too_big || too_small)
@@ -992,7 +1033,7 @@ constrain_size_limits (MetaWindow *window,
return TRUE; return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */ /* Determine whether constraint is already satisfied; exit if it is */
get_size_limits (window, &min_size, &max_size); get_size_limits (window, FALSE, &min_size, &max_size);
/* We ignore max-size limits for maximized windows; see #327543 */ /* We ignore max-size limits for maximized windows; see #327543 */
if (window->maximized_horizontally) if (window->maximized_horizontally)
max_size.width = MAX (max_size.width, info->current.width); max_size.width = MAX (max_size.width, info->current.width);
@@ -1184,7 +1225,8 @@ do_screen_and_monitor_relative_constraints (
/* Determine whether constraint applies; exit if it doesn't */ /* Determine whether constraint applies; exit if it doesn't */
how_far_it_can_be_smushed = info->current; how_far_it_can_be_smushed = info->current;
get_size_limits (window, &min_size, &max_size); get_size_limits (window, TRUE, &min_size, &max_size);
extend_by_frame (window, &info->current);
if (info->action_type != ACTION_MOVE) if (info->action_type != ACTION_MOVE)
{ {
@@ -1203,7 +1245,10 @@ do_screen_and_monitor_relative_constraints (
meta_rectangle_contained_in_region (region_spanning_rectangles, meta_rectangle_contained_in_region (region_spanning_rectangles,
&info->current); &info->current);
if (exit_early || constraint_satisfied || check_only) if (exit_early || constraint_satisfied || check_only)
return constraint_satisfied; {
unextend_by_frame (window, &info->current);
return constraint_satisfied;
}
/* Enforce constraint */ /* Enforce constraint */
@@ -1225,6 +1270,7 @@ do_screen_and_monitor_relative_constraints (
info->fixed_directions, info->fixed_directions,
&info->current); &info->current);
unextend_by_frame (window, &info->current);
return TRUE; return TRUE;
} }

View File

@@ -261,6 +261,45 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
timestamp); timestamp);
} }
void
meta_core_lower_beneath_grab_window (Display *xdisplay,
Window xwindow,
guint32 timestamp)
{
XWindowChanges changes;
MetaDisplay *display;
MetaScreen *screen;
MetaWindow *grab_window;
MetaStackWindow stack_window;
MetaStackWindow stack_sibling;
display = meta_display_for_x_display (xdisplay);
screen = display->screen;
grab_window = display->grab_window;
if (grab_window == NULL)
return;
changes.stack_mode = Below;
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_sibling.x11.xwindow = changes.sibling;
meta_stack_tracker_record_lower_below (screen->stack_tracker,
&stack_window,
&stack_sibling,
XNextRequest (screen->display->xdisplay));
meta_error_trap_push (display);
XConfigureWindow (xdisplay,
xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (display);
}
void void
meta_core_user_focus (Display *xdisplay, meta_core_user_focus (Display *xdisplay,
Window frame_xwindow, Window frame_xwindow,
@@ -620,6 +659,36 @@ meta_core_get_grab_op (Display *xdisplay)
return display->grab_op; return display->grab_op;
} }
Window
meta_core_get_grab_frame (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
g_assert (display != NULL);
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window &&
display->grab_window->frame)
return display->grab_window->frame->xwindow;
else
return None;
}
int
meta_core_get_grab_button (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display->grab_op == META_GRAB_OP_NONE)
return -1;
return display->grab_button;
}
void void
meta_core_grab_buttons (Display *xdisplay, meta_core_grab_buttons (Display *xdisplay,
Window frame_xwindow) Window frame_xwindow)

View File

@@ -114,6 +114,10 @@ void meta_core_user_focus (Display *xdisplay,
Window frame_xwindow, Window frame_xwindow,
guint32 timestamp); guint32 timestamp);
void meta_core_lower_beneath_grab_window (Display *xdisplay,
Window xwindow,
guint32 timestamp);
void meta_core_minimize (Display *xdisplay, void meta_core_minimize (Display *xdisplay,
Window frame_xwindow); Window frame_xwindow);
void meta_core_toggle_maximize (Display *xdisplay, void meta_core_toggle_maximize (Display *xdisplay,
@@ -178,6 +182,8 @@ gboolean meta_core_begin_grab_op (Display *xdisplay,
void meta_core_end_grab_op (Display *xdisplay, void meta_core_end_grab_op (Display *xdisplay,
guint32 timestamp); guint32 timestamp);
MetaGrabOp meta_core_get_grab_op (Display *xdisplay); MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
Window meta_core_get_grab_frame (Display *xdisplay);
int meta_core_get_grab_button (Display *xdisplay);
void meta_core_grab_buttons (Display *xdisplay, void meta_core_grab_buttons (Display *xdisplay,

View File

@@ -31,6 +31,7 @@
#include <glib.h> #include <glib.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
#include <meta/common.h> #include <meta/common.h>
#include <meta/boxes.h> #include <meta/boxes.h>
#include <meta/display.h> #include <meta/display.h>
@@ -43,7 +44,9 @@
#include <libsn/sn.h> #include <libsn/sn.h>
#endif #endif
#ifdef HAVE_XSYNC
#include <X11/extensions/sync.h> #include <X11/extensions/sync.h>
#endif
typedef struct _MetaStack MetaStack; typedef struct _MetaStack MetaStack;
typedef struct _MetaUISlave MetaUISlave; typedef struct _MetaUISlave MetaUISlave;
@@ -145,10 +148,13 @@ struct _MetaDisplay
guint focused_by_us : 1; guint focused_by_us : 1;
/*< private-ish >*/ /*< private-ish >*/
guint error_trap_synced_at_last_pop : 1;
MetaScreen *screen; MetaScreen *screen;
GHashTable *xids; GHashTable *xids;
GHashTable *wayland_windows; GHashTable *wayland_windows;
int error_traps;
int (* error_trap_handler) (Display *display,
XErrorEvent *error);
int server_grab_count; int server_grab_count;
/* serials of leave/unmap events that may /* serials of leave/unmap events that may
@@ -194,6 +200,7 @@ struct _MetaDisplay
int grab_tile_monitor_number; int grab_tile_monitor_number;
int grab_latest_motion_x; int grab_latest_motion_x;
int grab_latest_motion_y; int grab_latest_motion_y;
gulong grab_mask;
guint grab_have_pointer : 1; guint grab_have_pointer : 1;
guint grab_have_keyboard : 1; guint grab_have_keyboard : 1;
guint grab_frame_action : 1; guint grab_frame_action : 1;
@@ -203,7 +210,9 @@ struct _MetaDisplay
MetaRectangle grab_initial_window_pos; MetaRectangle grab_initial_window_pos;
int grab_initial_x, grab_initial_y; /* These are only relevant for */ int grab_initial_x, grab_initial_y; /* These are only relevant for */
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */ gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time; GTimeVal grab_last_moveresize_time;
GList* grab_old_window_stacking;
MetaEdgeResistanceData *grab_edge_resistance_data; MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap; unsigned int grab_last_user_action_was_snap;
guint32 grab_timestamp; guint32 grab_timestamp;
@@ -226,7 +235,11 @@ struct _MetaDisplay
int max_keycode; int max_keycode;
KeySym *keymap; KeySym *keymap;
int keysyms_per_keycode; int keysyms_per_keycode;
XModifierKeymap *modmap;
unsigned int above_tab_keycode;
unsigned int ignored_modifier_mask; unsigned int ignored_modifier_mask;
unsigned int num_lock_mask;
unsigned int scroll_lock_mask;
unsigned int hyper_mask; unsigned int hyper_mask;
unsigned int super_mask; unsigned int super_mask;
unsigned int meta_mask; unsigned int meta_mask;
@@ -262,6 +275,9 @@ struct _MetaDisplay
/* Managed by compositor.c */ /* Managed by compositor.c */
MetaCompositor *compositor; MetaCompositor *compositor;
int render_event_base;
int render_error_base;
int composite_event_base; int composite_event_base;
int composite_error_base; int composite_error_base;
int composite_major_version; int composite_major_version;
@@ -277,14 +293,28 @@ struct _MetaDisplay
#ifdef HAVE_STARTUP_NOTIFICATION #ifdef HAVE_STARTUP_NOTIFICATION
SnDisplay *sn_display; SnDisplay *sn_display;
#endif #endif
#ifdef HAVE_XSYNC
int xsync_event_base; int xsync_event_base;
int xsync_error_base; int xsync_error_base;
#endif
#ifdef HAVE_SHAPE
int shape_event_base; int shape_event_base;
int shape_error_base; int shape_error_base;
#endif
#ifdef HAVE_XSYNC
unsigned int have_xsync : 1; unsigned int have_xsync : 1;
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync) #define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
#else
#define META_DISPLAY_HAS_XSYNC(display) FALSE
#endif
#ifdef HAVE_SHAPE
unsigned int have_shape : 1; unsigned int have_shape : 1;
#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape) #define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape)
#else
#define META_DISPLAY_HAS_SHAPE(display) FALSE
#endif
unsigned int have_render : 1;
#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render)
unsigned int have_composite : 1; unsigned int have_composite : 1;
unsigned int have_damage : 1; unsigned int have_damage : 1;
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite) #define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
@@ -347,6 +377,7 @@ void meta_display_register_wayland_window (MetaDisplay *display,
void meta_display_unregister_wayland_window (MetaDisplay *display, void meta_display_unregister_wayland_window (MetaDisplay *display,
MetaWindow *window); MetaWindow *window);
#ifdef HAVE_XSYNC
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display, MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
XSyncAlarm alarm); XSyncAlarm alarm);
void meta_display_register_sync_alarm (MetaDisplay *display, void meta_display_register_sync_alarm (MetaDisplay *display,
@@ -354,6 +385,7 @@ void meta_display_register_sync_alarm (MetaDisplay *display,
MetaWindow *window); MetaWindow *window);
void meta_display_unregister_sync_alarm (MetaDisplay *display, void meta_display_unregister_sync_alarm (MetaDisplay *display,
XSyncAlarm alarm); XSyncAlarm alarm);
#endif /* HAVE_XSYNC */
void meta_display_notify_window_created (MetaDisplay *display, void meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window); MetaWindow *window);
@@ -366,9 +398,13 @@ MetaDisplay* meta_get_display (void);
Cursor meta_display_create_x_cursor (MetaDisplay *display, Cursor meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor); MetaCursor cursor);
XcursorImage *meta_display_load_x_cursor (MetaDisplay *display,
MetaCursor cursor);
void meta_display_set_grab_op_cursor (MetaDisplay *display, void meta_display_set_grab_op_cursor (MetaDisplay *display,
MetaScreen *screen,
MetaGrabOp op, MetaGrabOp op,
Window grab_xwindow,
guint32 timestamp); guint32 timestamp);
void meta_display_check_threshold_reached (MetaDisplay *display, 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_queue_retheme_all_windows (MetaDisplay *display);
void meta_display_retheme_all (void); void meta_display_retheme_all (void);
void meta_display_set_cursor_theme (const char *theme,
int size);
void meta_display_ping_window (MetaWindow *window, void meta_display_ping_window (MetaWindow *window,
guint32 timestamp, guint32 timestamp,
MetaWindowPingFunc ping_reply_func, 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_moving (MetaGrabOp op);
gboolean meta_grab_op_is_resizing (MetaGrabOp op); gboolean meta_grab_op_is_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_mouse (MetaGrabOp op); gboolean meta_grab_op_is_mouse (MetaGrabOp op);
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
gboolean meta_grab_op_is_keyboard (MetaGrabOp op); gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
gboolean meta_grab_op_should_block_wayland (MetaGrabOp op);
void meta_display_devirtualize_modifiers (MetaDisplay *display, void meta_display_devirtualize_modifiers (MetaDisplay *display,
MetaVirtualModifier modifiers, MetaVirtualModifier modifiers,
@@ -434,6 +473,9 @@ void meta_display_accelerator_activate (MetaDisplay *display,
ClutterKeyEvent *event); ClutterKeyEvent *event);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display); gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
#ifdef HAVE_XI23 #ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display, gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIEvent *event); XIEvent *event);

View File

@@ -41,6 +41,7 @@
#include <meta/errors.h> #include <meta/errors.h>
#include "keybindings-private.h" #include "keybindings-private.h"
#include <meta/prefs.h> #include <meta/prefs.h>
#include "resizepopup.h"
#include "workspace-private.h" #include "workspace-private.h"
#include "bell.h" #include "bell.h"
#include <meta/compositor.h> #include <meta/compositor.h>
@@ -49,14 +50,15 @@
#include "mutter-enum-types.h" #include "mutter-enum-types.h"
#include "meta-idle-monitor-dbus.h" #include "meta-idle-monitor-dbus.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_RANDR #ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#endif #endif
#ifdef HAVE_SHAPE
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#endif
#include <X11/Xcursor/Xcursor.h> #include <X11/Xcursor/Xcursor.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h> #include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.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 *gnome_wm_keybindings = "Mutter";
static const char *net_wm_name = "Mutter"; static const char *net_wm_name = "Mutter";
static void update_cursor_theme (void);
static void update_window_grab_modifiers (MetaDisplay *display); static void update_window_grab_modifiers (MetaDisplay *display);
static void prefs_changed_callback (MetaPreference pref, static void prefs_changed_callback (MetaPreference pref,
void *data); void *data);
static void static void
meta_display_get_property(GObject *object, meta_display_get_property(GObject *object,
guint prop_id, guint prop_id,
@@ -363,10 +363,12 @@ static void
enable_compositor (MetaDisplay *display) enable_compositor (MetaDisplay *display)
{ {
if (!META_DISPLAY_HAS_COMPOSITE (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_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; return;
} }
@@ -470,6 +472,9 @@ meta_display_open (void)
*/ */
the_display->name = g_strdup (XDisplayName (NULL)); the_display->name = g_strdup (XDisplayName (NULL));
the_display->xdisplay = xdisplay; 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->server_grab_count = 0;
the_display->display_opening = TRUE; the_display->display_opening = TRUE;
@@ -480,6 +485,7 @@ meta_display_open (void)
the_display->focus_serial = 0; the_display->focus_serial = 0;
the_display->server_focus_window = None; the_display->server_focus_window = None;
the_display->server_focus_serial = 0; 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->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a 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_op = META_GRAB_OP_NONE;
the_display->grab_window = NULL; the_display->grab_window = NULL;
the_display->grab_resize_popup = NULL;
the_display->grab_tile_mode = META_TILE_NONE; the_display->grab_tile_mode = META_TILE_NONE;
the_display->grab_tile_monitor_number = -1; the_display->grab_tile_monitor_number = -1;
the_display->grab_edge_resistance_data = NULL; the_display->grab_edge_resistance_data = NULL;
#ifdef HAVE_XSYNC
{ {
int major, minor; int major, minor;
@@ -593,7 +601,12 @@ meta_display_open (void)
the_display->xsync_error_base, the_display->xsync_error_base,
the_display->xsync_event_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; the_display->have_shape = FALSE;
@@ -614,6 +627,30 @@ meta_display_open (void)
the_display->shape_error_base, the_display->shape_error_base,
the_display->shape_event_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; 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"); 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 /* Create the leader window here. Set its properties and
* use the timestamp from one of the PropertyNotify events * use the timestamp from one of the PropertyNotify events
@@ -976,6 +1016,9 @@ meta_display_close (MetaDisplay *display,
return; return;
} }
if (display->error_traps > 0)
meta_bug ("Display closed with error traps pending\n");
display->closing += 1; display->closing += 1;
meta_prefs_remove_listener (prefs_changed_callback, display); meta_prefs_remove_listener (prefs_changed_callback, display);
@@ -986,6 +1029,9 @@ meta_display_close (MetaDisplay *display,
g_source_remove (display->focus_timeout_id); g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0; display->focus_timeout_id = 0;
if (display->grab_old_window_stacking)
g_list_free (display->grab_old_window_stacking);
/* Stop caring about events */ /* Stop caring about events */
meta_display_free_events (display); meta_display_free_events (display);
@@ -1108,6 +1154,27 @@ meta_get_display (void)
return the_display; 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 gboolean
meta_grab_op_is_mouse (MetaGrabOp op) 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_NW:
case META_GRAB_OP_RESIZING_W: case META_GRAB_OP_RESIZING_W:
case META_GRAB_OP_RESIZING_E: 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; return TRUE;
default: 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_NE:
case META_GRAB_OP_KEYBOARD_RESIZING_SW: case META_GRAB_OP_KEYBOARD_RESIZING_SW:
case META_GRAB_OP_KEYBOARD_RESIZING_NW: case META_GRAB_OP_KEYBOARD_RESIZING_NW:
case META_GRAB_OP_COMPOSITOR:
return TRUE; return TRUE;
default: default:
@@ -1195,31 +1274,32 @@ meta_grab_op_is_moving (MetaGrabOp op)
} }
gboolean 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) || switch (grab_op)
meta_grab_op_is_resizing (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 gboolean
meta_grab_op_should_block_wayland (MetaGrabOp op) meta_grab_op_is_wayland (MetaGrabOp op)
{ {
switch (op) return (op != META_GRAB_OP_NONE && !meta_grab_op_is_clicking (op));
{
case META_GRAB_OP_WAYLAND_POPUP:
case META_GRAB_OP_NONE:
return FALSE;
default:
return TRUE;
}
} }
/** /**
@@ -1303,6 +1383,19 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
return timestamp; 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: * meta_display_add_ignored_crossing_serial:
* @display: a #MetaDisplay * @display: a #MetaDisplay
@@ -1392,17 +1485,54 @@ meta_display_queue_autoraise_callback (MetaDisplay *display,
meta_prefs_get_auto_raise_delay (), meta_prefs_get_auto_raise_delay (),
window_raise_with_delay_callback, window_raise_with_delay_callback,
window, NULL); window, NULL);
g_source_set_name_by_id (display->autoraise_timeout_id, "[mutter] window_raise_with_delay_callback");
display->autoraise_window = window; 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 void
meta_display_sync_wayland_input_focus (MetaDisplay *display) meta_display_sync_wayland_input_focus (MetaDisplay *display)
{ {
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWindow *focus_window = NULL; 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; focus_window = NULL;
else if (meta_display_xwindow_is_a_no_focus_window (display, display->focus_xwindow)) else if (meta_display_xwindow_is_a_no_focus_window (display, display->focus_xwindow))
focus_window = NULL; 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_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 void
@@ -1591,6 +1724,7 @@ meta_display_unregister_wayland_window (MetaDisplay *display,
g_hash_table_remove (display->wayland_windows, window); g_hash_table_remove (display->wayland_windows, window);
} }
#ifdef HAVE_XSYNC
/* We store sync alarms in the window ID hash table, because they are /* 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 * just more types of XIDs in the same global space, but we have
* typesafe functions to register/unregister for readability. * 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); g_hash_table_remove (display->xids, &alarm);
} }
#endif /* HAVE_XSYNC */
void void
meta_display_notify_window_created (MetaDisplay *display, meta_display_notify_window_created (MetaDisplay *display,
@@ -1696,34 +1831,51 @@ meta_cursor_for_grab_op (MetaGrabOp op)
void void
meta_display_set_grab_op_cursor (MetaDisplay *display, meta_display_set_grab_op_cursor (MetaDisplay *display,
MetaScreen *screen,
MetaGrabOp op, MetaGrabOp op,
Window grab_xwindow,
guint32 timestamp) guint32 timestamp)
{ {
/* Set root cursor */ unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
MetaBackend *backend = meta_get_backend (); XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (display->screen);
MetaCursor cursor = meta_cursor_for_grab_op (op); MetaCursor cursor = meta_cursor_for_grab_op (op);
MetaCursorReference *cursor_ref; MetaCursorReference *cursor_ref;
cursor_ref = meta_cursor_reference_from_theme (cursor); XISetMask (mask.mask, XI_ButtonPress);
meta_cursor_tracker_set_grab_cursor (tracker, cursor_ref); XISetMask (mask.mask, XI_ButtonRelease);
if (cursor_ref) XISetMask (mask.mask, XI_Enter);
meta_cursor_reference_unref (cursor_ref); XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_Motion);
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp)) g_assert (screen != NULL);
display->grab_have_pointer = TRUE;
}
static MetaWindow * meta_error_trap_push (display);
get_toplevel_transient_for (MetaWindow *window) if (XIGrabDevice (display->xdisplay,
{ META_VIRTUAL_CORE_POINTER_ID,
while (TRUE) 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); display->grab_have_pointer = TRUE;
if (parent == NULL) meta_topic (META_DEBUG_WINDOW_OPS,
return window; "XIGrabDevice() returned GrabSuccess time %u\n",
window = parent; 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 gboolean
@@ -1734,18 +1886,19 @@ meta_display_begin_grab_op (MetaDisplay *display,
gboolean pointer_already_grabbed, gboolean pointer_already_grabbed,
gboolean frame_action, gboolean frame_action,
int button, int button,
gulong modmask, /* XXX - ignored */ gulong modmask,
guint32 timestamp, guint32 timestamp,
int root_x, int root_x,
int root_y) int root_y)
{ {
MetaWindow *grab_window = NULL; MetaWindow *grab_window = NULL;
Window grab_xwindow;
meta_topic (META_DEBUG_WINDOW_OPS, meta_topic (META_DEBUG_WINDOW_OPS,
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n", "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, op, window ? window->desc : "none", button, pointer_already_grabbed,
root_x, root_y); root_x, root_y);
if (display->grab_op != META_GRAB_OP_NONE) if (display->grab_op != META_GRAB_OP_NONE)
{ {
if (window) 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, /* If window is a modal dialog attached to its parent,
* grab the parent instead for moving. * grab the parent instead for moving.
*/ */
if (meta_grab_op_is_moving (op)) if (window && meta_window_is_attached_dialog (window) &&
grab_window = get_toplevel_transient_for (window); meta_grab_op_is_moving (op))
grab_window = meta_window_get_transient_for (window);
g_assert (grab_window != NULL); if (grab_window == NULL)
g_assert (op != META_GRAB_OP_NONE); 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; display->grab_have_pointer = FALSE;
if (pointer_already_grabbed) if (pointer_already_grabbed)
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
/* Since grab operations often happen as a result of implicit meta_display_set_grab_op_cursor (display, screen, op, grab_xwindow, timestamp);
* 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);
if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op)) 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; return FALSE;
} }
/* Grab keys for keyboard ops and mouse move/resizes; see #126497 */ /* 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) if (!display->grab_have_keyboard)
{ {
MetaBackend *backend = meta_get_backend (); meta_topic (META_DEBUG_WINDOW_OPS,
meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer\n"); "grabbing all keys failed, ungrabbing pointer\n");
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); XIUngrabDevice (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID, timestamp);
display->grab_have_pointer = FALSE; display->grab_have_pointer = FALSE;
return FALSE; return FALSE;
} }
} }
display->grab_op = op; display->grab_op = op;
display->grab_window = grab_window; display->grab_window = grab_window;
display->grab_xwindow = grab_xwindow;
display->grab_button = button; display->grab_button = button;
display->grab_tile_mode = grab_window->tile_mode; display->grab_mask = modmask;
display->grab_tile_monitor_number = grab_window->tile_monitor_number; 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_x = root_x;
display->grab_anchor_root_y = root_y; display->grab_anchor_root_y = root_y;
display->grab_latest_motion_x = root_x; display->grab_latest_motion_x = root_x;
display->grab_latest_motion_y = root_y; display->grab_latest_motion_y = root_y;
display->grab_last_moveresize_time.tv_sec = 0; display->grab_last_moveresize_time.tv_sec = 0;
display->grab_last_moveresize_time.tv_usec = 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; display->grab_last_user_action_was_snap = FALSE;
#endif
display->grab_frame_action = frame_action; display->grab_frame_action = frame_action;
display->grab_resize_unmaximize = 0; display->grab_resize_unmaximize = 0;
display->grab_timestamp = timestamp; display->grab_timestamp = timestamp;
@@ -1837,23 +2011,40 @@ meta_display_begin_grab_op (MetaDisplay *display,
g_source_remove (display->grab_resize_timeout_id); g_source_remove (display->grab_resize_timeout_id);
display->grab_resize_timeout_id = 0; 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, meta_topic (META_DEBUG_WINDOW_OPS,
"Grab op %u on window %s successful\n", "Grab op %u on window %s successful\n",
display->grab_op, window ? window->desc : "(null)"); display->grab_op, window ? window->desc : "(null)");
meta_window_get_client_root_coords (display->grab_window, g_assert (display->grab_window != NULL);
&display->grab_initial_window_pos); g_assert (display->grab_op != META_GRAB_OP_NONE);
display->grab_anchor_window_pos = display->grab_initial_window_pos;
if (display->grab_window)
{
meta_window_refresh_resize_popup (display->grab_window);
}
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display); meta_display_sync_wayland_input_focus (display);
g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0, g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
screen, display->grab_window, display->grab_op); screen, display->grab_window, display->grab_op);
meta_window_grab_op_began (display->grab_window, display->grab_op);
return TRUE; return TRUE;
} }
@@ -1861,57 +2052,83 @@ void
meta_display_end_grab_op (MetaDisplay *display, meta_display_end_grab_op (MetaDisplay *display,
guint32 timestamp) guint32 timestamp)
{ {
MetaCursorTracker *tracker;
meta_topic (META_DEBUG_WINDOW_OPS, meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u at time %u\n", display->grab_op, timestamp); "Ending grab op %u at time %u\n", display->grab_op, timestamp);
if (display->grab_op == META_GRAB_OP_NONE) if (display->grab_op == META_GRAB_OP_NONE)
return; return;
g_signal_emit (display, display_signals[GRAB_OP_END], 0, g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, display->grab_window, display->grab_op); display->screen, display->grab_window, display->grab_op);
meta_window_grab_op_ended (display->grab_window, display->grab_op); if (display->grab_window != NULL)
display->grab_window->shaken_loose = FALSE;
if (meta_grab_op_is_moving_or_resizing (display->grab_op))
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 /* Only raise the window in orthogonal raise
* ('do-not-raise-on-click') mode if the user didn't try to move * ('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. * or resize the given window by at least a threshold amount.
* For raise on click mode, the window was raised at the * For raise on click mode, the window was raised at the
* beginning of the grab_op. * beginning of the grab_op.
*/ */
if (!meta_prefs_get_raise_on_click () && if (!display->grab_threshold_movement_reached)
display->grab_threshold_movement_reached)
meta_window_raise (display->grab_window); 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) if (display->grab_have_pointer)
{ {
MetaBackend *backend = meta_get_backend (); meta_topic (META_DEBUG_WINDOW_OPS,
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); "Ungrabbing pointer with timestamp %u\n", timestamp);
XIUngrabDevice (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID, timestamp);
} }
if (display->grab_have_keyboard) if (display->grab_have_keyboard)
{ {
meta_topic (META_DEBUG_WINDOW_OPS, meta_topic (META_DEBUG_WINDOW_OPS,
"Ungrabbing all keys timestamp %u\n", timestamp); "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 (display->screen->cursor_tracker, NULL);
meta_cursor_tracker_set_grab_cursor (tracker, NULL);
display->grab_timestamp = 0; display->grab_timestamp = 0;
display->grab_window = NULL; display->grab_window = NULL;
display->grab_xwindow = None;
display->grab_tile_mode = META_TILE_NONE; display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1; display->grab_tile_monitor_number = -1;
display->grab_op = META_GRAB_OP_NONE; 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) if (display->grab_resize_timeout_id)
{ {
g_source_remove (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 button,
int modmask) int modmask)
{ {
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned int ignored_mask; unsigned int ignored_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
@@ -1973,6 +2188,13 @@ meta_change_button_grab (MetaDisplay *display,
XISetMask (mask.mask, XI_ButtonRelease); XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion); 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; ignored_mask = 0;
while (ignored_mask <= display->ignored_modifier_mask) while (ignored_mask <= display->ignored_modifier_mask)
{ {
@@ -1989,34 +2211,45 @@ meta_change_button_grab (MetaDisplay *display,
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 }; mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (meta_is_debugging ())
meta_error_trap_push_with_return (display);
/* GrabModeSync means freeze until XAllowEvents */ /* GrabModeSync means freeze until XAllowEvents */
if (grab) if (grab)
XIGrabButton (xdisplay, XIGrabButton (display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID, META_VIRTUAL_CORE_POINTER_ID,
button, xwindow, None, button, xwindow, None,
sync ? XIGrabModeSync : XIGrabModeAsync, sync ? XIGrabModeSync : XIGrabModeAsync,
XIGrabModeAsync, False, XIGrabModeAsync, False,
&mask, 1, &mods); &mask, 1, &mods);
else else
XIUngrabButton (xdisplay, XIUngrabButton (display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID, META_VIRTUAL_CORE_POINTER_ID,
button, xwindow, 1, &mods); 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; ++ignored_mask;
} }
meta_error_trap_pop (display);
} }
void void
meta_display_grab_window_buttons (MetaDisplay *display, meta_display_grab_window_buttons (MetaDisplay *display,
Window xwindow) 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 + button1 for moving window.
* Grab Alt + button2 for resizing window. * Grab Alt + button2 for resizing window.
* Grab Alt + button3 for popping up window menu. * Grab Alt + button3 for popping up window menu.
@@ -2067,12 +2300,6 @@ void
meta_display_ungrab_window_buttons (MetaDisplay *display, meta_display_ungrab_window_buttons (MetaDisplay *display,
Window xwindow) Window xwindow)
{ {
MetaBackend *backend = meta_get_backend ();
/* Do nothing under non-X11 backends */
if (!META_IS_BACKEND_X11 (backend))
return;
gboolean debug; gboolean debug;
int i; int i;
@@ -2101,12 +2328,6 @@ void
meta_display_grab_focus_window_button (MetaDisplay *display, meta_display_grab_focus_window_button (MetaDisplay *display,
MetaWindow *window) 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 */ /* Grab button 1 for activating unfocused windows */
meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc); meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc);
@@ -2156,12 +2377,6 @@ void
meta_display_ungrab_focus_window_button (MetaDisplay *display, meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window) 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); meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc);
if (!window->have_focus_click_grab) if (!window->have_focus_click_grab)
@@ -2238,32 +2453,16 @@ meta_display_retheme_all (void)
meta_display_queue_retheme_all_windows (meta_get_display ()); meta_display_queue_retheme_all_windows (meta_get_display ());
} }
static void void
set_cursor_theme (Display *xdisplay) meta_display_set_cursor_theme (const char *theme,
int size)
{ {
XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ()); MetaDisplay *display = meta_get_display ();
XcursorSetDefaultSize (xdisplay, meta_prefs_get_cursor_size ());
}
static void XcursorSetTheme (display->xdisplay, theme);
update_cursor_theme (void) XcursorSetDefaultSize (display->xdisplay, size);
{
{
MetaDisplay *display = meta_get_display ();
set_cursor_theme (display->xdisplay);
if (display->screen) meta_screen_update_cursor (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);
}
}
} }
/* /*
@@ -2401,7 +2600,6 @@ meta_display_ping_window (MetaWindow *window,
ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY, ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
meta_display_ping_timeout, meta_display_ping_timeout,
ping_data); 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); display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
@@ -2883,6 +3081,7 @@ meta_display_devirtualize_modifiers (MetaDisplay *display,
static void static void
update_window_grab_modifiers (MetaDisplay *display) update_window_grab_modifiers (MetaDisplay *display)
{ {
MetaVirtualModifier virtual_mods; MetaVirtualModifier virtual_mods;
unsigned int mods; unsigned int mods;
@@ -2946,11 +3145,6 @@ prefs_changed_callback (MetaPreference pref,
{ {
meta_bell_set_audible (display, meta_prefs_bell_is_audible ()); 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 void
@@ -3193,11 +3387,13 @@ meta_display_get_damage_event_base (MetaDisplay *display)
return display->damage_event_base; return display->damage_event_base;
} }
#ifdef HAVE_SHAPE
int int
meta_display_get_shape_event_base (MetaDisplay *display) meta_display_get_shape_event_base (MetaDisplay *display)
{ {
return display->shape_event_base; return display->shape_event_base;
} }
#endif
/** /**
* meta_display_clear_mouse_mode: * meta_display_clear_mouse_mode:
@@ -3213,10 +3409,3 @@ meta_display_clear_mouse_mode (MetaDisplay *display)
{ {
display->mouse_mode = FALSE; display->mouse_mode = FALSE;
} }
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
}

View File

@@ -437,8 +437,6 @@ apply_edge_resistance (MetaWindow *window,
g_timeout_add (timeout_length_ms, g_timeout_add (timeout_length_ms,
edge_resistance_timeout, edge_resistance_timeout,
resistance_data); resistance_data);
g_source_set_name_by_id (resistance_data->timeout_id,
"[mutter] edge_resistance_timeout");
resistance_data->timeout_setup = TRUE; resistance_data->timeout_setup = TRUE;
resistance_data->timeout_edge_pos = compare; resistance_data->timeout_edge_pos = compare;
resistance_data->timeout_over = FALSE; resistance_data->timeout_over = FALSE;

View File

@@ -55,6 +55,12 @@ meta_error_trap_pop (MetaDisplay *display)
gdk_error_trap_pop_ignored (); gdk_error_trap_pop_ignored ();
} }
void
meta_error_trap_push_with_return (MetaDisplay *display)
{
gdk_error_trap_push ();
}
int int
meta_error_trap_pop_with_return (MetaDisplay *display) meta_error_trap_pop_with_return (MetaDisplay *display)
{ {

View File

@@ -25,20 +25,20 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/extensions/Xdamage.h> #include <X11/extensions/Xdamage.h>
#ifdef HAVE_SHAPE
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#endif
#include <meta/errors.h> #include <meta/errors.h>
#include "display-private.h" #include "display-private.h"
#include "window-private.h" #include "window-private.h"
#include "bell.h" #include "bell.h"
#include "workspace-private.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/native/meta-idle-monitor-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "x11/window-x11.h" #include "x11/window-x11.h"
#include "x11/xprops.h" #include "x11/xprops.h"
#include "wayland/meta-xwayland.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "meta-surface-actor-wayland.h" #include "meta-surface-actor-wayland.h"
@@ -213,12 +213,14 @@ event_get_modified_window (MetaDisplay *display,
return None; return None;
default: default:
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display) && if (META_DISPLAY_HAS_SHAPE (display) &&
event->type == (display->shape_event_base + ShapeNotify)) event->type == (display->shape_event_base + ShapeNotify))
{ {
XShapeEvent *sev = (XShapeEvent*) event; XShapeEvent *sev = (XShapeEvent*) event;
return sev->window; return sev->window;
} }
#endif
return None; return None;
} }
@@ -348,6 +350,7 @@ stack_mode_to_string (int mode)
return "Unknown"; return "Unknown";
} }
#ifdef HAVE_XSYNC
G_GNUC_UNUSED static gint64 G_GNUC_UNUSED static gint64
sync_value_to_64 (const XSyncValue *value) sync_value_to_64 (const XSyncValue *value)
{ {
@@ -374,6 +377,7 @@ alarm_state_to_string (XSyncAlarmState state)
return "(unknown)"; return "(unknown)";
} }
} }
#endif /* HAVE_XSYNC */
G_GNUC_UNUSED static void G_GNUC_UNUSED static void
meta_spew_xi2_event (MetaDisplay *display, meta_spew_xi2_event (MetaDisplay *display,
@@ -607,6 +611,7 @@ meta_spew_core_event (MetaDisplay *display,
name = "MappingNotify"; name = "MappingNotify";
break; break;
default: default:
#ifdef HAVE_XSYNC
if (META_DISPLAY_HAS_XSYNC (display) && if (META_DISPLAY_HAS_XSYNC (display) &&
event->type == (display->xsync_event_base + XSyncAlarmNotify)) event->type == (display->xsync_event_base + XSyncAlarmNotify))
{ {
@@ -625,6 +630,8 @@ meta_spew_core_event (MetaDisplay *display,
alarm_state_to_string (aevent->state)); alarm_state_to_string (aevent->state));
} }
else else
#endif /* HAVE_XSYNC */
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display) && if (META_DISPLAY_HAS_SHAPE (display) &&
event->type == (display->shape_event_base + ShapeNotify)) event->type == (display->shape_event_base + ShapeNotify))
{ {
@@ -644,6 +651,7 @@ meta_spew_core_event (MetaDisplay *display,
sev->shaped); sev->shaped);
} }
else else
#endif /* HAVE_SHAPE */
{ {
name = "(Unknown event)"; name = "(Unknown event)";
extra = g_strdup_printf ("type: %d", event->xany.type); extra = g_strdup_printf ("type: %d", event->xany.type);
@@ -851,24 +859,9 @@ handle_input_xevent (MetaDisplay *display,
if (input_event == NULL) if (input_event == NULL)
return FALSE; 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); modified = xievent_get_modified_window (display, input_event);
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL; 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) switch (input_event->evtype)
{ {
case XI_Enter: 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) */ return FALSE;
if (window && window->frame && modified == window->frame->xwindow)
return FALSE;
/* Don't pass these events through to Clutter / GTK+ */
return TRUE;
} }
static void static void
@@ -1050,7 +1040,7 @@ convert_property (MetaDisplay *display,
conversion_targets[2] = display->atom_TIMESTAMP; conversion_targets[2] = display->atom_TIMESTAMP;
conversion_targets[3] = display->atom_VERSION; conversion_targets[3] = display->atom_VERSION;
meta_error_trap_push (display); meta_error_trap_push_with_return (display);
if (target == display->atom_TARGETS) if (target == display->atom_TARGETS)
XChangeProperty (display->xdisplay, w, property, XChangeProperty (display->xdisplay, w, property,
XA_ATOM, 32, PropModeReplace, XA_ATOM, 32, PropModeReplace,
@@ -1125,7 +1115,7 @@ process_selection_request (MetaDisplay *display,
unsigned long num, rest; unsigned long num, rest;
unsigned char *data; unsigned char *data;
meta_error_trap_push (display); meta_error_trap_push_with_return (display);
if (XGetWindowProperty (display->xdisplay, if (XGetWindowProperty (display->xdisplay,
event->xselectionrequest.requestor, event->xselectionrequest.requestor,
event->xselectionrequest.property, 0, 256, False, event->xselectionrequest.property, 0, 256, False,
@@ -1239,6 +1229,7 @@ handle_other_xevent (MetaDisplay *display,
window = NULL; window = NULL;
} }
#ifdef HAVE_XSYNC
if (META_DISPLAY_HAS_XSYNC (display) && if (META_DISPLAY_HAS_XSYNC (display) &&
event->type == (display->xsync_event_base + XSyncAlarmNotify)) event->type == (display->xsync_event_base + XSyncAlarmNotify))
{ {
@@ -1250,13 +1241,17 @@ handle_other_xevent (MetaDisplay *display,
XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value; XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value;
gint64 new_counter_value; gint64 new_counter_value;
new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32); 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 */ bypass_gtk = TRUE; /* GTK doesn't want to see this really */
} }
else
meta_idle_monitor_xsync_handle_xevent_all (event);
goto out; goto out;
} }
#endif /* HAVE_XSYNC */
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display) && if (META_DISPLAY_HAS_SHAPE (display) &&
event->type == (display->shape_event_base + ShapeNotify)) event->type == (display->shape_event_base + ShapeNotify))
{ {
@@ -1281,6 +1276,7 @@ handle_other_xevent (MetaDisplay *display,
goto out; goto out;
} }
#endif /* HAVE_SHAPE */
switch (event->type) switch (event->type)
{ {
@@ -1497,6 +1493,11 @@ handle_other_xevent (MetaDisplay *display,
event->xproperty.atom == event->xproperty.atom ==
display->atom__XKB_RULES_NAMES) display->atom__XKB_RULES_NAMES)
reload_xkb_rules (display->screen); 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 /* we just use this property as a sentinel to avoid
* certain race conditions. See the comment for the * certain race conditions. See the comment for the
@@ -1510,6 +1511,21 @@ handle_other_xevent (MetaDisplay *display,
} }
} }
break; 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: case SelectionRequest:
process_selection_request (display, event); process_selection_request (display, event);
break; break;
@@ -1520,12 +1536,7 @@ handle_other_xevent (MetaDisplay *display,
case ClientMessage: case ClientMessage:
if (window) if (window)
{ {
if (event->xclient.message_type == display->atom_WL_SURFACE_ID) if (!frame_was_receiver)
{
guint32 surface_id = event->xclient.data.l[0];
meta_xwayland_handle_wl_surface_id (window, surface_id);
}
else if (!frame_was_receiver)
meta_window_x11_client_message (window, event); meta_window_x11_client_message (window, event);
} }
else else
@@ -1688,7 +1699,7 @@ grab_op_should_block_mouse_events (MetaGrabOp op)
{ {
switch (op) switch (op)
{ {
case META_GRAB_OP_WAYLAND_POPUP: case META_GRAB_OP_WAYLAND_CLIENT:
case META_GRAB_OP_COMPOSITOR: case META_GRAB_OP_COMPOSITOR:
return TRUE; return TRUE;
@@ -1730,19 +1741,28 @@ meta_display_handle_xevent (MetaDisplay *display,
Window modified; Window modified;
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE; gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
XIEvent *input_event; XIEvent *input_event;
MetaMonitorManager *monitor;
#if 0 #if 0
meta_spew_event (display, event); meta_spew_event (display, event);
#endif #endif
#ifdef HAVE_STARTUP_NOTIFICATION #ifdef HAVE_STARTUP_NOTIFICATION
if (sn_display_process_event (display->sn_display, event)) sn_display_process_event (display->sn_display, event);
{
bypass_gtk = bypass_compositor = TRUE;
goto out;
}
#endif #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; display->monitor_cache_invalidated = TRUE;
if (display->focused_by_us && if (display->focused_by_us &&
@@ -1818,17 +1838,6 @@ meta_display_handle_xevent (MetaDisplay *display,
goto out; 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: out:
if (!bypass_compositor) if (!bypass_compositor)
{ {
@@ -1838,7 +1847,7 @@ meta_display_handle_xevent (MetaDisplay *display,
bypass_gtk = TRUE; bypass_gtk = TRUE;
} }
display->current_time = event_get_time (display, event); display->current_time = CurrentTime;
return bypass_gtk; return bypass_gtk;
} }
@@ -1850,10 +1859,8 @@ handle_idletime_for_event (const ClutterEvent *event)
int device_id; int device_id;
/* This is handled by XSync under X11. */ /* This is handled by XSync under X11. */
#if defined(CLUTTER_WINDOWING_X11) if (!meta_is_wayland_compositor ())
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
return; return;
#endif
device = clutter_event_get_device (event); device = clutter_event_get_device (event);
if (device == NULL) 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) switch (event->type)
{ {
case CLUTTER_BUTTON_PRESS: case CLUTTER_BUTTON_PRESS:
@@ -1935,7 +1931,24 @@ meta_display_handle_event (MetaDisplay *display,
display->overlay_key_only_pressed = FALSE; 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; ClutterModifierType grab_mask;
gboolean unmodified; gboolean unmodified;
@@ -1996,16 +2009,8 @@ meta_display_handle_event (MetaDisplay *display,
meta_verbose ("Allowing events time %u\n", meta_verbose ("Allowing events time %u\n",
(unsigned int)event->button.time); (unsigned int)event->button.time);
{ XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device),
MetaBackend *backend = meta_get_backend (); XIReplayDevice, event->button.time);
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);
}
}
bypass_clutter = TRUE; bypass_clutter = TRUE;
} }
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ()) 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; break;
case CLUTTER_BUTTON_RELEASE: case CLUTTER_BUTTON_RELEASE:
if (grab_op_should_block_mouse_events (display->grab_op)) if (grab_op_should_block_mouse_events (display->grab_op))
break; break;
display->overlay_key_only_pressed = FALSE; 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; break;
case CLUTTER_KEY_PRESS: case CLUTTER_KEY_PRESS:
@@ -2113,19 +2137,17 @@ meta_display_handle_event (MetaDisplay *display,
bypass_clutter = TRUE; bypass_clutter = TRUE;
bypass_wayland = TRUE; bypass_wayland = TRUE;
} }
break;
default: default:
break; break;
} }
out:
/* If the compositor has a grab, don't pass that through to Wayland */ /* If the compositor has a grab, don't pass that through to Wayland */
if (display->grab_op == META_GRAB_OP_COMPOSITOR) if (display->grab_op == META_GRAB_OP_COMPOSITOR)
bypass_wayland = TRUE; bypass_wayland = TRUE;
/* If a Wayland client has a grab, don't pass that through to Clutter */ /* 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; bypass_clutter = TRUE;
if (compositor && !bypass_wayland) if (compositor && !bypass_wayland)

View File

@@ -27,6 +27,8 @@
#include <meta/errors.h> #include <meta/errors.h>
#include "keybindings-private.h" #include "keybindings-private.h"
#include <X11/extensions/Xrender.h>
#define EVENT_MASK (SubstructureRedirectMask | \ #define EVENT_MASK (SubstructureRedirectMask | \
StructureNotifyMask | SubstructureNotifyMask | \ StructureNotifyMask | SubstructureNotifyMask | \
ExposureMask | \ ExposureMask | \

View File

@@ -94,6 +94,10 @@ void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display); void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen); void meta_screen_grab_keys (MetaScreen *screen);
void meta_screen_ungrab_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_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window); void meta_window_ungrab_keys (MetaWindow *window);
gboolean meta_window_grab_all_keys (MetaWindow *window, gboolean meta_window_grab_all_keys (MetaWindow *window,

View File

@@ -41,23 +41,18 @@
#include "screen-private.h" #include "screen-private.h"
#include <meta/prefs.h> #include <meta/prefs.h>
#include "util-private.h" #include "util-private.h"
#include "meta-accel-parse.h"
#include <X11/keysym.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <linux/input.h>
#include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKB #ifdef HAVE_XKB
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#endif #endif
#include "wayland/meta-wayland.h" #include "wayland/meta-wayland.h"
#include "backends/x11/meta-backend-x11.h" #include "meta-backend.h"
#include "backends/native/meta-backend-native.h"
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings" #define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings" #define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
@@ -187,6 +182,10 @@ reload_keymap (MetaDisplay *display)
if (display->keymap) if (display->keymap)
meta_XFree (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->keymap = XGetKeyboardMapping (display->xdisplay,
display->min_keycode, display->min_keycode,
display->max_keycode - display->max_keycode -
@@ -194,27 +193,24 @@ reload_keymap (MetaDisplay *display)
&display->keysyms_per_keycode); &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 static void
reload_modmap (MetaDisplay *display) reload_modmap (MetaDisplay *display)
{ {
XModifierKeymap *modmap; XModifierKeymap *modmap;
int map_size; int map_size;
int i; int i;
int num_lock_mask = 0;
int scroll_lock_mask = 0; if (display->modmap)
XFreeModifiermap (display->modmap);
modmap = XGetModifierMapping (display->xdisplay); modmap = XGetModifierMapping (display->xdisplay);
display->modmap = modmap;
display->ignored_modifier_mask = 0; display->ignored_modifier_mask = 0;
/* Multiple bits may get set in each of these */ /* Multiple bits may get set in each of these */
display->num_lock_mask = 0;
display->scroll_lock_mask = 0;
display->meta_mask = 0; display->meta_mask = 0;
display->hyper_mask = 0; display->hyper_mask = 0;
display->super_mask = 0; display->super_mask = 0;
@@ -242,37 +238,40 @@ reload_modmap (MetaDisplay *display)
{ {
if (syms[j] != 0) if (syms[j] != 0)
{ {
const char *str;
str = XKeysymToString (syms[j]);
meta_topic (META_DEBUG_KEYBINDINGS, meta_topic (META_DEBUG_KEYBINDINGS,
"Keysym %s bound to modifier 0x%x\n", "Keysym %s bound to modifier 0x%x\n",
keysym_name (syms[j]), str ? str : "none",
(1 << ( i / modmap->max_keypermod))); (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 /* Mod1Mask is 1 << 3 for example, i.e. the
* fourth modifier, i / keyspermod is the modifier * fourth modifier, i / keyspermod is the modifier
* index * 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 || else if (syms[j] == XK_Super_L ||
syms[j] == XKB_KEY_Super_R) syms[j] == XK_Super_R)
{ {
display->super_mask |= (1 << ( i / modmap->max_keypermod)); display->super_mask |= (1 << ( i / modmap->max_keypermod));
} }
else if (syms[j] == XKB_KEY_Hyper_L || else if (syms[j] == XK_Hyper_L ||
syms[j] == XKB_KEY_Hyper_R) syms[j] == XK_Hyper_R)
{ {
display->hyper_mask |= (1 << ( i / modmap->max_keypermod)); display->hyper_mask |= (1 << ( i / modmap->max_keypermod));
} }
else if (syms[j] == XKB_KEY_Meta_L || else if (syms[j] == XK_Meta_L ||
syms[j] == XKB_KEY_Meta_R) syms[j] == XK_Meta_R)
{ {
display->meta_mask |= (1 << ( i / modmap->max_keypermod)); display->meta_mask |= (1 << ( i / modmap->max_keypermod));
} }
@@ -284,20 +283,18 @@ reload_modmap (MetaDisplay *display)
++i; ++i;
} }
display->ignored_modifier_mask = (num_lock_mask | display->ignored_modifier_mask = (display->num_lock_mask |
scroll_lock_mask | display->scroll_lock_mask |
LockMask); LockMask);
meta_topic (META_DEBUG_KEYBINDINGS, 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", "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, display->ignored_modifier_mask,
num_lock_mask, display->num_lock_mask,
scroll_lock_mask, display->scroll_lock_mask,
display->hyper_mask, display->hyper_mask,
display->super_mask, display->super_mask,
display->meta_mask); display->meta_mask);
XFreeModifiermap (modmap);
} }
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in /* 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)); 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; keycode = display->min_keycode;
while (keycode <= display->max_keycode) while (keycode <= display->max_keycode)
{ {
@@ -338,31 +327,12 @@ get_keycodes_for_keysym (MetaDisplay *display,
++keycode; ++keycode;
} }
out:
n_keycodes = retval->len; n_keycodes = retval->len;
*keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE); *keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
return n_keycodes; 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 static void
reload_iso_next_group_combos (MetaDisplay *display) reload_iso_next_group_combos (MetaDisplay *display)
{ {
@@ -380,7 +350,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
if (iso_next_group_option == NULL) if (iso_next_group_option == NULL)
return; 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") || if (g_str_equal (iso_next_group_option, "toggle") ||
g_str_equal (iso_next_group_option, "lalt_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) 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].keycode = keycodes[i];
combos[i].modifiers = 0; combos[i].modifiers = 0;
} }
@@ -412,7 +382,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
for (i = 0; i < n_keycodes; ++i) 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].keycode = keycodes[i];
combos[i].modifiers = ShiftMask; combos[i].modifiers = ShiftMask;
} }
@@ -425,7 +395,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
for (i = 0; i < n_keycodes; ++i) 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].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask; combos[i].modifiers = Mod1Mask;
} }
@@ -439,11 +409,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
for (i = 0; i < n_keycodes; ++i) 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].keycode = keycodes[i];
combos[i].modifiers = ShiftMask; 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].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask; combos[i + n_keycodes].modifiers = ControlMask;
} }
@@ -455,11 +425,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
for (i = 0; i < n_keycodes; ++i) 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].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask; 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].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask; combos[i + n_keycodes].modifiers = ControlMask;
} }
@@ -472,11 +442,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
for (i = 0; i < n_keycodes; ++i) 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].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask; 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].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ShiftMask; combos[i + n_keycodes].modifiers = ShiftMask;
} }
@@ -493,6 +463,16 @@ reload_iso_next_group_combos (MetaDisplay *display)
display->iso_next_group_combos = combos; 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 static void
binding_reload_keycode_foreach (gpointer key, binding_reload_keycode_foreach (gpointer key,
gpointer value, gpointer value,
@@ -502,7 +482,7 @@ binding_reload_keycode_foreach (gpointer key,
MetaKeyBinding *binding = value; MetaKeyBinding *binding = value;
if (binding->keysym) if (binding->keysym)
binding->keycode = get_first_keycode_for_keysym (display, binding->keysym); binding->keycode = keysym_to_keycode (display, binding->keysym);
} }
static void static void
@@ -514,7 +494,7 @@ reload_keycodes (MetaDisplay *display)
if (display->overlay_key_combo.keysym != 0) if (display->overlay_key_combo.keysym != 0)
{ {
display->overlay_key_combo.keycode = 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 else
{ {
@@ -704,6 +684,8 @@ ungrab_key_bindings (MetaDisplay *display)
GSList *tmp; GSList *tmp;
GSList *windows; GSList *windows;
meta_error_trap_push (display); /* for efficiency push outer trap */
meta_screen_ungrab_keys (display->screen); meta_screen_ungrab_keys (display->screen);
windows = meta_display_list_windows (display, META_LIST_DEFAULT); windows = meta_display_list_windows (display, META_LIST_DEFAULT);
@@ -716,6 +698,7 @@ ungrab_key_bindings (MetaDisplay *display)
tmp = tmp->next; tmp = tmp->next;
} }
meta_error_trap_pop (display);
g_slist_free (windows); g_slist_free (windows);
} }
@@ -726,6 +709,8 @@ grab_key_bindings (MetaDisplay *display)
GSList *tmp; GSList *tmp;
GSList *windows; GSList *windows;
meta_error_trap_push (display); /* for efficiency push outer trap */
meta_screen_grab_keys (display->screen); meta_screen_grab_keys (display->screen);
windows = meta_display_list_windows (display, META_LIST_DEFAULT); windows = meta_display_list_windows (display, META_LIST_DEFAULT);
@@ -738,6 +723,7 @@ grab_key_bindings (MetaDisplay *display)
tmp = tmp->next; tmp = tmp->next;
} }
meta_error_trap_pop (display);
g_slist_free (windows); g_slist_free (windows);
} }
@@ -756,8 +742,7 @@ display_get_keybinding (MetaDisplay *display,
} }
static guint static guint
next_dynamic_keybinding_action (void) next_dynamic_keybinding_action () {
{
static guint num_dynamic_bindings = 0; static guint num_dynamic_bindings = 0;
return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings); return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings);
} }
@@ -1006,15 +991,32 @@ bindings_changed_callback (MetaPreference pref,
void void
meta_display_shutdown_keys (MetaDisplay *display) meta_display_shutdown_keys (MetaDisplay *display)
{ {
/* Note that display->xdisplay is invalid in this function */
meta_prefs_remove_listener (bindings_changed_callback, display); meta_prefs_remove_listener (bindings_changed_callback, display);
if (display->keymap) if (display->keymap)
meta_XFree (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_index);
g_hash_table_destroy (display->key_bindings); 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. */ /* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
static void static void
meta_change_keygrab (MetaDisplay *display, meta_change_keygrab (MetaDisplay *display,
@@ -1032,9 +1034,6 @@ meta_change_keygrab (MetaDisplay *display,
XISetMask (mask.mask, XI_KeyPress); XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease); 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 /* Grab keycode/modmask, together with
* all combinations of ignored modifiers. * all combinations of ignored modifiers.
* X provides no better way to do this. * X provides no better way to do this.
@@ -1046,6 +1045,9 @@ meta_change_keygrab (MetaDisplay *display,
keysym_name (keysym), keycode, keysym_name (keysym), keycode,
modmask, xwindow); modmask, xwindow);
/* efficiency, avoid so many XSync() */
meta_error_trap_push (display);
ignored_mask = 0; ignored_mask = 0;
while (ignored_mask <= display->ignored_modifier_mask) while (ignored_mask <= display->ignored_modifier_mask)
{ {
@@ -1062,19 +1064,40 @@ meta_change_keygrab (MetaDisplay *display,
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 }; mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
if (meta_is_debugging ())
meta_error_trap_push_with_return (display);
if (grab) if (grab)
XIGrabKeycode (xdisplay, XIGrabKeycode (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID, META_VIRTUAL_CORE_KEYBOARD_ID,
keycode, xwindow, keycode, xwindow,
XIGrabModeSync, XIGrabModeAsync, XIGrabModeSync, XIGrabModeAsync,
False, &mask, 1, &mods); False, &mask, 1, &mods);
else else
XIUngrabKeycode (xdisplay, XIUngrabKeycode (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID, META_VIRTUAL_CORE_KEYBOARD_ID,
keycode, xwindow, 1, &mods); 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; ++ignored_mask;
} }
meta_error_trap_pop (display);
} }
typedef struct typedef struct
@@ -1117,7 +1140,9 @@ change_binding_keygrabs (MetaDisplay *display,
data.binding_per_window = binding_per_window; data.binding_per_window = binding_per_window;
data.grab = grab; data.grab = grab;
meta_error_trap_push (display);
g_hash_table_foreach (display->key_bindings, change_keygrab_foreach, &data); g_hash_table_foreach (display->key_bindings, change_keygrab_foreach, &data);
meta_error_trap_pop (display);
} }
static void static void
@@ -1154,9 +1179,7 @@ meta_screen_change_keygrabs (MetaScreen *screen,
void void
meta_screen_grab_keys (MetaScreen *screen) meta_screen_grab_keys (MetaScreen *screen)
{ {
MetaBackend *backend = meta_get_backend (); if (screen->all_keys_grabbed)
if (!META_IS_BACKEND_X11 (backend))
return; return;
if (screen->keys_grabbed) if (screen->keys_grabbed)
@@ -1189,11 +1212,6 @@ meta_window_change_keygrabs (MetaWindow *window,
void void
meta_window_grab_keys (MetaWindow *window) meta_window_grab_keys (MetaWindow *window)
{ {
MetaBackend *backend = meta_get_backend ();
if (!META_IS_BACKEND_X11 (backend))
return;
if (window->all_keys_grabbed) if (window->all_keys_grabbed)
return; return;
@@ -1266,7 +1284,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
guint mask = 0; guint mask = 0;
MetaVirtualModifier modifiers = 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, meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse accelerator\n"); "Failed to parse accelerator\n");
@@ -1276,7 +1294,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
} }
meta_display_devirtualize_modifiers (display, modifiers, &mask); meta_display_devirtualize_modifiers (display, modifiers, &mask);
keycode = get_first_keycode_for_keysym (display, keysym); keycode = keysym_to_keycode (display, keysym);
if (keycode == 0) if (keycode == 0)
return META_KEYBINDING_ACTION_NONE; return META_KEYBINDING_ACTION_NONE;
@@ -1328,7 +1346,7 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
return FALSE; return FALSE;
meta_display_devirtualize_modifiers (display, grab->combo->modifiers, &mask); 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); binding = display_get_keybinding (display, keycode, mask);
if (binding) if (binding)
@@ -1352,12 +1370,35 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
return TRUE; 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 static gboolean
grab_keyboard (MetaDisplay *display, grab_keyboard (MetaDisplay *display,
Window xwindow, Window xwindow,
guint32 timestamp, guint32 timestamp,
int grab_mode) int grab_mode)
{ {
int result;
int grab_status; int grab_status;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; 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 /* Grab the keyboard, so we get key releases and all key
* presses * presses
*/ */
meta_error_trap_push_with_return (display);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
/* Strictly, we only need to set grab_mode on the keyboard device /* Strictly, we only need to set grab_mode on the keyboard device
* while the pointer should always be XIGrabModeAsync. Unfortunately * 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 * http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
*/ */
grab_status = XIGrabDevice (xdisplay, grab_status = XIGrabDevice (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID, META_VIRTUAL_CORE_KEYBOARD_ID,
xwindow, xwindow,
timestamp, timestamp,
@@ -1391,16 +1430,82 @@ grab_keyboard (MetaDisplay *display,
False, /* owner_events */ False, /* owner_events */
&mask); &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 static void
ungrab_keyboard (MetaDisplay *display, guint32 timestamp) ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
{ {
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); meta_error_trap_push (display);
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
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 gboolean
@@ -1409,9 +1514,9 @@ meta_window_grab_all_keys (MetaWindow *window,
{ {
Window grabwindow; Window grabwindow;
gboolean retval; 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; return TRUE;
if (window->all_keys_grabbed) if (window->all_keys_grabbed)
@@ -1474,45 +1579,40 @@ meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
void void
meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp) meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
{ {
MetaBackend *backend = meta_get_backend (); meta_error_trap_push (display);
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
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,
XIAsyncDevice, timestamp); XIAsyncDevice, timestamp);
/* We shouldn't need to unfreeze the pointer device here, however we /* We shouldn't need to unfreeze the pointer device here, however we
* have to, due to the workaround we do in grab_keyboard(). * 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); XIAsyncDevice, timestamp);
meta_error_trap_pop (display);
} }
static gboolean 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: if (keycode == display->modmap->modifiermap[i])
case XKB_KEY_Shift_R: {
case XKB_KEY_Control_L: retval = TRUE;
case XKB_KEY_Control_R: break;
case XKB_KEY_Caps_Lock: }
case XKB_KEY_Shift_Lock: ++i;
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;
} }
return retval;
} }
static void static void
@@ -1593,13 +1693,6 @@ process_overlay_key (MetaDisplay *display,
ClutterKeyEvent *event, ClutterKeyEvent *event,
MetaWindow *window) 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 (display->overlay_key_only_pressed)
{ {
if (event->hardware_keycode != (int)display->overlay_key_combo.keycode) 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 * binding, we unfreeze the keyboard but keep the grab
* (this is important for something like cycling * (this is important for something like cycling
* windows */ * windows */
XIAllowEvents (xdisplay, XIAllowEvents (display->xdisplay,
clutter_input_device_get_device_id (event->device), clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time); XIAsyncDevice, event->time);
} }
@@ -1632,7 +1725,7 @@ process_overlay_key (MetaDisplay *display,
{ {
/* Replay the event so it gets delivered to our /* Replay the event so it gets delivered to our
* per-window key bindings or to the application */ * per-window key bindings or to the application */
XIAllowEvents (xdisplay, XIAllowEvents (display->xdisplay,
clutter_input_device_get_device_id (event->device), clutter_input_device_get_device_id (event->device),
XIReplayDevice, event->time); 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 /* We want to unfreeze events, but keep the grab so that if the user
* starts typing into the overlay we get all the keys */ * starts typing into the overlay we get all the keys */
XIAllowEvents (xdisplay, XIAllowEvents (display->xdisplay,
clutter_input_device_get_device_id (event->device), clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time); XIAsyncDevice, event->time);
binding = display_get_keybinding (display, binding = display_get_keybinding (display,
display->overlay_key_combo.keycode, display->overlay_key_combo.keycode,
0); display->grab_mask);
if (binding && if (binding &&
meta_compositor_filter_keybinding (display->compositor, binding)) meta_compositor_filter_keybinding (display->compositor, binding))
return TRUE; return TRUE;
@@ -1671,7 +1764,7 @@ process_overlay_key (MetaDisplay *display,
* *
* https://bugzilla.gnome.org/show_bug.cgi?id=666101 * https://bugzilla.gnome.org/show_bug.cgi?id=666101
*/ */
XIAllowEvents (xdisplay, XIAllowEvents (display->xdisplay,
clutter_input_device_get_device_id (event->device), clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time); XIAsyncDevice, event->time);
} }
@@ -1684,7 +1777,7 @@ process_overlay_key (MetaDisplay *display,
display->overlay_key_only_pressed = TRUE; display->overlay_key_only_pressed = TRUE;
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard /* 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 */ * 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), clutter_input_device_get_device_id (event->device),
XISyncDevice, event->time); XISyncDevice, event->time);
@@ -1716,7 +1809,9 @@ process_iso_next_group (MetaDisplay *display,
remain frozen. It's the signal handler's responsibility remain frozen. It's the signal handler's responsibility
to unfreeze it. */ to unfreeze it. */
if (!meta_display_modifiers_accelerator_activate (display)) 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; activate = TRUE;
break; break;
} }
@@ -1753,7 +1848,7 @@ meta_display_process_key_event (MetaDisplay *display,
screen = display->screen; 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) if (!all_keys_grabbed)
{ {
handled = process_overlay_key (display, screen, event, window); handled = process_overlay_key (display, screen, event, window);
@@ -1765,16 +1860,9 @@ meta_display_process_key_event (MetaDisplay *display,
return TRUE; return TRUE;
} }
{ XIAllowEvents (display->xdisplay,
MetaBackend *backend = meta_get_backend (); clutter_input_device_get_device_id (event->device),
if (META_IS_BACKEND_X11 (backend)) XIAsyncDevice, event->time);
{
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
XIAllowEvents (xdisplay,
clutter_input_device_get_device_id (event->device),
XIAsyncDevice, event->time);
}
}
keep_grab = TRUE; keep_grab = TRUE;
if (all_keys_grabbed) if (all_keys_grabbed)
@@ -1902,7 +1990,7 @@ process_keyboard_move_grab (MetaDisplay *display,
return TRUE; return TRUE;
/* don't end grab on modifier key presses */ /* don't end grab on modifier key presses */
if (is_modifier (event->keyval)) if (is_modifier (display, event->hardware_keycode))
return TRUE; return TRUE;
meta_window_get_position (window, &x, &y); meta_window_get_position (window, &x, &y);
@@ -2144,7 +2232,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
return TRUE; return TRUE;
/* don't end grab on modifier key presses */ /* don't end grab on modifier key presses */
if (is_modifier (event->keyval)) if (is_modifier (display, event->hardware_keycode))
return TRUE; return TRUE;
if (event->keyval == CLUTTER_KEY_Escape) if (event->keyval == CLUTTER_KEY_Escape)
@@ -2358,19 +2446,6 @@ process_keyboard_resize_grab (MetaDisplay *display,
return handled; 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 static void
handle_switch_to_workspace (MetaDisplay *display, handle_switch_to_workspace (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
@@ -2382,19 +2457,7 @@ handle_switch_to_workspace (MetaDisplay *display,
gint which = binding->handler->data; gint which = binding->handler->data;
MetaWorkspace *workspace; MetaWorkspace *workspace;
if (which < 0) workspace = meta_screen_get_workspace_by_index (screen, which);
{
/* 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);
}
if (workspace) if (workspace)
{ {
@@ -2955,26 +3018,6 @@ handle_toggle_on_all_workspaces (MetaDisplay *display,
meta_window_stick (window); 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 static void
handle_move_to_workspace (MetaDisplay *display, handle_move_to_workspace (MetaDisplay *display,
MetaScreen *screen, MetaScreen *screen,
@@ -3269,36 +3312,28 @@ init_builtin_key_bindings (MetaDisplay *display)
common_keybindings, common_keybindings,
META_KEY_BINDING_NONE, META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_WORKSPACE_LEFT, META_KEYBINDING_ACTION_WORKSPACE_LEFT,
handle_switch_to_workspace, META_MOTION_LEFT); NULL, 0);
add_builtin_keybinding (display, add_builtin_keybinding (display,
"switch-to-workspace-right", "switch-to-workspace-right",
common_keybindings, common_keybindings,
META_KEY_BINDING_NONE, META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_WORKSPACE_RIGHT, META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
handle_switch_to_workspace, META_MOTION_RIGHT); NULL, 0);
add_builtin_keybinding (display, add_builtin_keybinding (display,
"switch-to-workspace-up", "switch-to-workspace-up",
common_keybindings, common_keybindings,
META_KEY_BINDING_NONE, META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_WORKSPACE_UP, META_KEYBINDING_ACTION_WORKSPACE_UP,
handle_switch_to_workspace, META_MOTION_UP); NULL, 0);
add_builtin_keybinding (display, add_builtin_keybinding (display,
"switch-to-workspace-down", "switch-to-workspace-down",
common_keybindings, common_keybindings,
META_KEY_BINDING_NONE, META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_WORKSPACE_DOWN, META_KEYBINDING_ACTION_WORKSPACE_DOWN,
handle_switch_to_workspace, META_MOTION_DOWN); NULL, 0);
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);
/* The ones which have inverses. These can't be bound to any keystroke /* 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, META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12,
handle_move_to_workspace, 11); 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, add_builtin_keybinding (display,
"move-to-workspace-left", "move-to-workspace-left",
common_keybindings, common_keybindings,
@@ -3862,9 +3890,12 @@ meta_display_init_keys (MetaDisplay *display)
/* Keybindings */ /* Keybindings */
display->keymap = NULL; display->keymap = NULL;
display->keysyms_per_keycode = 0; display->keysyms_per_keycode = 0;
display->modmap = NULL;
display->min_keycode = 0; display->min_keycode = 0;
display->max_keycode = 0; display->max_keycode = 0;
display->ignored_modifier_mask = 0; display->ignored_modifier_mask = 0;
display->num_lock_mask = 0;
display->scroll_lock_mask = 0;
display->hyper_mask = 0; display->hyper_mask = 0;
display->super_mask = 0; display->super_mask = 0;
display->meta_mask = 0; display->meta_mask = 0;

View File

@@ -125,6 +125,16 @@ log_handler (const gchar *log_domain,
static void static void
meta_print_compilation_info (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 #ifdef HAVE_RANDR
meta_verbose ("Compiled with randr extension\n"); meta_verbose ("Compiled with randr extension\n");
#else #else
@@ -544,6 +554,11 @@ prefs_changed_callback (MetaPreference pref,
meta_display_retheme_all (); meta_display_retheme_all ();
break; 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: default:
/* handled elsewhere or otherwise */ /* handled elsewhere or otherwise */
break; break;

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -318,19 +318,6 @@ window_overlaps_focus_window (MetaWindow *window)
&overlap); &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 static void
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
int *x, int *x,
@@ -750,7 +737,9 @@ meta_window_place (MetaWindow *window,
* on the sides of the parent window or something. * 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 */ /* Center on current monitor */
int w, h; int w, h;

View File

@@ -36,7 +36,6 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "keybindings-private.h" #include "keybindings-private.h"
#include "meta-accel-parse.h"
/* If you add a key, it needs updating in init() and in the gsettings /* If you add a key, it needs updating in init() and in the gsettings
* notify listener and of course in the .schemas file. * 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 GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART; static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE; static gboolean raise_on_click = TRUE;
static gboolean center_new_windows = FALSE;
static gboolean attach_modal_dialogs = FALSE; static gboolean attach_modal_dialogs = FALSE;
static char* current_theme = NULL; static char* current_theme = NULL;
static int num_workspaces = 4; static int num_workspaces = 4;
@@ -273,13 +271,6 @@ static MetaBoolPreference preferences_bool[] =
}, },
&attach_modal_dialogs, &attach_modal_dialogs,
}, },
{
{ "center-new-windows",
SCHEMA_MUTTER,
META_PREF_CENTER_NEW_WINDOWS,
},
&center_new_windows,
},
{ {
{ "raise-on-click", { "raise-on-click",
SCHEMA_GENERAL, SCHEMA_GENERAL,
@@ -924,11 +915,8 @@ queue_changed (MetaPreference pref)
meta_preference_to_string (pref)); meta_preference_to_string (pref));
if (changed_idle == 0) if (changed_idle == 0)
{ changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY, changed_idle_handler, NULL, NULL);
changed_idle_handler, NULL, NULL);
g_source_set_name_by_id (changed_idle, "[mutter] changed_idle_handler");
}
} }
@@ -1222,12 +1210,6 @@ meta_prefs_get_focus_new_windows (void)
return focus_new_windows; return focus_new_windows;
} }
gboolean
meta_prefs_get_center_new_windows (void)
{
return center_new_windows;
}
gboolean gboolean
meta_prefs_get_attach_modal_dialogs (void) meta_prefs_get_attach_modal_dialogs (void)
{ {
@@ -1341,7 +1323,7 @@ mouse_button_mods_handler (GVariant *value,
*result = NULL; /* ignored */ *result = NULL; /* ignored */
string_value = g_variant_get_string (value, NULL); 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, meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse new GSettings value\n"); "Failed to parse new GSettings value\n");
@@ -1645,9 +1627,9 @@ overlay_key_handler (GVariant *value,
*result = NULL; /* ignored */ *result = NULL; /* ignored */
string_value = g_variant_get_string (value, NULL); string_value = g_variant_get_string (value, NULL);
if (string_value && meta_parse_accelerator (string_value, &combo.keysym, if (string_value && meta_ui_parse_accelerator (string_value, &combo.keysym,
&combo.keycode, &combo.keycode,
&combo.modifiers)) &combo.modifiers))
; ;
else else
{ {
@@ -1743,9 +1725,6 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_FOCUS_NEW_WINDOWS: case META_PREF_FOCUS_NEW_WINDOWS:
return "FOCUS_NEW_WINDOWS"; return "FOCUS_NEW_WINDOWS";
case META_PREF_CENTER_NEW_WINDOWS:
return "CENTER_NEW_WINDOWS";
case META_PREF_ATTACH_MODAL_DIALOGS: case META_PREF_ATTACH_MODAL_DIALOGS:
return "ATTACH_MODAL_DIALOGS"; return "ATTACH_MODAL_DIALOGS";
@@ -1908,7 +1887,7 @@ update_binding (MetaKeyPref *binding,
keycode = 0; keycode = 0;
mods = 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, meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse new GSettings value\n"); "Failed to parse new GSettings value\n");

View File

@@ -79,6 +79,7 @@ struct _MetaScreen
MetaStack *stack; MetaStack *stack;
MetaStackTracker *stack_tracker; MetaStackTracker *stack_tracker;
MetaCursorTracker *cursor_tracker;
MetaCursor current_cursor; MetaCursor current_cursor;
Window wm_sn_selection_window; Window wm_sn_selection_window;
@@ -112,6 +113,7 @@ struct _MetaScreen
guint workspace_layout_overridden : 1; guint workspace_layout_overridden : 1;
guint keys_grabbed : 1; guint keys_grabbed : 1;
guint all_keys_grabbed : 1;
int closing; int closing;

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