Compare commits
232 Commits
3.13.1
...
wip/gestur
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed80495e0 | ||
|
|
f13c86d651 | ||
|
|
be2ca66735 | ||
|
|
2df807549e | ||
|
|
66cdb1bb71 | ||
|
|
8030a2972e | ||
|
|
ba086dea8c | ||
|
|
6a02d7dfa3 | ||
|
|
c5db56da5c | ||
|
|
b5c605df5e | ||
|
|
4ad2865cce | ||
|
|
b9687d1a72 | ||
|
|
66d18fcc55 | ||
|
|
321cd5d85f | ||
|
|
ae91de5d03 | ||
|
|
7247b8d81b | ||
|
|
97f2de37e1 | ||
|
|
967b6c33df | ||
|
|
00c7a27732 | ||
|
|
048ba353c4 | ||
|
|
555e2f6de2 | ||
|
|
ff8d5281f0 | ||
|
|
4f9b994e73 | ||
|
|
b8b0dc5c78 | ||
|
|
d0cafab836 | ||
|
|
24d7c5ebe3 | ||
|
|
dc6decefb5 | ||
|
|
25d7e48077 | ||
|
|
b0b8f37240 | ||
|
|
188e4e1b92 | ||
|
|
9d5273bb15 | ||
|
|
3c0fae74f1 | ||
|
|
86dae6d4c7 | ||
|
|
d06600aeb0 | ||
|
|
895a3d1f39 | ||
|
|
381ef5c683 | ||
|
|
62097897be | ||
|
|
2d2c47ba49 | ||
|
|
89cdfc9194 | ||
|
|
ad60ea9e0e | ||
|
|
a7350475e8 | ||
|
|
f3d7c9cff9 | ||
|
|
906cbeed61 | ||
|
|
0fccb0fc86 | ||
|
|
8100cefd4c | ||
|
|
d7e99a3f86 | ||
|
|
6af944fe2c | ||
|
|
12fc394b92 | ||
|
|
53814fefc1 | ||
|
|
e87a01c80b | ||
|
|
21d7c1a850 | ||
|
|
e33c58297d | ||
|
|
5350120db4 | ||
|
|
0997cf7fee | ||
|
|
af3aae7295 | ||
|
|
98e219da4b | ||
|
|
fba022cc06 | ||
|
|
3f6c6f1dd9 | ||
|
|
ebc2e7221b | ||
|
|
7cb30ced23 | ||
|
|
7b449ac56c | ||
|
|
724953101d | ||
|
|
8734477d52 | ||
|
|
ec8ba4b5f9 | ||
|
|
2250865eb6 | ||
|
|
847a3bbee3 | ||
|
|
410a002ddd | ||
|
|
8766db2593 | ||
|
|
e362227514 | ||
|
|
da311f266d | ||
|
|
f5a4e996a8 | ||
|
|
a7f083897f | ||
|
|
e2105dc721 | ||
|
|
b64548ee1f | ||
|
|
53425fa721 | ||
|
|
048f035d30 | ||
|
|
b32c837df9 | ||
|
|
dd03a76d51 | ||
|
|
806a666950 | ||
|
|
b240a5e819 | ||
|
|
fe823b3553 | ||
|
|
d380d30ef4 | ||
|
|
1fe5b3e7d5 | ||
|
|
a8df208a5c | ||
|
|
f3f3c94831 | ||
|
|
6e06648f7a | ||
|
|
afb41f715b | ||
|
|
19d26dde92 | ||
|
|
4acb902423 | ||
|
|
626516d12e | ||
|
|
1c94df2553 | ||
|
|
43762da9d3 | ||
|
|
266166a2d6 | ||
|
|
3a0af0faae | ||
|
|
0890eaa3fe | ||
|
|
d4058d947b | ||
|
|
b704659899 | ||
|
|
0a9187a6e9 | ||
|
|
31db32e826 | ||
|
|
c2ea650b3c | ||
|
|
969131f00e | ||
|
|
c98090c061 | ||
|
|
3168d3b5e6 | ||
|
|
efcd7d86e7 | ||
|
|
04449923bd | ||
|
|
47b3336ffa | ||
|
|
0f37c1b58e | ||
|
|
a3747725ed | ||
|
|
c448650a60 | ||
|
|
c45f616fdc | ||
|
|
9402691aaa | ||
|
|
cbffbb0be0 | ||
|
|
9df5b17940 | ||
|
|
feae23506b | ||
|
|
6408e59c7c | ||
|
|
47d72680ff | ||
|
|
6513cbb470 | ||
|
|
50b81fe4b9 | ||
|
|
f38c1f6ab4 | ||
|
|
f159611fab | ||
|
|
f1a7231ac2 | ||
|
|
21991a7edb | ||
|
|
3f1b6ddc8f | ||
|
|
aa84813400 | ||
|
|
dd243813e1 | ||
|
|
d8c2933c58 | ||
|
|
2b798511de | ||
|
|
6c37f6e601 | ||
|
|
92e9f3d467 | ||
|
|
05419b8450 | ||
|
|
e215c07439 | ||
|
|
5b7dff7a57 | ||
|
|
1a3aa75385 | ||
|
|
41880778b5 | ||
|
|
ecb4e09ec5 | ||
|
|
d02505852d | ||
|
|
3941dc7537 | ||
|
|
e790c45303 | ||
|
|
ae4e553ddb | ||
|
|
809568280b | ||
|
|
4053c92abf | ||
|
|
56906a29e0 | ||
|
|
2c0ad5bef7 | ||
|
|
4a7939268c | ||
|
|
80266d3071 | ||
|
|
8e5cfccf49 | ||
|
|
dcf64ca167 | ||
|
|
f93fc1506b | ||
|
|
4ee8fb8154 | ||
|
|
446b75907e | ||
|
|
550f1989ff | ||
|
|
91a6f42345 | ||
|
|
e97cae0eb3 | ||
|
|
8640982e68 | ||
|
|
480a853263 | ||
|
|
b05953d960 | ||
|
|
3a0de6a4f1 | ||
|
|
fb9f22c02f | ||
|
|
10ac1000f7 | ||
|
|
c81a0dede2 | ||
|
|
fc8a2b8a42 | ||
|
|
2ae0a72dad | ||
|
|
5b17c72047 | ||
|
|
8d9653dece | ||
|
|
e2b7b26f28 | ||
|
|
ff2eb77fcd | ||
|
|
0588399ac7 | ||
|
|
71544fbf4e | ||
|
|
c8f3820956 | ||
|
|
f57b0726a0 | ||
|
|
da175bca52 | ||
|
|
33cb7f4a2c | ||
|
|
7732447abc | ||
|
|
c49c37999c | ||
|
|
91f35d6a01 | ||
|
|
549df04ed8 | ||
|
|
4334135c52 | ||
|
|
03c4de5590 | ||
|
|
7a109a18af | ||
|
|
d9b72b0f43 | ||
|
|
a7ea54bd7d | ||
|
|
df642b96e2 | ||
|
|
f56cc1f733 | ||
|
|
f5bff4b7f3 | ||
|
|
bbfdf5dd2a | ||
|
|
9b95eda42a | ||
|
|
2d225a3386 | ||
|
|
7b3cdc8f96 | ||
|
|
b6f9500ccc | ||
|
|
ea354e96cb | ||
|
|
098c8908ed | ||
|
|
ab632e36a5 | ||
|
|
1427d20922 | ||
|
|
aed671810c | ||
|
|
324d7d720d | ||
|
|
413e39ecbb | ||
|
|
2ca2c18c2a | ||
|
|
01cd4b2ba0 | ||
|
|
bca210db45 | ||
|
|
66d6f73af2 | ||
|
|
bc8799d7d7 | ||
|
|
fd5c14550a | ||
|
|
a5cca5296c | ||
|
|
f4ef4b79f9 | ||
|
|
6c7a51378f | ||
|
|
9c4908b44a | ||
|
|
afaab8aef2 | ||
|
|
845fdda22c | ||
|
|
fa29a1a99e | ||
|
|
f9bffae9fd | ||
|
|
31c925c602 | ||
|
|
5d310e06ba | ||
|
|
25a16c3379 | ||
|
|
730ed6f75f | ||
|
|
a6601e92aa | ||
|
|
f3a2bb7779 | ||
|
|
73e2d7049a | ||
|
|
a6353944f6 | ||
|
|
43d6088ebb | ||
|
|
e3001794f2 | ||
|
|
e97ca325e6 | ||
|
|
c9c6645284 | ||
|
|
57bb297450 | ||
|
|
06ca99c3a3 | ||
|
|
4b5593c67f | ||
|
|
acb3dc6754 | ||
|
|
4c21a46452 | ||
|
|
900ae2c1fa | ||
|
|
01b6445708 | ||
|
|
292d502205 | ||
|
|
adf2e44a82 | ||
|
|
b075d576a0 |
35
.cvsignore
35
.cvsignore
@@ -1,35 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
libtool
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
stamp.h
|
||||
version.h
|
||||
config.h.in
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
INSTALL
|
||||
intl
|
||||
ABOUT-NLS
|
||||
COPYING
|
||||
intltool-*
|
||||
metacity.spec
|
||||
autom4te.cache
|
||||
compile
|
||||
depcomp
|
||||
omf.make
|
||||
xmldocs.make
|
||||
23
.gitignore
vendored
23
.gitignore
vendored
@@ -3,6 +3,7 @@ Makefile.in
|
||||
Makefile.in.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
@@ -19,11 +20,11 @@ libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/50-mutter-navigation.xml
|
||||
src/50-mutter-system.xml
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter.desktop
|
||||
src/mutter-wayland.desktop
|
||||
50-mutter-navigation.xml
|
||||
50-mutter-system.xml
|
||||
50-mutter-windows.xml
|
||||
mutter.desktop
|
||||
mutter-wayland.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
@@ -32,10 +33,6 @@ src/mutter-wayland.desktop
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
stamp-tidy-marshal.h
|
||||
stamp-h1
|
||||
*.gmo
|
||||
*.make
|
||||
@@ -44,11 +41,8 @@ stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-launch
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
org.gnome.mutter.wayland.gschema.valid
|
||||
@@ -67,9 +61,6 @@ test-focus
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
# We can't say just "wm-tester" here or it will ignore the directory
|
||||
# rather than the binary
|
||||
src/wm-tester/wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
||||
src/mutter-enum-types.[ch]
|
||||
@@ -78,12 +69,14 @@ src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-display-config.[ch]
|
||||
src/meta-dbus-idle-monitor.[ch]
|
||||
src/meta-dbus-login1.[ch]
|
||||
src/gtk-shell-protocol.c
|
||||
src/gtk-shell-server-protocol.h
|
||||
src/xdg-shell-protocol.c
|
||||
src/xdg-shell-server-protocol.h
|
||||
src/xserver-protocol.c
|
||||
src/xserver-server-protocol.h
|
||||
src/meta/meta-version.h
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
doc/reference/*.hierarchy
|
||||
|
||||
11
Makefile.am
11
Makefile.am
@@ -1,10 +1,13 @@
|
||||
|
||||
SUBDIRS=src po doc
|
||||
SUBDIRS = data src po doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
DISTCLEANFILES = \
|
||||
intltool-extract \
|
||||
intltool-merge \
|
||||
intltool-update \
|
||||
po/stamp-it \
|
||||
po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
31
NEWS
31
NEWS
@@ -1,3 +1,34 @@
|
||||
3.13.3
|
||||
======
|
||||
* Improve behavior of window buttons with compositor menus [Florian; #731058]
|
||||
* Implement touch support on wayland [Carlos; #724442]
|
||||
* Update window shadows [Nikita; #731866]
|
||||
* Keep windows on the preferred output [Florian; #731760]
|
||||
* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332,
|
||||
#730527, #662962]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.13.2
|
||||
======
|
||||
* Add basic HiDPI support on wayland [Adel; #728902]
|
||||
* Fix crash when monitors change during suspend [Giovanni; #725637]
|
||||
* Replace mutter-launch with logind integration [Jasper; #724604]
|
||||
* Move window menu into the compositor [Jasper; #726352]
|
||||
* Fix delayed focus-follows-mouse support [Florian; #730541]
|
||||
* Support fallback app menu in window decorations [Florian; #730752]
|
||||
* Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602,
|
||||
#726714]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
Translations:
|
||||
Pau Iranzo [ca], Daniel Mustieles [es]
|
||||
|
||||
3.13.1
|
||||
======
|
||||
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
|
||||
|
||||
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
REQUIRED_AUTOMAKE_VERSION=1.11
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
|
||||
68
configure.ac
68
configure.ac
@@ -1,9 +1,8 @@
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [13])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_micro_version], [3])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -14,6 +13,7 @@ AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@@ -40,12 +40,14 @@ GETTEXT_PACKAGE=mutter
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||
|
||||
IT_PROG_INTLTOOL([0.34.90])
|
||||
LT_PREREQ([2.2.6])
|
||||
LT_INIT([disable-static])
|
||||
IT_PROG_INTLTOOL([0.41])
|
||||
AC_PROG_CC
|
||||
AC_ISC_POSIX
|
||||
AC_PROG_CC_C_O
|
||||
AC_PROG_INSTALL
|
||||
AC_HEADER_STDC
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
PKG_PROG_PKG_CONFIG([0.21])
|
||||
|
||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||
AM_PATH_GLIB_2_0()
|
||||
@@ -75,8 +77,13 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
||||
xcursor
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
clutter-wayland-1.0
|
||||
clutter-wayland-compositor-1.0
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
wayland-server >= 1.4.93
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
@@ -107,37 +114,12 @@ AC_ARG_WITH(libcanberra,
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_ENABLE(xsync,
|
||||
AC_HELP_STRING([--disable-xsync],
|
||||
[disable mutter's use of the XSync extension]),,
|
||||
enable_xsync=auto)
|
||||
|
||||
AC_ARG_ENABLE(shape,
|
||||
AC_HELP_STRING([--disable-shape],
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
enable_shape=auto)
|
||||
|
||||
## Wayland support requires the xserver.xml protocol extension found in the weston
|
||||
## repository but since there aren't currently established conventions for
|
||||
## installing and discovering these we simply require a location to be given
|
||||
## explicitly...
|
||||
AC_ARG_WITH([wayland-protocols],
|
||||
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
|
||||
[
|
||||
],
|
||||
[])
|
||||
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -202,17 +184,20 @@ if test x$found_introspection != xno; then
|
||||
AC_SUBST(META_GIR)
|
||||
fi
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
|
||||
if test $have_native_backend = yes; then
|
||||
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
|
||||
|
||||
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
|
||||
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
|
||||
|
||||
@@ -304,17 +289,6 @@ fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
|
||||
|
||||
HOST_ALIAS=$host_alias
|
||||
AC_SUBST(HOST_ALIAS)
|
||||
|
||||
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
|
||||
|
||||
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
|
||||
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
|
||||
fi
|
||||
|
||||
AC_SUBST(GDK_PIXBUF_CSOURCE)
|
||||
|
||||
AC_PATH_PROG(ZENITY, zenity, no)
|
||||
if test x"$ZENITY" = xno; then
|
||||
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
|
||||
@@ -397,6 +371,7 @@ changequote([,])dnl
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
doc/Makefile
|
||||
doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
@@ -404,6 +379,7 @@ doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter.pc
|
||||
src/compositor/plugins/Makefile
|
||||
src/meta/meta-version.h
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
defaultcursordir = $(datadir)/mutter/cursors
|
||||
desktopfiles_in_files = \
|
||||
mutter.desktop.in \
|
||||
mutter-wayland.desktop.in
|
||||
desktopfilesdir = $(datadir)/applications
|
||||
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
|
||||
dist_defaultcursor_DATA = left_ptr.png
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xmldir = $(GNOME_KEYBINDINGS_KEYSDIR)
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
gschema_in_files = \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in
|
||||
gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml)
|
||||
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
$(desktopfiles_DATA) \
|
||||
$(gsettings_SCHEMAS) \
|
||||
$(xml_DATA)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(convert_DATA) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(gschema_in_files) \
|
||||
$(xml_in_files)
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=Mutter (wayland compositor)
|
||||
Exec=mutter-launch -- mutter --wayland --display-server
|
||||
Exec=mutter --wayland --display-server
|
||||
NoDisplay=true
|
||||
# name of loadable control center module
|
||||
X-GNOME-WMSettingsModule=metacity
|
||||
@@ -79,8 +79,6 @@ IGNORE_HFILES= \
|
||||
iconcache.h \
|
||||
inlinepixbufs.h \
|
||||
keybindings-private.h \
|
||||
menu.h \
|
||||
metaaccellabel.h \
|
||||
meta-background-actor-private.h \
|
||||
meta-background-group-private.h \
|
||||
meta-module.h \
|
||||
|
||||
@@ -555,7 +555,7 @@ meta_window_is_monitor_sized
|
||||
meta_window_is_override_redirect
|
||||
meta_window_is_skip_taskbar
|
||||
meta_window_get_rect
|
||||
meta_window_get_input_rect
|
||||
meta_window_get_buffer_rect
|
||||
meta_window_get_frame_rect
|
||||
meta_window_get_outer_rect
|
||||
meta_window_client_rect_to_frame_rect
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/50-mutter-navigation.xml.in
|
||||
src/50-mutter-system.xml.in
|
||||
src/50-mutter-windows.xml.in
|
||||
data/50-mutter-navigation.xml.in
|
||||
data/50-mutter-system.xml.in
|
||||
data/50-mutter-windows.xml.in
|
||||
data/mutter.desktop.in
|
||||
data/org.gnome.mutter.gschema.xml.in
|
||||
data/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/backends/meta-monitor-manager.c
|
||||
src/compositor/compositor.c
|
||||
src/compositor/meta-background.c
|
||||
@@ -18,12 +21,7 @@ src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/mutter.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/ui/frames.c
|
||||
src/ui/menu.c
|
||||
src/ui/metaaccellabel.c
|
||||
src/ui/resizepopup.c
|
||||
src/ui/theme.c
|
||||
src/ui/theme-parser.c
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
src/metacity.schemas.in
|
||||
|
||||
data/mutter-wayland.desktop.in
|
||||
|
||||
148
po/es.po
148
po/es.po
@@ -14,16 +14,16 @@ msgstr ""
|
||||
"Project-Id-Version: mutter.master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2014-04-09 22:40+0000\n"
|
||||
"PO-Revision-Date: 2014-04-10 11:04+0200\n"
|
||||
"POT-Creation-Date: 2014-05-08 09:39+0000\n"
|
||||
"PO-Revision-Date: 2014-05-10 19:21+0200\n"
|
||||
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
|
||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||
"X-Generator: Gtranslator 2.91.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Gtranslator 2.91.6\n"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:1
|
||||
msgid "Navigation"
|
||||
@@ -46,98 +46,108 @@ msgid "Move window to workspace 4"
|
||||
msgstr "Mover la ventana al área de trabajo 4"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:6
|
||||
#| msgid "Move window to workspace 1"
|
||||
msgid "Move window to last workspace"
|
||||
msgstr "Mover la ventana a la última área de trabajo"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:7
|
||||
msgid "Move window one workspace to the left"
|
||||
msgstr "Mover la ventana un área de trabajo a la izquierda"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:7
|
||||
#: ../src/50-mutter-navigation.xml.in.h:8
|
||||
msgid "Move window one workspace to the right"
|
||||
msgstr "Mover la ventana un área de trabajo a la derecha"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:8
|
||||
#: ../src/50-mutter-navigation.xml.in.h:9
|
||||
msgid "Move window one workspace up"
|
||||
msgstr "Subir la ventana un área de trabajo"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:9
|
||||
#: ../src/50-mutter-navigation.xml.in.h:10
|
||||
msgid "Move window one workspace down"
|
||||
msgstr "Bajar la ventana un área de trabajo"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:10
|
||||
#: ../src/50-mutter-navigation.xml.in.h:11
|
||||
msgid "Move window one monitor to the left"
|
||||
msgstr "Mover la ventana una pantalla a la izquierda"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:11
|
||||
#: ../src/50-mutter-navigation.xml.in.h:12
|
||||
msgid "Move window one monitor to the right"
|
||||
msgstr "Mover la ventana una pantalla a la derecha"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:12
|
||||
#: ../src/50-mutter-navigation.xml.in.h:13
|
||||
msgid "Move window one monitor up"
|
||||
msgstr "Subir la ventana una pantalla"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:13
|
||||
#: ../src/50-mutter-navigation.xml.in.h:14
|
||||
msgid "Move window one monitor down"
|
||||
msgstr "Bajar la ventana una pantalla"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:14
|
||||
#: ../src/50-mutter-navigation.xml.in.h:15
|
||||
msgid "Switch applications"
|
||||
msgstr "Cambiar entre aplicaciones"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:15
|
||||
#: ../src/50-mutter-navigation.xml.in.h:16
|
||||
msgid "Switch windows"
|
||||
msgstr "Cambiar entre ventanas"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:16
|
||||
#: ../src/50-mutter-navigation.xml.in.h:17
|
||||
msgid "Switch windows of an application"
|
||||
msgstr "Cambiar entre ventanas de una aplicación"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:17
|
||||
#: ../src/50-mutter-navigation.xml.in.h:18
|
||||
msgid "Switch system controls"
|
||||
msgstr "Cambiar entre controles del sistema"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:18
|
||||
#: ../src/50-mutter-navigation.xml.in.h:19
|
||||
msgid "Switch windows directly"
|
||||
msgstr "Cambiar entre ventanas directamente"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:19
|
||||
#: ../src/50-mutter-navigation.xml.in.h:20
|
||||
msgid "Switch windows of an app directly"
|
||||
msgstr "Cambiar entre ventanas de una aplicación directamente"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:20
|
||||
#: ../src/50-mutter-navigation.xml.in.h:21
|
||||
msgid "Switch system controls directly"
|
||||
msgstr "Cambiar entre controles del sistema directamente"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:21
|
||||
#: ../src/50-mutter-navigation.xml.in.h:22
|
||||
msgid "Hide all normal windows"
|
||||
msgstr "Ocultar todas las ventanas normales"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:22
|
||||
#: ../src/50-mutter-navigation.xml.in.h:23
|
||||
msgid "Switch to workspace 1"
|
||||
msgstr "Cambiar al área de trabajo 1"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:23
|
||||
#: ../src/50-mutter-navigation.xml.in.h:24
|
||||
msgid "Switch to workspace 2"
|
||||
msgstr "Cambiar al área de trabajo 2"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:24
|
||||
#: ../src/50-mutter-navigation.xml.in.h:25
|
||||
msgid "Switch to workspace 3"
|
||||
msgstr "Cambiar al área de trabajo 3"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:25
|
||||
#: ../src/50-mutter-navigation.xml.in.h:26
|
||||
msgid "Switch to workspace 4"
|
||||
msgstr "Cambiar al área de trabajo 4"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:26
|
||||
#: ../src/50-mutter-navigation.xml.in.h:27
|
||||
#| msgid "Switch to workspace 1"
|
||||
msgid "Switch to last workspace"
|
||||
msgstr "Cambiar a la útima área de trabajo"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:28
|
||||
msgid "Move to workspace left"
|
||||
msgstr "Mover al área de trabajo de la izquierda"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:27
|
||||
#: ../src/50-mutter-navigation.xml.in.h:29
|
||||
msgid "Move to workspace right"
|
||||
msgstr "Mover al área de trabajo de la derecha"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:28
|
||||
#: ../src/50-mutter-navigation.xml.in.h:30
|
||||
msgid "Move to workspace above"
|
||||
msgstr "Mover al área de trabajo de la arriba"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:29
|
||||
#: ../src/50-mutter-navigation.xml.in.h:31
|
||||
msgid "Move to workspace below"
|
||||
msgstr "Mover al área de trabajo de abajo"
|
||||
|
||||
@@ -229,29 +239,29 @@ msgstr "Ver división a la izquierda"
|
||||
msgid "View split on right"
|
||||
msgstr "Ver división a la derecha"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:465
|
||||
#: ../src/backends/meta-monitor-manager.c:412
|
||||
msgid "Built-in display"
|
||||
msgstr "Pantalla integrada"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:490
|
||||
#: ../src/backends/meta-monitor-manager.c:437
|
||||
msgid "Unknown"
|
||||
msgstr "Desconocida"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:492
|
||||
#: ../src/backends/meta-monitor-manager.c:439
|
||||
msgid "Unknown Display"
|
||||
msgstr "Pantalla desconocida"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: ../src/backends/meta-monitor-manager.c:500
|
||||
#: ../src/backends/meta-monitor-manager.c:447
|
||||
#, c-format
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:505
|
||||
#: ../src/compositor/compositor.c:464
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
@@ -264,7 +274,7 @@ msgstr ""
|
||||
msgid "background texture could not be created from file"
|
||||
msgstr "no se pudo crear la textura de fondo a partir de archivo"
|
||||
|
||||
#: ../src/core/bell.c:213
|
||||
#: ../src/core/bell.c:215
|
||||
msgid "Bell event"
|
||||
msgstr "Evento de campana"
|
||||
|
||||
@@ -293,49 +303,49 @@ msgstr "_Esperar"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Forzar la salida"
|
||||
|
||||
#: ../src/core/display.c:453
|
||||
#: ../src/core/display.c:451
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n"
|
||||
|
||||
#: ../src/core/main.c:200
|
||||
#: ../src/core/main.c:190
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "Desactivar conexión al gestor de sesión"
|
||||
|
||||
#: ../src/core/main.c:206
|
||||
#: ../src/core/main.c:196
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "Reemplazar el gestor de ventanas en ejecución"
|
||||
|
||||
#: ../src/core/main.c:212
|
||||
#: ../src/core/main.c:202
|
||||
msgid "Specify session management ID"
|
||||
msgstr "Especificar el ID se gestión de sesión"
|
||||
|
||||
#: ../src/core/main.c:217
|
||||
#: ../src/core/main.c:207
|
||||
msgid "X Display to use"
|
||||
msgstr "Pantalla X que usar"
|
||||
|
||||
#: ../src/core/main.c:223
|
||||
#: ../src/core/main.c:213
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "Inicializar sesión desde el archivo de salvaguarda"
|
||||
|
||||
#: ../src/core/main.c:229
|
||||
#: ../src/core/main.c:219
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "Hacer que las llamadas a las X sean síncronas"
|
||||
|
||||
#: ../src/core/main.c:235
|
||||
#: ../src/core/main.c:225
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "Ejecutar como compositor Wayland"
|
||||
|
||||
#: ../src/core/main.c:241
|
||||
#: ../src/core/main.c:231
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Ejecutar como servidor completo, en lugar de anidado"
|
||||
|
||||
#: ../src/core/main.c:486
|
||||
#: ../src/core/main.c:476
|
||||
#, c-format
|
||||
msgid "Failed to scan themes directory: %s\n"
|
||||
msgstr "Falló al inspeccionar la carpeta de temas: %s\n"
|
||||
|
||||
#: ../src/core/main.c:502
|
||||
#: ../src/core/main.c:492
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
|
||||
@@ -366,17 +376,17 @@ msgstr "Imprimir versión"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Complemento de mutter que usar"
|
||||
|
||||
#: ../src/core/prefs.c:1985
|
||||
#: ../src/core/prefs.c:2005
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Área de trabajo %d"
|
||||
|
||||
#: ../src/core/screen.c:543
|
||||
#: ../src/core/screen.c:529
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "La ventana %d en la pantalla «%s» no es válida\n"
|
||||
|
||||
#: ../src/core/screen.c:559
|
||||
#: ../src/core/screen.c:545
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||
@@ -385,7 +395,7 @@ msgstr ""
|
||||
"La ventana %d en la pantalla «%s» ya tiene un gestor de ventanas, intente "
|
||||
"usar la opción «--replace» para reemplazar el gestor de ventanas activo.\n"
|
||||
|
||||
#: ../src/core/screen.c:664
|
||||
#: ../src/core/screen.c:650
|
||||
#, c-format
|
||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||
msgstr "La ventana %d en la pantalla «%s» ya tiene un gestor de ventanas\n"
|
||||
@@ -398,10 +408,6 @@ msgstr "Mutter fue compilado sin soporte para modo prolijo\n"
|
||||
msgid "Mutter"
|
||||
msgstr "Mutter"
|
||||
|
||||
#: ../src/mutter-wayland.desktop.in.h:1
|
||||
msgid "Mutter (wayland compositor)"
|
||||
msgstr "Mutter (compositor Wayland)"
|
||||
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:1
|
||||
msgid "Modifier to use for extended window management operations"
|
||||
msgstr ""
|
||||
@@ -530,45 +536,50 @@ msgstr ""
|
||||
"la pantalla, se maximizan."
|
||||
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:19
|
||||
msgid "Place new windows in the center"
|
||||
msgstr "Colocar las ventanas nuevas en el centro"
|
||||
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"When true, the new windows will always be put in the center of the active "
|
||||
"screen of the monitor."
|
||||
msgstr ""
|
||||
"Cuando es cierto, las ventanas nuevas se colocarán siempre en el centro de "
|
||||
"la pantalla activa del monitor."
|
||||
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:21
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "Seleccionar ventana de la pestaña emergente"
|
||||
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:20
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:22
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Cancelar pestaña emergente"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:1
|
||||
#| msgid "Switch to workspace 1"
|
||||
msgid "Switch to VT 1"
|
||||
msgstr "Cambiar al VT 1"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:2
|
||||
#| msgid "Switch to workspace 2"
|
||||
msgid "Switch to VT 2"
|
||||
msgstr "Cambiar al VT 2"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:3
|
||||
#| msgid "Switch to workspace 3"
|
||||
msgid "Switch to VT 3"
|
||||
msgstr "Cambiar al VT 3"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:4
|
||||
#| msgid "Switch to workspace 4"
|
||||
msgid "Switch to VT 4"
|
||||
msgstr "Cambiar al VT 4"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:5
|
||||
#| msgid "Switch to workspace 5"
|
||||
msgid "Switch to VT 5"
|
||||
msgstr "Cambiar al VT 5"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:6
|
||||
#| msgid "Switch to workspace 6"
|
||||
msgid "Switch to VT 6"
|
||||
msgstr "Cambiar al VT 6"
|
||||
|
||||
#: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:7
|
||||
#| msgid "Switch to workspace 7"
|
||||
msgid "Switch to VT 7"
|
||||
msgstr "Cambiar al VT 7"
|
||||
|
||||
@@ -654,22 +665,22 @@ msgstr "Mover al área de trabajo de a_bajo"
|
||||
msgid "_Close"
|
||||
msgstr "_Cerrar"
|
||||
|
||||
#: ../src/ui/menu.c:200
|
||||
#: ../src/ui/menu.c:198
|
||||
#, c-format
|
||||
msgid "Workspace %d%n"
|
||||
msgstr "Área de trabajo %d%n"
|
||||
|
||||
#: ../src/ui/menu.c:210
|
||||
#: ../src/ui/menu.c:208
|
||||
#, c-format
|
||||
msgid "Workspace 1_0"
|
||||
msgstr "Área de trabajo 1_0"
|
||||
|
||||
#: ../src/ui/menu.c:212
|
||||
#: ../src/ui/menu.c:210
|
||||
#, c-format
|
||||
msgid "Workspace %s%d"
|
||||
msgstr "Área de trabajo %s%d"
|
||||
|
||||
#: ../src/ui/menu.c:382
|
||||
#: ../src/ui/menu.c:380
|
||||
msgid "Move to Another _Workspace"
|
||||
msgstr "Mover a _otro área de trabajo"
|
||||
|
||||
@@ -1482,6 +1493,9 @@ msgstr ""
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (on %s)"
|
||||
|
||||
#~ msgid "Mutter (wayland compositor)"
|
||||
#~ msgstr "Mutter (compositor Wayland)"
|
||||
|
||||
#~ msgid "Unknown window information request: %d"
|
||||
#~ msgstr "Petición de información de ventana desconocida: %d"
|
||||
|
||||
@@ -2015,11 +2029,11 @@ msgstr "%s (on %s)"
|
||||
|
||||
#~ msgid "GConf key %s is already in use and can't be used to override %s\n"
|
||||
#~ msgstr ""
|
||||
#~ "La clave de GConf %s ya está en uso y no se puede usar para sobreescribir "
|
||||
#~ "La clave de GConf %s ya está en uso y no se puede usar para sobrescribir "
|
||||
#~ "%s\n"
|
||||
|
||||
#~ msgid "Can't override GConf key, %s not found\n"
|
||||
#~ msgstr "No se puede sobreescribir la clave de GConf, no se encontró %s\n"
|
||||
#~ msgstr "No se puede sobrescribir la clave de GConf, no se encontró %s\n"
|
||||
|
||||
#~ msgid "Error setting number of workspaces to %d: %s\n"
|
||||
#~ msgstr ""
|
||||
|
||||
134
src/Makefile.am
134
src/Makefile.am
@@ -5,36 +5,35 @@ lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
AM_CPPFLAGS = \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
$(MUTTER_CFLAGS) \
|
||||
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
|
||||
-I$(builddir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/backends \
|
||||
-I$(srcdir)/core \
|
||||
-I$(srcdir)/ui \
|
||||
-I$(srcdir)/compositor \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
|
||||
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
|
||||
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
|
||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_display_config_built_sources) \
|
||||
$(dbus_login1_built_sources) \
|
||||
meta/meta-version.h \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
gtk-shell-protocol.c \
|
||||
@@ -70,18 +69,10 @@ libmutter_la_SOURCES = \
|
||||
backends/meta-monitor-manager-dummy.h \
|
||||
backends/edid-parse.c \
|
||||
backends/edid.h \
|
||||
backends/native/meta-backend-native.c \
|
||||
backends/native/meta-backend-native.h \
|
||||
backends/native/meta-cursor-renderer-native.c \
|
||||
backends/native/meta-cursor-renderer-native.h \
|
||||
backends/native/meta-idle-monitor-native.c \
|
||||
backends/native/meta-idle-monitor-native.h \
|
||||
backends/native/meta-monitor-manager-kms.c \
|
||||
backends/native/meta-monitor-manager-kms.h \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/x11/meta-backend-x11.c \
|
||||
backends/x11/meta-backend-x11.h \
|
||||
backends/x11/meta-cursor-renderer-x11.c \
|
||||
backends/x11/meta-cursor-renderer-x11.h \
|
||||
backends/x11/meta-idle-monitor-xsync.c \
|
||||
backends/x11/meta-idle-monitor-xsync.h \
|
||||
backends/x11/meta-monitor-manager-xrandr.c \
|
||||
@@ -161,6 +152,8 @@ libmutter_la_SOURCES = \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/gesture-tracker.c \
|
||||
core/gesture-tracker-private.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -189,10 +182,6 @@ libmutter_la_SOURCES = \
|
||||
ui/ui.h \
|
||||
ui/frames.c \
|
||||
ui/frames.h \
|
||||
ui/menu.c \
|
||||
ui/menu.h \
|
||||
ui/metaaccellabel.c \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/theme-parser.c \
|
||||
@@ -204,6 +193,8 @@ libmutter_la_SOURCES = \
|
||||
x11/iconcache.h \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/events.c \
|
||||
x11/events.h \
|
||||
x11/group-private.h \
|
||||
x11/group-props.c \
|
||||
x11/group-props.h \
|
||||
@@ -233,6 +224,8 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-touch.c \
|
||||
wayland/meta-wayland-touch.h \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
@@ -242,15 +235,31 @@ libmutter_la_SOURCES = \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
|
||||
if HAVE_NATIVE_BACKEND
|
||||
libmutter_la_SOURCES += \
|
||||
backends/native/meta-backend-native.c \
|
||||
backends/native/meta-backend-native.h \
|
||||
backends/native/meta-cursor-renderer-native.c \
|
||||
backends/native/meta-cursor-renderer-native.h \
|
||||
backends/native/meta-idle-monitor-native.c \
|
||||
backends/native/meta-idle-monitor-native.h \
|
||||
backends/native/meta-monitor-manager-kms.c \
|
||||
backends/native/meta-monitor-manager-kms.h \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/native/dbus-utils.c \
|
||||
backends/native/dbus-utils.h
|
||||
endif
|
||||
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
libmutterinclude_headers = \
|
||||
meta/barrier.h \
|
||||
meta/boxes.h \
|
||||
meta/common.h \
|
||||
@@ -279,6 +288,13 @@ libmutterinclude_base_headers = \
|
||||
meta/window.h \
|
||||
meta/workspace.h
|
||||
|
||||
libmutterinclude_built_headers = \
|
||||
meta/meta-version.h
|
||||
|
||||
libmutterinclude_base_headers = \
|
||||
$(libmutterinclude_headers) \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
# Excluded from scanning for introspection but installed
|
||||
# atomnames.h: macros cause problems for scanning process
|
||||
libmutterinclude_extra_headers = \
|
||||
@@ -287,27 +303,17 @@ libmutterinclude_extra_headers = \
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
nodist_libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
bin_PROGRAMS+=mutter-launch
|
||||
|
||||
mutter_launch_SOURCES = \
|
||||
backends/native/weston-launch.c \
|
||||
backends/native/weston-launch.h
|
||||
|
||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
|
||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
||||
|
||||
install-exec-hook:
|
||||
-chown root $(DESTDIR)$(bindir)/mutter-launch
|
||||
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
|
||||
@@ -331,7 +337,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
|
||||
Meta-$(api_version).gir: libmutter.la
|
||||
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
@@ -351,56 +357,23 @@ testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopfilesdir=$(datadir)/applications
|
||||
desktopfiles_in_files=mutter.desktop.in
|
||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
desktopfiles_DATA = $(desktopfiles_files)
|
||||
|
||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml \
|
||||
$(xml_DATA) \
|
||||
$(mutter_built_sources) \
|
||||
$(libmutterinclude_built_headers) \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
pkgconfig_DATA = libmutter.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
$(IMAGES) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
EXTRA_DIST = \
|
||||
$(wayland_protocols) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
org.freedesktop.login1.xml \
|
||||
org.gnome.Mutter.DisplayConfig.xml \
|
||||
org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
@@ -444,6 +417,15 @@ $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
|
||||
--c-generate-object-manager \
|
||||
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
|
||||
|
||||
$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--interface-prefix org.freedesktop.login1 \
|
||||
--c-namespace Login1 \
|
||||
--generate-c-code meta-dbus-login1 \
|
||||
$(srcdir)/org.freedesktop.login1.xml
|
||||
|
||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||
|
||||
@@ -62,6 +62,10 @@ struct _MetaBackendClass
|
||||
gboolean (* ungrab_device) (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void (* warp_pointer) (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
};
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
static MetaBackend *_backend;
|
||||
|
||||
@@ -72,8 +75,8 @@ 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);
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
@@ -189,6 +192,14 @@ meta_backend_ungrab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
||||
}
|
||||
|
||||
static GType
|
||||
get_backend_type (void)
|
||||
{
|
||||
@@ -197,7 +208,7 @@ get_backend_type (void)
|
||||
return META_TYPE_BACKEND_X11;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_BACKEND_NATIVE;
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_clutter_init (void);
|
||||
|
||||
#endif /* META_BACKEND_H */
|
||||
|
||||
@@ -41,6 +41,7 @@ struct _MetaCursorRendererPrivate
|
||||
MetaRectangle current_rect;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
@@ -57,19 +58,16 @@ queue_redraw (MetaCursorRenderer *renderer)
|
||||
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);
|
||||
if (priv->handled_by_backend)
|
||||
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
|
||||
else
|
||||
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
queue_redraw (renderer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -87,6 +85,8 @@ static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend;
|
||||
gboolean should_redraw = FALSE;
|
||||
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
@@ -108,7 +108,18 @@ update_cursor (MetaCursorRenderer *renderer)
|
||||
priv->current_rect.height = 0;
|
||||
}
|
||||
|
||||
META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
if (handled_by_backend != priv->handled_by_backend)
|
||||
{
|
||||
priv->handled_by_backend = handled_by_backend;
|
||||
should_redraw = TRUE;
|
||||
}
|
||||
|
||||
if (!handled_by_backend)
|
||||
should_redraw = TRUE;
|
||||
|
||||
if (should_redraw)
|
||||
queue_redraw (renderer);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
|
||||
@@ -51,7 +51,7 @@ struct _MetaCursorRendererClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
@@ -37,22 +37,8 @@ struct _MetaCursorTracker {
|
||||
|
||||
gboolean is_showing;
|
||||
|
||||
/* The cursor tracker stores the cursor for the current grab
|
||||
* operation, the cursor for the window with pointer focus, and
|
||||
* the cursor for the root window, which contains either the
|
||||
* default arrow cursor or the 'busy' hourglass if we're launching
|
||||
* an app.
|
||||
*
|
||||
* We choose the first one available -- if there's a grab cursor,
|
||||
* we choose that cursor, if there's window cursor, we choose that,
|
||||
* otherwise we choose the root cursor.
|
||||
*
|
||||
* The displayed_cursor contains the chosen cursor.
|
||||
*/
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
MetaCursorReference *grab_cursor;
|
||||
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
* explicitly, which means that we shouldn't display anything.
|
||||
* So, we can't simply store a NULL in window_cursor to
|
||||
@@ -62,6 +48,9 @@ struct _MetaCursorTracker {
|
||||
MetaCursorReference *window_cursor;
|
||||
|
||||
MetaCursorReference *root_cursor;
|
||||
|
||||
/* The cursor from the X11 server. */
|
||||
MetaCursorReference *xfixes_cursor;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerClass {
|
||||
@@ -71,8 +60,6 @@ struct _MetaCursorTrackerClass {
|
||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent);
|
||||
|
||||
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
@@ -63,11 +63,11 @@ get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->grab_cursor)
|
||||
return tracker->grab_cursor;
|
||||
|
||||
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
}
|
||||
|
||||
return tracker->root_cursor;
|
||||
}
|
||||
@@ -97,11 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
|
||||
detecting if the system mouse cursor is showing or not.
|
||||
|
||||
On wayland we start with the cursor showing
|
||||
*/
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
@@ -224,7 +219,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -254,7 +249,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
gboolean free_cursor_data;
|
||||
CoglContext *ctx;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
if (tracker->xfixes_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
@@ -304,7 +299,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
||||
cursor_image->xhot,
|
||||
cursor_image->yhot);
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
tracker->xfixes_cursor = cursor;
|
||||
}
|
||||
XFree (cursor_image);
|
||||
}
|
||||
@@ -317,13 +312,22 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
CoglTexture *
|
||||
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
cursor = tracker->displayed_cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_xfixes_cursor (tracker);
|
||||
cursor = tracker->xfixes_cursor;
|
||||
}
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
||||
if (cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -340,13 +344,22 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
cursor = tracker->displayed_cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_xfixes_cursor (tracker);
|
||||
cursor = tracker->xfixes_cursor;
|
||||
}
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
|
||||
if (cursor)
|
||||
meta_cursor_reference_get_cogl_texture (cursor, x, y);
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
@@ -356,17 +369,6 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
|
||||
if (cursor)
|
||||
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
|
||||
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
@@ -466,19 +468,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
return;
|
||||
tracker->is_showing = visible;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (visible)
|
||||
XFixesShowCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
else
|
||||
XFixesHideCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
|
||||
@@ -28,7 +28,10 @@
|
||||
#include "display-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "meta-backend.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -171,12 +174,14 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
else
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,9 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
||||
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
||||
|
||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||
|
||||
g_object_unref (skeleton);
|
||||
g_object_unref (object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -210,9 +210,9 @@ make_watch (MetaIdleMonitor *monitor,
|
||||
* meta_idle_monitor_add_idle_watch:
|
||||
* @monitor: A #MetaIdleMonitor
|
||||
* @interval_msec: The idletime interval, in milliseconds
|
||||
* @callback: (allow-none): The callback to call when the user has
|
||||
* @callback: (nullable): The callback to call when the user has
|
||||
* accumulated @interval_msec milliseconds of idle time.
|
||||
* @user_data: (allow-none): The user data to pass to the callback
|
||||
* @user_data: (nullable): The user data to pass to the callback
|
||||
* @notify: A #GDestroyNotify
|
||||
*
|
||||
* Returns: a watch id
|
||||
@@ -252,9 +252,9 @@ meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
|
||||
/**
|
||||
* meta_idle_monitor_add_user_active_watch:
|
||||
* @monitor: A #MetaIdleMonitor
|
||||
* @callback: (allow-none): The callback to call when the user is
|
||||
* @callback: (nullable): The callback to call when the user is
|
||||
* active again.
|
||||
* @user_data: (allow-none): The user data to pass to the callback
|
||||
* @user_data: (nullable): The user data to pass to the callback
|
||||
* @notify: A #GDestroyNotify
|
||||
*
|
||||
* Returns: a watch id
|
||||
|
||||
@@ -78,6 +78,7 @@ struct _MetaMonitorConfig {
|
||||
GHashTable *configs;
|
||||
MetaConfiguration *current;
|
||||
gboolean current_is_stored;
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
GFile *file;
|
||||
@@ -877,7 +878,8 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
|
||||
/* Stored (persistent) configurations override the previous one always.
|
||||
Also, we clear the previous configuration if the current one (which is
|
||||
about to become previous) is stored.
|
||||
about to become previous) is stored, or if the current one has
|
||||
different outputs.
|
||||
*/
|
||||
if (stored ||
|
||||
(self->current && self->current_is_stored))
|
||||
@@ -887,12 +889,28 @@ apply_configuration (MetaMonitorConfig *self,
|
||||
self->previous = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Despite the name, config_equal() only checks the set of outputs,
|
||||
not their modes
|
||||
*/
|
||||
if (self->current && config_equal (self->current, config))
|
||||
{
|
||||
self->previous = self->current;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->current)
|
||||
config_free (self->current);
|
||||
self->previous = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
self->current = config;
|
||||
self->current_is_stored = stored;
|
||||
/* If true, we'll be overridden at the end of this call
|
||||
inside turn_off_laptop_display()
|
||||
*/
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
if (self->current == self->previous)
|
||||
self->previous = NULL;
|
||||
@@ -1009,8 +1027,16 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
if (self->lid_is_closed &&
|
||||
stored->n_outputs > 1 &&
|
||||
laptop_display_is_on (stored))
|
||||
return apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE);
|
||||
{
|
||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE))
|
||||
{
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return apply_configuration (self, stored, manager, TRUE);
|
||||
}
|
||||
@@ -1357,6 +1383,7 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
apply_configuration (self, new, manager, FALSE);
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1376,7 +1403,7 @@ power_client_changed_cb (UpClient *client,
|
||||
|
||||
if (is_closed)
|
||||
turn_off_laptop_display (self, manager);
|
||||
else
|
||||
else if (self->current_is_for_laptop_lid)
|
||||
meta_monitor_config_restore_previous (self, manager);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ struct _MetaOutput
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
CoglSubpixelOrder subpixel_order;
|
||||
int scale;
|
||||
|
||||
MetaMonitorMode *preferred_mode;
|
||||
MetaMonitorMode **modes;
|
||||
|
||||
107
src/backends/native/dbus-utils.c
Normal file
107
src/backends/native/dbus-utils.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "dbus-utils.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* Stolen from tp_escape_as_identifier, from tp-glib,
|
||||
* which follows the same escaping convention as systemd.
|
||||
*/
|
||||
static inline gboolean
|
||||
_esc_ident_bad (gchar c, gboolean is_first)
|
||||
{
|
||||
return ((c < 'a' || c > 'z') &&
|
||||
(c < 'A' || c > 'Z') &&
|
||||
(c < '0' || c > '9' || is_first));
|
||||
}
|
||||
|
||||
static gchar *
|
||||
escape_dbus_component (const gchar *name)
|
||||
{
|
||||
gboolean bad = FALSE;
|
||||
size_t len = 0;
|
||||
GString *op;
|
||||
const gchar *ptr, *first_ok;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
/* fast path for empty name */
|
||||
if (name[0] == '\0')
|
||||
return g_strdup ("_");
|
||||
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
{
|
||||
if (_esc_ident_bad (*ptr, ptr == name))
|
||||
{
|
||||
bad = TRUE;
|
||||
len += 3;
|
||||
}
|
||||
else
|
||||
len++;
|
||||
}
|
||||
|
||||
/* fast path if it's clean */
|
||||
if (!bad)
|
||||
return g_strdup (name);
|
||||
|
||||
/* If strictly less than ptr, first_ok is the first uncopied safe character.
|
||||
*/
|
||||
first_ok = name;
|
||||
op = g_string_sized_new (len);
|
||||
for (ptr = name; *ptr; ptr++)
|
||||
{
|
||||
if (_esc_ident_bad (*ptr, ptr == name))
|
||||
{
|
||||
/* copy preceding safe characters if any */
|
||||
if (first_ok < ptr)
|
||||
{
|
||||
g_string_append_len (op, first_ok, ptr - first_ok);
|
||||
}
|
||||
/* escape the unsafe character */
|
||||
g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
|
||||
/* restart after it */
|
||||
first_ok = ptr + 1;
|
||||
}
|
||||
}
|
||||
/* copy trailing safe characters if any */
|
||||
if (first_ok < ptr)
|
||||
{
|
||||
g_string_append_len (op, first_ok, ptr - first_ok);
|
||||
}
|
||||
return g_string_free (op, FALSE);
|
||||
}
|
||||
|
||||
char *
|
||||
get_escaped_dbus_path (const char *prefix,
|
||||
const char *component)
|
||||
{
|
||||
char *escaped_component = escape_dbus_component (component);
|
||||
char *path = g_strconcat (prefix, "/", escaped_component, NULL);
|
||||
|
||||
g_free (escaped_component);
|
||||
return path;
|
||||
}
|
||||
32
src/backends/native/dbus-utils.h
Normal file
32
src/backends/native/dbus-utils.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef DBUS_UTILS_H
|
||||
#define DBUS_UTILS_H
|
||||
|
||||
char *
|
||||
get_escaped_dbus_path (const char *prefix,
|
||||
const char *component);
|
||||
|
||||
#endif /* DBUS_UTILS_H */
|
||||
@@ -174,6 +174,20 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
/* XXX */
|
||||
guint32 time_ = 0;
|
||||
|
||||
clutter_evdev_warp_pointer (device, time_, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
{
|
||||
@@ -183,6 +197,8 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||
|
||||
backend_class->warp_pointer = meta_backend_native_warp_pointer;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -120,7 +120,7 @@ update_hw_cursor (MetaCursorRendererNative *native,
|
||||
|
||||
set_crtc_cursor (native, &crtcs[i], crtc_cursor, force);
|
||||
|
||||
if (cursor)
|
||||
if (crtc_cursor)
|
||||
{
|
||||
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
|
||||
cursor_rect->x - crtc_rect->x,
|
||||
@@ -140,7 +140,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
@@ -148,10 +148,7 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||
|
||||
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);
|
||||
return priv->has_hw_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-launcher.h"
|
||||
#include "weston-launch.h"
|
||||
|
||||
#include <gio/gunixfdmessage.h>
|
||||
#include <gio/gunixfdlist.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/egl/clutter-egl.h>
|
||||
@@ -30,10 +29,17 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <malloc.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "dbus-utils.h"
|
||||
#include "meta-dbus-login1.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "backends/meta-backend.h"
|
||||
@@ -41,156 +47,42 @@
|
||||
|
||||
struct _MetaLauncher
|
||||
{
|
||||
GSocket *weston_launch;
|
||||
Login1Session *session_proxy;
|
||||
Login1Seat *seat_proxy;
|
||||
|
||||
gboolean vt_switched;
|
||||
|
||||
GMainContext *nested_context;
|
||||
GMainLoop *nested_loop;
|
||||
|
||||
GSource *inner_source;
|
||||
GSource *outer_source;
|
||||
gboolean session_active;
|
||||
};
|
||||
|
||||
static void handle_request_vt_switch (MetaLauncher *self);
|
||||
|
||||
static gboolean
|
||||
request_vt_switch_idle (gpointer user_data)
|
||||
static Login1Session *
|
||||
get_session_proxy (GCancellable *cancellable)
|
||||
{
|
||||
handle_request_vt_switch (user_data);
|
||||
char *proxy_path;
|
||||
char *session_id;
|
||||
Login1Session *session_proxy;
|
||||
|
||||
return FALSE;
|
||||
if (sd_pid_get_session (getpid (), &session_id) < 0)
|
||||
return NULL;
|
||||
|
||||
proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
|
||||
|
||||
session_proxy = login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"org.freedesktop.login1",
|
||||
proxy_path,
|
||||
cancellable, NULL);
|
||||
free (proxy_path);
|
||||
|
||||
return session_proxy;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
send_message_to_wl (MetaLauncher *self,
|
||||
void *message,
|
||||
gsize size,
|
||||
GSocketControlMessage *out_cmsg,
|
||||
GSocketControlMessage **in_cmsg,
|
||||
GError **error)
|
||||
static Login1Seat *
|
||||
get_seat_proxy (GCancellable *cancellable)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
GInputVector in_iov = { &reply, sizeof (reply) };
|
||||
GOutputVector out_iov = { message, size };
|
||||
GSocketControlMessage *out_all_cmsg[2];
|
||||
GSocketControlMessage **in_all_cmsg;
|
||||
int flags = 0;
|
||||
int i;
|
||||
|
||||
out_all_cmsg[0] = out_cmsg;
|
||||
out_all_cmsg[1] = NULL;
|
||||
if (g_socket_send_message (self->weston_launch, NULL,
|
||||
&out_iov, 1,
|
||||
out_all_cmsg, -1,
|
||||
flags, NULL, error) != (gssize)size)
|
||||
return FALSE;
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
&in_all_cmsg, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
|
||||
while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
|
||||
{
|
||||
guint id;
|
||||
|
||||
/* There were events queued */
|
||||
g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT);
|
||||
|
||||
/* This can never happen, because the only time mutter-launch can queue
|
||||
this event is after confirming a VT switch, and we don't make requests
|
||||
during that time.
|
||||
|
||||
Note that getting this event would be really bad, because we would be
|
||||
in the wrong loop/context.
|
||||
*/
|
||||
g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
|
||||
|
||||
switch (reply.header.opcode)
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
id = g_idle_add (request_vt_switch_idle, self);
|
||||
g_source_set_name_by_id (id, "[mutter] request_vt_switch_idle");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
NULL, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (reply.ret != 0)
|
||||
{
|
||||
if (reply.ret == -1)
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Got failure from weston-launch");
|
||||
else
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
|
||||
"Got failure from weston-launch: %s", strerror (-reply.ret));
|
||||
|
||||
for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
g_free (in_all_cmsg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (in_all_cmsg && in_all_cmsg[0])
|
||||
{
|
||||
for (i = 1; in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
*in_cmsg = in_all_cmsg[0];
|
||||
}
|
||||
|
||||
g_free (in_all_cmsg);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
meta_launcher_open_device (MetaLauncher *self,
|
||||
const char *name,
|
||||
int flags,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_open *message;
|
||||
GSocketControlMessage *cmsg;
|
||||
gboolean ok;
|
||||
gsize size;
|
||||
int *fds, n_fd;
|
||||
int ret;
|
||||
|
||||
size = sizeof (struct weston_launcher_open) + strlen (name) + 1;
|
||||
message = g_malloc (size);
|
||||
message->header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
message->flags = flags;
|
||||
strcpy (message->path, name);
|
||||
message->path[strlen(name)] = 0;
|
||||
|
||||
ok = send_message_to_wl (self, message, size, NULL, &cmsg, error);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
g_assert (G_IS_UNIX_FD_MESSAGE (cmsg));
|
||||
|
||||
fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (cmsg), &n_fd);
|
||||
g_assert (n_fd == 1);
|
||||
|
||||
ret = fds[0];
|
||||
g_free (fds);
|
||||
g_object_unref (cmsg);
|
||||
}
|
||||
else
|
||||
ret = -1;
|
||||
|
||||
g_free (message);
|
||||
return ret;
|
||||
return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1/seat/self",
|
||||
cancellable, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -206,6 +98,7 @@ session_unpause (void)
|
||||
cogl_kms_display_queue_modes_reset (cogl_display);
|
||||
|
||||
clutter_evdev_reclaim_devices ();
|
||||
clutter_egl_thaw_master_clock ();
|
||||
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
@@ -225,6 +118,92 @@ static void
|
||||
session_pause (void)
|
||||
{
|
||||
clutter_evdev_release_devices ();
|
||||
clutter_egl_freeze_master_clock ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
take_device (Login1Session *session_proxy,
|
||||
int dev_major,
|
||||
int dev_minor,
|
||||
int *out_fd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GVariant *fd_variant = NULL;
|
||||
int fd = -1;
|
||||
GUnixFDList *fd_list;
|
||||
|
||||
if (!login1_session_call_take_device_sync (session_proxy,
|
||||
dev_major,
|
||||
dev_minor,
|
||||
NULL,
|
||||
&fd_variant,
|
||||
NULL, /* paused */
|
||||
&fd_list,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
|
||||
if (fd == -1)
|
||||
goto out;
|
||||
|
||||
*out_fd = fd;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (fd_variant)
|
||||
g_variant_unref (fd_variant);
|
||||
if (fd_list)
|
||||
g_object_unref (fd_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_device_info_from_path (const char *path,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = stat (path, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_device_info_from_fd (int fd,
|
||||
int *out_major,
|
||||
int *out_minor)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
r = fstat (fd, &st);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (!S_ISCHR (st.st_mode))
|
||||
goto out;
|
||||
|
||||
*out_major = major (st.st_rdev);
|
||||
*out_minor = minor (st.st_rdev);
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -233,169 +212,151 @@ on_evdev_device_open (const char *path,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
MetaLauncher *self = user_data;
|
||||
int fd;
|
||||
int major, minor;
|
||||
|
||||
return meta_launcher_open_device (launcher, path, flags, error);
|
||||
if (!get_device_info_from_path (path, &major, &minor))
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"Could not get device info for path %s: %m", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!take_device (self->session_proxy, major, minor, &fd, NULL, error))
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
on_evdev_device_close (int fd,
|
||||
gpointer user_data)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_vt_enter (MetaLauncher *launcher)
|
||||
{
|
||||
g_assert (launcher->vt_switched);
|
||||
|
||||
g_main_loop_quit (launcher->nested_loop);
|
||||
|
||||
session_unpause ();
|
||||
}
|
||||
|
||||
static void
|
||||
handle_request_vt_switch (MetaLauncher *launcher)
|
||||
{
|
||||
struct weston_launcher_message message;
|
||||
GError *error;
|
||||
gboolean ok;
|
||||
|
||||
session_pause ();
|
||||
|
||||
message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
|
||||
|
||||
error = NULL;
|
||||
ok = send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, &error);
|
||||
if (!ok) {
|
||||
g_warning ("Failed to acknowledge VT switch: %s", error->message);
|
||||
g_error_free (error);
|
||||
MetaLauncher *self = user_data;
|
||||
int major, minor;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!get_device_info_from_fd (fd, &major, &minor))
|
||||
{
|
||||
g_warning ("Could not get device info for fd %d: %m", fd);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (!launcher->vt_switched);
|
||||
launcher->vt_switched = TRUE;
|
||||
if (!login1_session_call_release_device_sync (self->session_proxy,
|
||||
major, minor,
|
||||
NULL, &error))
|
||||
{
|
||||
g_warning ("Could not release device %d,%d: %s", major, minor, error->message);
|
||||
}
|
||||
}
|
||||
|
||||
/* We can't do anything at this point, because we don't
|
||||
have input devices and we don't have the DRM master,
|
||||
so let's run a nested busy loop until the VT is reentered */
|
||||
g_main_loop_run (launcher->nested_loop);
|
||||
static void
|
||||
sync_active (MetaLauncher *self)
|
||||
{
|
||||
gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy));
|
||||
|
||||
g_assert (launcher->vt_switched);
|
||||
launcher->vt_switched = FALSE;
|
||||
if (active == self->session_active)
|
||||
return;
|
||||
|
||||
self->session_active = active;
|
||||
|
||||
if (active)
|
||||
session_unpause ();
|
||||
else
|
||||
session_pause ();
|
||||
}
|
||||
|
||||
static void
|
||||
on_active_changed (Login1Session *session,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaLauncher *self = user_data;
|
||||
sync_active (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_socket_readable (GSocket *socket,
|
||||
GIOCondition condition,
|
||||
gpointer user_data)
|
||||
get_kms_fd (Login1Session *session_proxy,
|
||||
int *fd_out)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
struct weston_launcher_event event;
|
||||
gssize read;
|
||||
GError *error;
|
||||
int major, minor;
|
||||
int fd;
|
||||
GError *error = NULL;
|
||||
|
||||
if ((condition & G_IO_IN) == 0)
|
||||
return TRUE;
|
||||
|
||||
error = NULL;
|
||||
read = g_socket_receive (socket, (char*)&event, sizeof(event), NULL, &error);
|
||||
if (read < (gssize)sizeof(event))
|
||||
/* XXX -- use udev to find the DRM master device */
|
||||
if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
|
||||
{
|
||||
g_warning ("Error reading from weston-launcher socket: %s", error->message);
|
||||
g_warning ("Could not stat /dev/dri/card0: %m");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
|
||||
{
|
||||
g_warning ("Could not open DRM device: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (event.header.opcode)
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
handle_request_vt_switch (launcher);
|
||||
break;
|
||||
|
||||
case WESTON_LAUNCHER_SERVER_VT_ENTER:
|
||||
handle_vt_enter (launcher);
|
||||
break;
|
||||
}
|
||||
*fd_out = fd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
env_get_fd (const char *env)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = g_getenv (env);
|
||||
|
||||
if (value == NULL)
|
||||
return -1;
|
||||
else
|
||||
return g_ascii_strtoll (value, NULL, 10);
|
||||
}
|
||||
|
||||
MetaLauncher *
|
||||
meta_launcher_new (void)
|
||||
{
|
||||
MetaLauncher *self = g_slice_new0 (MetaLauncher);
|
||||
MetaLauncher *self;
|
||||
Login1Session *session_proxy;
|
||||
GError *error = NULL;
|
||||
int launch_fd;
|
||||
int kms_fd;
|
||||
|
||||
launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
|
||||
if (launch_fd < 0)
|
||||
g_error ("Invalid mutter-launch socket");
|
||||
session_proxy = get_session_proxy (NULL);
|
||||
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
|
||||
{
|
||||
g_warning ("Could not take control: %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
|
||||
if (!get_kms_fd (session_proxy, &kms_fd))
|
||||
return NULL;
|
||||
|
||||
self->nested_context = g_main_context_new ();
|
||||
self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
|
||||
self = g_slice_new0 (MetaLauncher);
|
||||
self->session_proxy = session_proxy;
|
||||
self->seat_proxy = get_seat_proxy (NULL);
|
||||
|
||||
self->outer_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
|
||||
g_source_set_callback (self->outer_source, (GSourceFunc)on_socket_readable, self, NULL);
|
||||
g_source_attach (self->outer_source, NULL);
|
||||
g_source_unref (self->outer_source);
|
||||
|
||||
self->inner_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
|
||||
g_source_set_callback (self->inner_source, (GSourceFunc)on_socket_readable, self, NULL);
|
||||
g_source_attach (self->inner_source, self->nested_context);
|
||||
g_source_unref (self->inner_source);
|
||||
|
||||
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);
|
||||
self->session_active = TRUE;
|
||||
|
||||
clutter_egl_set_kms_fd (kms_fd);
|
||||
clutter_evdev_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
self);
|
||||
|
||||
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_launcher_free (MetaLauncher *launcher)
|
||||
meta_launcher_free (MetaLauncher *self)
|
||||
{
|
||||
g_source_destroy (launcher->outer_source);
|
||||
g_source_destroy (launcher->inner_source);
|
||||
|
||||
g_main_loop_unref (launcher->nested_loop);
|
||||
g_main_context_unref (launcher->nested_context);
|
||||
|
||||
g_object_unref (launcher->weston_launch);
|
||||
|
||||
g_slice_free (MetaLauncher, launcher);
|
||||
g_object_unref (self->seat_proxy);
|
||||
g_object_unref (self->session_proxy);
|
||||
g_slice_free (MetaLauncher, self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_session (MetaLauncher *launcher,
|
||||
GError **error)
|
||||
{
|
||||
return meta_launcher_activate_vt (launcher, -1, error);
|
||||
if (!login1_session_call_activate_sync (launcher->session_proxy, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
sync_active (launcher);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -403,10 +364,5 @@ meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
signed char vt,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_activate_vt message;
|
||||
|
||||
message.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
|
||||
message.vt = vt;
|
||||
|
||||
return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
|
||||
return login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, NULL, error);
|
||||
}
|
||||
|
||||
@@ -1,711 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <error.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "weston-launch.h"
|
||||
|
||||
#define MAX_ARGV_SIZE 256
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
enum vt_state {
|
||||
VT_HAS_VT,
|
||||
VT_PENDING_CONFIRM,
|
||||
VT_NOT_HAVE_VT,
|
||||
};
|
||||
|
||||
struct weston_launch {
|
||||
int tty;
|
||||
int ttynr;
|
||||
int sock[2];
|
||||
struct passwd *pw;
|
||||
|
||||
int signalfd;
|
||||
|
||||
pid_t child;
|
||||
int verbose;
|
||||
|
||||
struct termios terminal_attributes;
|
||||
int kb_mode;
|
||||
enum vt_state vt_state;
|
||||
unsigned vt;
|
||||
|
||||
int drm_fd;
|
||||
};
|
||||
|
||||
union cmsg_data { unsigned char b[4]; int fd; };
|
||||
|
||||
static void quit (struct weston_launch *wl, int status);
|
||||
|
||||
static int
|
||||
weston_launch_allowed(struct weston_launch *wl)
|
||||
{
|
||||
char *session, *seat;
|
||||
int err;
|
||||
|
||||
if (getuid() == 0)
|
||||
return 1;
|
||||
|
||||
err = sd_pid_get_session(getpid(), &session);
|
||||
if (err == 0 && session) {
|
||||
if (sd_session_is_active(session) &&
|
||||
sd_session_get_seat(session, &seat) == 0) {
|
||||
free(seat);
|
||||
free(session);
|
||||
return 1;
|
||||
}
|
||||
free(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_launcher_socket(struct weston_launch *wl)
|
||||
{
|
||||
if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, wl->sock) < 0)
|
||||
error(1, errno, "socketpair failed");
|
||||
|
||||
fcntl(wl->sock[0], F_SETFD, O_CLOEXEC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_signals(struct weston_launch *wl)
|
||||
{
|
||||
int ret;
|
||||
sigset_t mask;
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
|
||||
ret = sigaction(SIGCHLD, &sa, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
|
||||
ret = sigemptyset(&mask);
|
||||
assert(ret == 0);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
ret = sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
wl->signalfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
|
||||
if (wl->signalfd < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
setenv_fd(const char *env, int fd)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof buf, "%d", fd);
|
||||
setenv(env, buf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
|
||||
reply.ret = -1;
|
||||
|
||||
if (wl->vt_state != VT_PENDING_CONFIRM) {
|
||||
error(0, 0, "unexpected CONFIRM_VT_SWITCH");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wl->drm_fd != -1) {
|
||||
int ret;
|
||||
|
||||
ret = drmDropMaster(wl->drm_fd);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to drop DRM master: %m\n");
|
||||
} else if (wl->verbose) {
|
||||
fprintf(stderr, "dropped DRM master for VT switch\n");
|
||||
}
|
||||
}
|
||||
|
||||
wl->vt_state = VT_NOT_HAVE_VT;
|
||||
ioctl(wl->tty, VT_RELDISP, 1);
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launcher: confirmed VT switch\n");
|
||||
|
||||
reply.ret = 0;
|
||||
|
||||
out:
|
||||
do {
|
||||
len = send(wl->sock[0], &reply, sizeof reply, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
struct weston_launcher_activate_vt *message;
|
||||
unsigned vt;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
|
||||
reply.ret = -1;
|
||||
|
||||
if (len != sizeof(*message)) {
|
||||
error(0, 0, "missing value in activate_vt request");
|
||||
goto out;
|
||||
}
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
|
||||
/* Negative values mean that we're activating our own VT */
|
||||
if (message->vt > 0)
|
||||
vt = message->vt;
|
||||
else
|
||||
vt = wl->vt;
|
||||
|
||||
reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
|
||||
if (reply.ret < 0)
|
||||
reply.ret = -errno;
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launch: activate VT, ret: %d\n", reply.ret);
|
||||
|
||||
out:
|
||||
do {
|
||||
len = send(wl->sock[0], &reply, sizeof reply, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
int fd = -1;
|
||||
char control[CMSG_SPACE(sizeof(fd))];
|
||||
struct cmsghdr *cmsg;
|
||||
struct stat s;
|
||||
struct msghdr nmsg;
|
||||
struct iovec iov;
|
||||
struct weston_launcher_open *message;
|
||||
union cmsg_data *data;
|
||||
int dev_major;
|
||||
|
||||
reply.header.opcode = WESTON_LAUNCHER_OPEN;
|
||||
reply.ret = -1;
|
||||
|
||||
message = msg->msg_iov->iov_base;
|
||||
if ((size_t)len < sizeof(*message))
|
||||
goto err0;
|
||||
|
||||
/* Ensure path is null-terminated */
|
||||
((char *) message)[len-1] = '\0';
|
||||
|
||||
if (stat(message->path, &s) < 0) {
|
||||
reply.ret = -errno;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
dev_major = major(s.st_rdev);
|
||||
|
||||
if (dev_major != INPUT_MAJOR &&
|
||||
dev_major != DRM_MAJOR) {
|
||||
fprintf(stderr, "Device %s is not an input or DRM device\n",
|
||||
message->path);
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dev_major == DRM_MAJOR && wl->drm_fd != -1) {
|
||||
fprintf(stderr, "Already have a DRM device open\n");
|
||||
reply.ret = -EPERM;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
fd = open(message->path, message->flags);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error opening device %s: %m\n",
|
||||
message->path);
|
||||
reply.ret = -errno;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dev_major == DRM_MAJOR) {
|
||||
wl->drm_fd = fd;
|
||||
}
|
||||
|
||||
err0:
|
||||
memset(&nmsg, 0, sizeof nmsg);
|
||||
nmsg.msg_iov = &iov;
|
||||
nmsg.msg_iovlen = 1;
|
||||
if (fd != -1) {
|
||||
nmsg.msg_control = control;
|
||||
nmsg.msg_controllen = sizeof control;
|
||||
cmsg = CMSG_FIRSTHDR(&nmsg);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
|
||||
data = (union cmsg_data *) CMSG_DATA(cmsg);
|
||||
data->fd = fd;
|
||||
nmsg.msg_controllen = cmsg->cmsg_len;
|
||||
reply.ret = 0;
|
||||
}
|
||||
iov.iov_base = &reply;
|
||||
iov.iov_len = sizeof reply;
|
||||
|
||||
if (wl->verbose)
|
||||
fprintf(stderr, "mutter-launch: opened %s: ret: %d, fd: %d\n",
|
||||
message->path, reply.ret, fd);
|
||||
do {
|
||||
len = sendmsg(wl->sock[0], &nmsg, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
close(fd);
|
||||
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_socket_msg(struct weston_launch *wl)
|
||||
{
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
char buf[BUFSIZ];
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
int ret = -1;
|
||||
ssize_t len;
|
||||
struct weston_launcher_message *message;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = sizeof buf;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = control;
|
||||
msg.msg_controllen = sizeof control;
|
||||
|
||||
do {
|
||||
len = recvmsg(wl->sock[0], &msg, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
if (len < 1)
|
||||
return -1;
|
||||
|
||||
message = (void *) buf;
|
||||
switch (message->opcode) {
|
||||
case WESTON_LAUNCHER_OPEN:
|
||||
ret = handle_open(wl, &msg, len);
|
||||
break;
|
||||
case WESTON_LAUNCHER_CONFIRM_VT_SWITCH:
|
||||
ret = handle_confirm_vt_switch(wl, &msg, len);
|
||||
break;
|
||||
case WESTON_LAUNCHER_ACTIVATE_VT:
|
||||
ret = handle_activate_vt(wl, &msg, len);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
tty_reset(struct weston_launch *wl)
|
||||
{
|
||||
struct vt_mode mode = { 0 };
|
||||
|
||||
if (ioctl(wl->tty, KDSKBMODE, wl->kb_mode))
|
||||
fprintf(stderr, "failed to restore keyboard mode: %m\n");
|
||||
|
||||
if (ioctl(wl->tty, KDSETMODE, KD_TEXT))
|
||||
fprintf(stderr, "failed to set KD_TEXT mode on tty: %m\n");
|
||||
|
||||
if (tcsetattr(wl->tty, TCSANOW, &wl->terminal_attributes) < 0)
|
||||
fprintf(stderr, "could not restore terminal to canonical mode\n");
|
||||
|
||||
mode.mode = VT_AUTO;
|
||||
if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
|
||||
fprintf(stderr, "could not reset vt handling\n");
|
||||
}
|
||||
|
||||
static void
|
||||
quit(struct weston_launch *wl, int status)
|
||||
{
|
||||
if (wl->child > 0)
|
||||
kill(wl->child, SIGKILL);
|
||||
|
||||
close(wl->signalfd);
|
||||
close(wl->sock[0]);
|
||||
|
||||
if (wl->drm_fd > 0)
|
||||
close(wl->drm_fd);
|
||||
|
||||
tty_reset(wl);
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static int
|
||||
handle_vt_switch(struct weston_launch *wl)
|
||||
{
|
||||
struct weston_launcher_event message;
|
||||
ssize_t len;
|
||||
|
||||
if (wl->vt_state == VT_HAS_VT) {
|
||||
wl->vt_state = VT_PENDING_CONFIRM;
|
||||
message.header.opcode = WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH;
|
||||
} else if (wl->vt_state == VT_NOT_HAVE_VT) {
|
||||
wl->vt_state = VT_HAS_VT;
|
||||
ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
|
||||
|
||||
if (wl->drm_fd != -1) {
|
||||
int ret;
|
||||
|
||||
ret = drmSetMaster(wl->drm_fd);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to become DRM master: %m\n");
|
||||
/* This is very, very bad, and the compositor will crash soon,
|
||||
but oh well... */
|
||||
} else if (wl->verbose) {
|
||||
fprintf(stderr, "became DRM master after VT switch\n");
|
||||
}
|
||||
}
|
||||
|
||||
message.header.opcode = WESTON_LAUNCHER_SERVER_VT_ENTER;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
message.detail = 0;
|
||||
|
||||
do {
|
||||
len = send(wl->sock[0], &message, sizeof(message), 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
handle_signal(struct weston_launch *wl)
|
||||
{
|
||||
struct signalfd_siginfo sig;
|
||||
int pid, status, ret;
|
||||
|
||||
if (read(wl->signalfd, &sig, sizeof sig) != sizeof sig) {
|
||||
error(0, errno, "reading signalfd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (sig.ssi_signo) {
|
||||
case SIGCHLD:
|
||||
pid = waitpid(-1, &status, 0);
|
||||
if (pid == wl->child) {
|
||||
wl->child = 0;
|
||||
if (WIFEXITED(status))
|
||||
ret = WEXITSTATUS(status);
|
||||
else if (WIFSIGNALED(status))
|
||||
/*
|
||||
* If weston dies because of signal N, we
|
||||
* return 10+N. This is distinct from
|
||||
* weston-launch dying because of a signal
|
||||
* (128+N).
|
||||
*/
|
||||
ret = 10 + WTERMSIG(status);
|
||||
else
|
||||
ret = 0;
|
||||
quit(wl, ret);
|
||||
}
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
if (wl->child)
|
||||
kill(wl->child, sig.ssi_signo);
|
||||
break;
|
||||
case SIGUSR1:
|
||||
return handle_vt_switch(wl);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_tty(struct weston_launch *wl)
|
||||
{
|
||||
struct stat buf;
|
||||
struct termios raw_attributes;
|
||||
struct vt_mode mode = { 0 };
|
||||
char *session;
|
||||
char path[PATH_MAX];
|
||||
int ok;
|
||||
|
||||
ok = sd_pid_get_session(getpid(), &session);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current session");
|
||||
|
||||
ok = sd_session_get_vt(session, &wl->vt);
|
||||
if (ok < 0)
|
||||
error(1, -ok, "could not determine current TTY");
|
||||
|
||||
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
|
||||
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
|
||||
if (wl->tty < 0)
|
||||
error(1, errno, "failed to open tty");
|
||||
|
||||
if (fstat(wl->tty, &buf) < 0)
|
||||
error(1, errno, "stat %s failed", path);
|
||||
|
||||
if (major(buf.st_rdev) != TTY_MAJOR)
|
||||
error(1, 0, "invalid tty device: %s", path);
|
||||
|
||||
wl->ttynr = minor(buf.st_rdev);
|
||||
|
||||
if (tcgetattr(wl->tty, &wl->terminal_attributes) < 0)
|
||||
error(1, errno, "could not get terminal attributes");
|
||||
|
||||
/* Ignore control characters and disable echo */
|
||||
raw_attributes = wl->terminal_attributes;
|
||||
cfmakeraw(&raw_attributes);
|
||||
|
||||
/* Fix up line endings to be normal (cfmakeraw hoses them) */
|
||||
raw_attributes.c_oflag |= OPOST | OCRNL;
|
||||
/* Don't generate ttou signals */
|
||||
raw_attributes.c_oflag &= ~TOSTOP;
|
||||
|
||||
if (tcsetattr(wl->tty, TCSANOW, &raw_attributes) < 0)
|
||||
error(1, errno, "could not put terminal into raw mode");
|
||||
|
||||
ioctl(wl->tty, KDGKBMODE, &wl->kb_mode);
|
||||
ok = ioctl(wl->tty, KDSKBMODE, K_OFF);
|
||||
if (ok < 0) {
|
||||
ok = ioctl(wl->tty, KDSKBMODE, K_RAW);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to set keyboard mode on tty");
|
||||
}
|
||||
|
||||
ok = ioctl(wl->tty, KDSETMODE, KD_GRAPHICS);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to set KD_GRAPHICS mode on tty");
|
||||
|
||||
wl->vt_state = VT_HAS_VT;
|
||||
mode.mode = VT_PROCESS;
|
||||
mode.relsig = SIGUSR1;
|
||||
mode.acqsig = SIGUSR1;
|
||||
ok = ioctl(wl->tty, VT_SETMODE, &mode);
|
||||
if (ok < 0)
|
||||
error(1, errno, "failed to take control of vt handling");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drop_privileges(struct weston_launch *wl)
|
||||
{
|
||||
if (setgid(wl->pw->pw_gid) < 0 ||
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 ||
|
||||
#endif
|
||||
setuid(wl->pw->pw_uid) < 0)
|
||||
error(1, errno, "dropping privileges failed");
|
||||
}
|
||||
|
||||
static void
|
||||
launch_compositor(struct weston_launch *wl, int argc, char *argv[])
|
||||
{
|
||||
char command[PATH_MAX];
|
||||
char *child_argv[MAX_ARGV_SIZE];
|
||||
sigset_t mask;
|
||||
int i;
|
||||
|
||||
if (wl->verbose)
|
||||
printf("weston-launch: spawned weston with pid: %d\n", getpid());
|
||||
|
||||
drop_privileges(wl);
|
||||
|
||||
setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
|
||||
setenv("LD_LIBRARY_PATH", LIBDIR, 1);
|
||||
unsetenv("DISPLAY");
|
||||
|
||||
/* Do not give our signal mask to the new process. */
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigprocmask(SIG_UNBLOCK, &mask, NULL);
|
||||
|
||||
snprintf (command, PATH_MAX, "%s \"$@\"", argv[0]);
|
||||
|
||||
child_argv[0] = wl->pw->pw_shell;
|
||||
child_argv[1] = "-l";
|
||||
child_argv[2] = "-c";
|
||||
child_argv[3] = command;
|
||||
for (i = 0; i < argc; ++i)
|
||||
child_argv[4 + i] = argv[i];
|
||||
child_argv[4 + i] = NULL;
|
||||
|
||||
execv(child_argv[0], child_argv);
|
||||
error(1, errno, "exec failed");
|
||||
}
|
||||
|
||||
static void
|
||||
help(const char *name)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
|
||||
fprintf(stderr, " -u, --user Start session as specified username\n");
|
||||
fprintf(stderr, " -v, --verbose Be verbose\n");
|
||||
fprintf(stderr, " -h, --help Display this help message\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct weston_launch wl;
|
||||
int i, c;
|
||||
struct option opts[] = {
|
||||
{ "verbose", no_argument, NULL, 'v' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ 0, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
memset(&wl, 0, sizeof wl);
|
||||
wl.drm_fd = -1;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
|
||||
switch (c) {
|
||||
case 'v':
|
||||
wl.verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
help("mutter-launch");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) > (MAX_ARGV_SIZE - 6))
|
||||
error(1, E2BIG, "Too many arguments to pass to weston");
|
||||
|
||||
if (optind >= argc)
|
||||
error(1, 0, "Expected program argument");
|
||||
|
||||
wl.pw = getpwuid(getuid());
|
||||
if (wl.pw == NULL)
|
||||
error(1, errno, "failed to get username");
|
||||
|
||||
if (!weston_launch_allowed(&wl))
|
||||
error(1, 0, "Permission denied. You must run from an active and local (systemd) session.");
|
||||
|
||||
if (setup_tty(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (setup_launcher_socket(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
if (setup_signals(&wl) < 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
wl.child = fork();
|
||||
if (wl.child == -1) {
|
||||
error(1, errno, "fork failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (wl.child == 0)
|
||||
launch_compositor(&wl, argc - optind, argv + optind);
|
||||
|
||||
close(wl.sock[1]);
|
||||
|
||||
while (1) {
|
||||
struct pollfd fds[2];
|
||||
int n;
|
||||
|
||||
fds[0].fd = wl.sock[0];
|
||||
fds[0].events = POLLIN;
|
||||
fds[1].fd = wl.signalfd;
|
||||
fds[1].events = POLLIN;
|
||||
|
||||
n = poll(fds, 2, -1);
|
||||
if (n < 0)
|
||||
error(0, errno, "poll failed");
|
||||
if (fds[0].revents & POLLIN)
|
||||
handle_socket_msg(&wl);
|
||||
if (fds[1].revents)
|
||||
handle_signal(&wl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 Benjamin Franzke
|
||||
* 2013 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software
|
||||
* without specific, written prior permission. The copyright holders make
|
||||
* no representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _WESTON_LAUNCH_H_
|
||||
#define _WESTON_LAUNCH_H_
|
||||
|
||||
enum weston_launcher_message_type {
|
||||
WESTON_LAUNCHER_REQUEST,
|
||||
WESTON_LAUNCHER_EVENT,
|
||||
};
|
||||
|
||||
enum weston_launcher_opcode {
|
||||
WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
WESTON_LAUNCHER_ACTIVATE_VT = (2 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST),
|
||||
};
|
||||
|
||||
enum weston_launcher_server_opcode {
|
||||
WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH = (1 << 1 | WESTON_LAUNCHER_EVENT),
|
||||
WESTON_LAUNCHER_SERVER_VT_ENTER = (2 << 1 | WESTON_LAUNCHER_EVENT),
|
||||
};
|
||||
|
||||
struct weston_launcher_message {
|
||||
int opcode;
|
||||
};
|
||||
|
||||
struct weston_launcher_open {
|
||||
struct weston_launcher_message header;
|
||||
int flags;
|
||||
char path[0];
|
||||
};
|
||||
|
||||
struct weston_launcher_activate_vt {
|
||||
struct weston_launcher_message header;
|
||||
signed char vt;
|
||||
};
|
||||
|
||||
struct weston_launcher_reply {
|
||||
struct weston_launcher_message header;
|
||||
int ret;
|
||||
};
|
||||
|
||||
struct weston_launcher_event {
|
||||
struct weston_launcher_message header;
|
||||
int detail; /* unused, but makes sure replies and events are serialized the same */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -33,9 +33,8 @@
|
||||
#include "meta-idle-monitor-xsync.h"
|
||||
#include "meta-monitor-manager-xrandr.h"
|
||||
#include "backends/meta-monitor-manager-dummy.h"
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-cursor.h"
|
||||
#include <meta/util.h>
|
||||
#include "display-private.h"
|
||||
#include "compositor/compositor-private.h"
|
||||
@@ -52,6 +51,7 @@ struct _MetaBackendX11Private
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
Time latest_evtime;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
@@ -68,21 +68,12 @@ handle_alarm_notify (MetaBackend *backend,
|
||||
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);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window stage_window = meta_backend_x11_get_xwindow (x11);
|
||||
|
||||
if (device_event->event != stage_window)
|
||||
{
|
||||
@@ -99,6 +90,21 @@ translate_device_event (MetaBackendX11 *x11,
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
}
|
||||
|
||||
if (!device_event->send_event && device_event->time != CurrentTime)
|
||||
{
|
||||
if (device_event->time < priv->latest_evtime)
|
||||
{
|
||||
/* Emulated pointer events received after XIRejectTouch is received
|
||||
* on a passive touch grab will contain older timestamps, update those
|
||||
* so we dont get InvalidTime at grabs.
|
||||
*/
|
||||
device_event->time = priv->latest_evtime;
|
||||
}
|
||||
|
||||
/* Update the internal latest evtime, for any possible later use */
|
||||
priv->latest_evtime = device_event->time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
@@ -128,6 +134,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
case XI_TouchBegin:
|
||||
case XI_TouchUpdate:
|
||||
case XI_TouchEnd:
|
||||
translate_device_event (x11, (XIDeviceEvent *) input_event);
|
||||
break;
|
||||
default:
|
||||
@@ -153,17 +162,14 @@ handle_host_xevent (MetaBackend *backend,
|
||||
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)
|
||||
{
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
clutter_x11_handle_event (event);
|
||||
}
|
||||
|
||||
XFreeEventData (priv->xdisplay, &event->xcookie);
|
||||
}
|
||||
@@ -307,6 +313,12 @@ meta_backend_x11_create_monitor_manager (MetaBackend *backend)
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -318,6 +330,9 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
int ret;
|
||||
|
||||
if (timestamp != CurrentTime)
|
||||
timestamp = MAX (timestamp, priv->latest_evtime);
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
@@ -326,14 +341,10 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
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),
|
||||
meta_backend_x11_get_xwindow (x11),
|
||||
timestamp,
|
||||
meta_cursor_create_x_cursor (priv->xdisplay, cursor),
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
@@ -355,6 +366,22 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
|
||||
return (ret == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
XIWarpPointer (priv->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
None,
|
||||
meta_backend_x11_get_xwindow (x11),
|
||||
0, 0, 0, 0,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
{
|
||||
@@ -363,9 +390,11 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
backend_class->post_init = meta_backend_x11_post_init;
|
||||
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
|
||||
|
||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -383,3 +412,15 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
|
||||
return priv->xdisplay;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
|
||||
if (compositor == NULL)
|
||||
return None;
|
||||
|
||||
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
|
||||
return clutter_x11_get_stage_window (stage);
|
||||
}
|
||||
|
||||
@@ -53,4 +53,6 @@ GType meta_backend_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);
|
||||
|
||||
Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend);
|
||||
|
||||
#endif /* META_BACKEND_X11_H */
|
||||
|
||||
99
src/backends/x11/meta-cursor-renderer-x11.c
Normal file
99
src/backends/x11/meta-cursor-renderer-x11.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
struct _MetaCursorRendererX11Private
|
||||
{
|
||||
gboolean server_cursor_visible;
|
||||
};
|
||||
typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER);
|
||||
|
||||
static gboolean
|
||||
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer);
|
||||
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
|
||||
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Window xwindow = meta_backend_x11_get_xwindow (backend);
|
||||
|
||||
if (xwindow == None)
|
||||
return FALSE;
|
||||
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer);
|
||||
gboolean has_server_cursor = FALSE;
|
||||
|
||||
if (cursor_ref)
|
||||
{
|
||||
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
|
||||
if (cursor != META_CURSOR_NONE)
|
||||
{
|
||||
Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor);
|
||||
XDefineCursor (xdisplay, xwindow, xcursor);
|
||||
XFlush (xdisplay);
|
||||
XFreeCursor (xdisplay, xcursor);
|
||||
|
||||
has_server_cursor = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_server_cursor != priv->server_cursor_visible)
|
||||
{
|
||||
if (has_server_cursor)
|
||||
XFixesShowCursor (xdisplay, xwindow);
|
||||
else
|
||||
XFixesHideCursor (xdisplay, xwindow);
|
||||
|
||||
priv->server_cursor_visible = has_server_cursor;
|
||||
}
|
||||
|
||||
return priv->server_cursor_visible;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_x11_class_init (MetaCursorRendererX11Class *klass)
|
||||
{
|
||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
|
||||
|
||||
renderer_class->update_cursor = meta_cursor_renderer_x11_update_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_x11_init (MetaCursorRendererX11 *x11)
|
||||
{
|
||||
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
|
||||
|
||||
/* XFixes has no way to retrieve the current cursor visibility. */
|
||||
priv->server_cursor_visible = TRUE;
|
||||
}
|
||||
52
src/backends/x11/meta-cursor-renderer-x11.h
Normal file
52
src/backends/x11/meta-cursor-renderer-x11.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_RENDERER_X11_H
|
||||
#define META_CURSOR_RENDERER_X11_H
|
||||
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER_X11 (meta_cursor_renderer_x11_get_type ())
|
||||
#define META_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11))
|
||||
#define META_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
||||
#define META_IS_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11))
|
||||
#define META_IS_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_X11))
|
||||
#define META_CURSOR_RENDERER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
||||
|
||||
typedef struct _MetaCursorRendererX11 MetaCursorRendererX11;
|
||||
typedef struct _MetaCursorRendererX11Class MetaCursorRendererX11Class;
|
||||
|
||||
struct _MetaCursorRendererX11
|
||||
{
|
||||
MetaCursorRenderer parent;
|
||||
};
|
||||
|
||||
struct _MetaCursorRendererX11Class
|
||||
{
|
||||
MetaCursorRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_X11_H */
|
||||
@@ -918,6 +918,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
XUngrabServer (manager_xrandr->xdisplay);
|
||||
XFlush (manager_xrandr->xdisplay);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -68,7 +68,7 @@ meta_create_color_texture_4ub (guint8 red,
|
||||
|
||||
/**
|
||||
* meta_create_texture_pipeline:
|
||||
* @src_texture: (allow-none): texture to use initially for the layer
|
||||
* @src_texture: (nullable): texture to use initially for the layer
|
||||
*
|
||||
* Creates a pipeline with a single layer. Using a common template
|
||||
* makes it easier for Cogl to share a shader for different uses in
|
||||
|
||||
@@ -385,6 +385,10 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-begin",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
|
||||
@@ -401,6 +405,10 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
||||
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-end",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
display->grab_have_pointer = FALSE;
|
||||
@@ -595,7 +603,7 @@ meta_compositor_unmanage (MetaCompositor *compositor)
|
||||
/**
|
||||
* meta_shape_cow_for_window:
|
||||
* @compositor: A #MetaCompositor
|
||||
* @window: (allow-none): A #MetaWindow to shape the COW for
|
||||
* @window: (nullable): A #MetaWindow to shape the COW for
|
||||
*
|
||||
* Sets an bounding shape on the COW so that the given window
|
||||
* is exposed. If @window is %NULL it clears the shape again.
|
||||
@@ -691,12 +699,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen)
|
||||
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
|
||||
meta_window_actor_sync_updates_frozen (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1356,3 +1363,22 @@ meta_compositor_hide_tile_preview (MetaCompositor *compositor)
|
||||
{
|
||||
meta_plugin_manager_hide_tile_preview (compositor->plugin_mgr);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_plugin_manager_show_window_menu_for_rect (compositor->plugin_mgr, window, menu, rect);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <meta/meta-plugin.h>
|
||||
#include <meta/meta-version.h>
|
||||
#include "meta-module.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
@@ -68,7 +69,7 @@ meta_module_load (GTypeModule *gmodule)
|
||||
(gpointer *)(void *)®ister_type) &&
|
||||
info && register_type)
|
||||
{
|
||||
if (info->version_api != MUTTER_PLUGIN_API_VERSION)
|
||||
if (info->version_api != META_PLUGIN_API_VERSION)
|
||||
g_warning ("Plugin API mismatch for [%s]", priv->path);
|
||||
else
|
||||
{
|
||||
|
||||
@@ -356,3 +356,38 @@ meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
||||
|
||||
if (display->display_opening)
|
||||
return;
|
||||
|
||||
if (klass->show_window_menu)
|
||||
klass->show_window_menu (plugin, window, menu, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *plugin_mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
||||
|
||||
if (display->display_opening)
|
||||
return;
|
||||
|
||||
if (klass->show_window_menu_for_rect)
|
||||
klass->show_window_menu_for_rect (plugin, window, menu, rect);
|
||||
}
|
||||
|
||||
@@ -80,4 +80,17 @@ gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
|
||||
|
||||
void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -121,17 +121,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
||||
/* The first element in this array also defines the default parameters
|
||||
* for newly created classes */
|
||||
MetaShadowClassInfo default_shadow_classes[] = {
|
||||
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "normal", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "dialog", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "modal_dialog", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
|
||||
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
|
||||
{ "border", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "menu", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
|
||||
|
||||
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
{ "popup-menu", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
|
||||
{ "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } },
|
||||
{ "attached", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
|
||||
{ "attached", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
|
||||
@@ -189,7 +189,7 @@ meta_shadow_unref (MetaShadow *shadow)
|
||||
* @window_y: y position of the region to paint a shadow for
|
||||
* @window_width: actual width of the region to paint a shadow for
|
||||
* @window_height: actual height of the region to paint a shadow for
|
||||
* @clip: (allow-none): if non-%NULL specifies the visible portion
|
||||
* @clip: (nullable): if non-%NULL specifies the visible portion
|
||||
* of the shadow.
|
||||
* @clip_strictly: if %TRUE, drawing will be clipped strictly
|
||||
* to @clip, otherwise, it will be only used to optimize
|
||||
@@ -496,7 +496,12 @@ get_box_filter_size (int radius)
|
||||
static int
|
||||
get_shadow_spread (int radius)
|
||||
{
|
||||
int d = get_box_filter_size (radius);
|
||||
int d;
|
||||
|
||||
if (radius == 0)
|
||||
return 0;
|
||||
|
||||
d = get_box_filter_size (radius);
|
||||
|
||||
if (d % 2 == 1)
|
||||
return 3 * (d / 2);
|
||||
|
||||
@@ -108,6 +108,62 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
get_output_scale (int output_id)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||
MetaOutput *outputs;
|
||||
guint n_outputs, i;
|
||||
int output_scale = 1;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].output_id == output_id)
|
||||
{
|
||||
output_scale = outputs[i].scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output_scale;
|
||||
}
|
||||
|
||||
double
|
||||
meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor);
|
||||
MetaWaylandSurface *surface = priv->surface;
|
||||
MetaWindow *window = surface->window;
|
||||
int output_scale = 1;
|
||||
|
||||
while (surface)
|
||||
{
|
||||
if (surface->window)
|
||||
{
|
||||
window = surface->window;
|
||||
break;
|
||||
}
|
||||
surface = surface->sub.parent;
|
||||
}
|
||||
|
||||
/* XXX: We do not handle x11 clients yet */
|
||||
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
output_scale = get_output_scale (window->monitor->output_id);
|
||||
|
||||
return (double)output_scale / (double)priv->surface->scale;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (actor));
|
||||
double output_scale = meta_surface_actor_wayland_get_scale (actor);
|
||||
|
||||
clutter_actor_set_scale (CLUTTER_ACTOR (stex), output_scale, output_scale);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
@@ -116,6 +172,42 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
return priv->surface->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self));
|
||||
|
||||
clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), for_height, min_width_p, natural_width_p);
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p *= scale;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p *= scale;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self));
|
||||
|
||||
clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), for_width, min_height_p, natural_height_p);
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p *= scale;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p *= scale;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_dispose (GObject *object)
|
||||
{
|
||||
@@ -130,8 +222,12 @@ static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||
|
||||
@@ -61,6 +61,9 @@ MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWay
|
||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
|
||||
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
|
||||
|
||||
void meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "window-private.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "x11/window-x11.h"
|
||||
|
||||
struct _MetaSurfaceActorX11Private
|
||||
{
|
||||
@@ -143,7 +144,7 @@ update_pixmap (MetaSurfaceActorX11 *self)
|
||||
if (priv->pixmap == None)
|
||||
{
|
||||
Pixmap new_pixmap;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
@@ -312,7 +313,7 @@ sync_unredirected (MetaSurfaceActorX11 *self)
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
@@ -404,7 +405,7 @@ create_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
Display *xdisplay = meta_display_get_xdisplay (priv->display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,7 @@ void meta_window_actor_update_shape (MetaWindowActor *self);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
gboolean updates_frozen);
|
||||
void meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
|
||||
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
gboolean no_delay_frame);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-x11.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
@@ -549,6 +550,16 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
cairo_region_get_extents (priv->shape_region, bounds);
|
||||
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
|
||||
{
|
||||
double scale = priv->surface ?
|
||||
meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (priv->surface)) : 1.;
|
||||
bounds->x *= scale;
|
||||
bounds->y *= scale;
|
||||
bounds->width *= scale;
|
||||
bounds->height *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -735,9 +746,11 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* Add shadows to override redirect windows (e.g., Gtk menus).
|
||||
* Add shadows to override redirect windows on X11 unless the toolkit
|
||||
* indicates that it is handling shadows itself (e.g., Gtk menus).
|
||||
*/
|
||||
if (priv->window->override_redirect)
|
||||
if (priv->window->override_redirect &&
|
||||
!priv->window->has_custom_frame_extents)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@@ -1139,7 +1152,7 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaRectangle window_rect;
|
||||
|
||||
meta_window_get_input_rect (priv->window, &window_rect);
|
||||
meta_window_get_buffer_rect (priv->window, &window_rect);
|
||||
|
||||
/* When running as a Wayland compositor we catch size changes when new
|
||||
* buffers are attached */
|
||||
@@ -1313,7 +1326,7 @@ meta_window_actor_new (MetaWindow *window)
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
|
||||
meta_window_actor_sync_updates_frozen (self);
|
||||
|
||||
/* If a window doesn't start off with updates frozen, we should
|
||||
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
|
||||
@@ -2009,7 +2022,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
gboolean updates_frozen)
|
||||
{
|
||||
@@ -2026,3 +2039,12 @@ meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
meta_window_actor_thaw (self);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
|
||||
pkglibdir=@MUTTER_PLUGIN_DIR@
|
||||
pkglibdir = $(MUTTER_PLUGIN_DIR)
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
|
||||
AM_CPPFLAGS = \
|
||||
$(MUTTER_CFLAGS) \
|
||||
-I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/src \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"
|
||||
|
||||
default_la_CFLAGS = -fPIC
|
||||
default_la_SOURCES = default.c
|
||||
default_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
default_la_LIBADD = @CLUTTER_LIBS@
|
||||
default_la_LIBADD = $(CLUTTER_LIBS)
|
||||
|
||||
pkglib_LTLIBRARIES = default.la
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ meta_region_builder_finish (MetaRegionBuilder *builder)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* MetaRegionIterator */
|
||||
|
||||
@@ -171,7 +171,7 @@ meta_region_iterator_next (MetaRegionIterator *iter)
|
||||
iter->line_end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_expanded_rect (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
|
||||
@@ -546,6 +546,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
return b_area - a_area; /* positive ret value denotes b > a, ... */
|
||||
}
|
||||
|
||||
/* ... and another helper for get_minimal_spanning_set_for_region()... */
|
||||
static gboolean
|
||||
check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
|
||||
{
|
||||
/* Check whether @strut actually aligns to the side of @rect it claims */
|
||||
switch (strut->side)
|
||||
{
|
||||
case META_SIDE_TOP:
|
||||
return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
|
||||
case META_SIDE_BOTTOM:
|
||||
return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
|
||||
case META_SIDE_LEFT:
|
||||
return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
|
||||
case META_SIDE_RIGHT:
|
||||
return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region:
|
||||
* @basic_rect: Input rectangle
|
||||
@@ -630,7 +650,8 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
|
||||
{
|
||||
GList *rect_iter;
|
||||
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
|
||||
MetaStrut *strut = (MetaStrut*)strut_iter->data;
|
||||
MetaRectangle *strut_rect = &strut->rect;
|
||||
|
||||
tmp_list = ret;
|
||||
ret = NULL;
|
||||
@@ -638,7 +659,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
while (rect_iter)
|
||||
{
|
||||
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
|
||||
if (!meta_rectangle_overlap (rect, strut_rect))
|
||||
|
||||
if (!meta_rectangle_overlap (strut_rect, rect) ||
|
||||
!check_strut_align (strut, basic_rect))
|
||||
ret = g_list_prepend (ret, rect);
|
||||
else
|
||||
{
|
||||
|
||||
@@ -275,11 +275,6 @@ meta_window_constrain (MetaWindow *window,
|
||||
ConstraintPriority priority = PRIORITY_MINIMUM;
|
||||
gboolean satisfied = FALSE;
|
||||
|
||||
/* WARNING: orig and new specify positions and sizes of the inner window,
|
||||
* not the outer. This is a common gotcha since half the constraints
|
||||
* deal with inner window position/size and half deal with outer. See
|
||||
* doc/how-constraints-works.txt for more information.
|
||||
*/
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d\n",
|
||||
window->desc,
|
||||
@@ -409,31 +404,6 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly - don't get fooled by
|
||||
* windows which hide their titlebar when maximized or which are
|
||||
* client decorated; that's not the same as fullscreen, even
|
||||
* if there are no struts making the workarea smaller than
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
/*
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
*/
|
||||
meta_warning (
|
||||
"Treating resize request of legacy application %s as a "
|
||||
"fullscreen request\n",
|
||||
window->desc);
|
||||
meta_window_make_fullscreen_internal (window);
|
||||
}
|
||||
|
||||
/* Log all this information for debugging */
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Setting up constraint info:\n"
|
||||
@@ -511,8 +481,6 @@ place_window_if_needed(MetaWindow *window,
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
|
||||
|
||||
info->current.x = placed_rect.x;
|
||||
info->current.y = placed_rect.y;
|
||||
|
||||
@@ -544,10 +512,10 @@ place_window_if_needed(MetaWindow *window,
|
||||
.083 * info->work_area_monitor.height;
|
||||
}
|
||||
|
||||
/* idle_move_resize() uses the user_rect, so make sure it uses the
|
||||
* placed coordinates (bug #556696).
|
||||
/* idle_move_resize() uses the unconstrained_rect, so make sure it
|
||||
* uses the placed coordinates (bug #556696).
|
||||
*/
|
||||
window->user_rect = info->current;
|
||||
window->unconstrained_rect = info->current;
|
||||
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
window->maximize_vertically_after_placement)
|
||||
@@ -620,7 +588,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_fully_onscreen =
|
||||
meta_rectangle_contained_in_region (info->usable_screen_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_fully_onscreen)
|
||||
if (old != window->require_fully_onscreen)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_fully_onscreen for %s toggled to %s\n",
|
||||
window->desc,
|
||||
@@ -633,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_on_single_monitor =
|
||||
meta_rectangle_contained_in_region (info->usable_monitor_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_on_single_monitor)
|
||||
if (old != window->require_on_single_monitor)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_on_single_monitor for %s toggled to %s\n",
|
||||
window->desc,
|
||||
@@ -644,18 +612,15 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame && window->decorated)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
MetaRectangle titlebar_rect;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
|
||||
titlebar_rect = info->current;
|
||||
titlebar_rect.height = borders.visible.top;
|
||||
old = window->require_titlebar_visible;
|
||||
window->require_titlebar_visible =
|
||||
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
||||
&titlebar_rect);
|
||||
if (old ^ window->require_titlebar_visible)
|
||||
if (old != window->require_titlebar_visible)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_titlebar_visible for %s toggled to %s\n",
|
||||
window->desc,
|
||||
@@ -910,6 +875,7 @@ constrain_size_increments (MetaWindow *window,
|
||||
int new_width, new_height;
|
||||
gboolean constraint_already_satisfied;
|
||||
MetaRectangle *start_rect;
|
||||
MetaRectangle client_rect;
|
||||
|
||||
if (priority > PRIORITY_SIZE_HINTS_INCREMENTS)
|
||||
return TRUE;
|
||||
@@ -920,13 +886,15 @@ constrain_size_increments (MetaWindow *window,
|
||||
info->action_type == ACTION_MOVE)
|
||||
return TRUE;
|
||||
|
||||
meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
bh = window->size_hints.base_height;
|
||||
hi = window->size_hints.height_inc;
|
||||
bw = window->size_hints.base_width;
|
||||
wi = window->size_hints.width_inc;
|
||||
extra_height = (info->current.height - bh) % hi;
|
||||
extra_width = (info->current.width - bw) % wi;
|
||||
extra_height = (client_rect.height - bh) % hi;
|
||||
extra_width = (client_rect.width - bw) % wi;
|
||||
/* ignore size increments for maximized windows */
|
||||
if (window->maximized_horizontally)
|
||||
extra_width *= 0;
|
||||
@@ -940,8 +908,8 @@ constrain_size_increments (MetaWindow *window,
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
new_width = info->current.width - extra_width;
|
||||
new_height = info->current.height - extra_height;
|
||||
new_width = client_rect.width - extra_width;
|
||||
new_height = client_rect.height - extra_height;
|
||||
|
||||
/* Adjusting down instead of up (as done in the above two lines) may
|
||||
* violate minimum size constraints; fix the adjustment if this
|
||||
@@ -952,6 +920,14 @@ constrain_size_increments (MetaWindow *window,
|
||||
if (new_height < window->size_hints.min_height)
|
||||
new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi;
|
||||
|
||||
{
|
||||
client_rect.width = new_width;
|
||||
client_rect.height = new_height;
|
||||
meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
|
||||
new_width = client_rect.width;
|
||||
new_height = client_rect.height;
|
||||
}
|
||||
|
||||
/* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
|
||||
* See bug 448183
|
||||
*/
|
||||
|
||||
204
src/core/core.c
204
src/core/core.c
@@ -29,6 +29,9 @@
|
||||
#include <meta/errors.h>
|
||||
#include "util-private.h"
|
||||
|
||||
#include "x11/window-x11.h"
|
||||
#include "x11/window-x11-private.h"
|
||||
|
||||
/* Looks up the MetaWindow representing the frame of the given X window.
|
||||
* Used as a helper function by a bunch of the functions below.
|
||||
*
|
||||
@@ -69,6 +72,8 @@ meta_core_get (Display *xdisplay,
|
||||
|
||||
MetaDisplay *display = meta_display_for_x_display (xdisplay);
|
||||
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
|
||||
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
|
||||
MetaWindowX11Private *priv = window_x11->priv;
|
||||
|
||||
va_start (args, xwindow);
|
||||
|
||||
@@ -86,28 +91,27 @@ meta_core_get (Display *xdisplay,
|
||||
*/
|
||||
|
||||
if (request != META_CORE_WINDOW_HAS_FRAME &&
|
||||
(window == NULL || window->frame == NULL)) {
|
||||
(window == NULL || window->frame == NULL))
|
||||
{
|
||||
meta_bug ("No such frame window 0x%lx!\n", xwindow);
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (request != META_CORE_GET_END) {
|
||||
|
||||
while (request != META_CORE_GET_END)
|
||||
{
|
||||
gpointer answer = va_arg (args, gpointer);
|
||||
|
||||
switch (request) {
|
||||
switch (request)
|
||||
{
|
||||
case META_CORE_WINDOW_HAS_FRAME:
|
||||
*((gboolean*)answer) = window != NULL && window->frame != NULL;
|
||||
if (!*((gboolean*)answer)) goto out; /* see above */
|
||||
break;
|
||||
case META_CORE_GET_CLIENT_WIDTH:
|
||||
*((gint*)answer) = window->rect.width;
|
||||
*((gint*)answer) = priv->client_rect.width;
|
||||
break;
|
||||
case META_CORE_GET_CLIENT_HEIGHT:
|
||||
*((gint*)answer) = window->rect.height;
|
||||
break;
|
||||
case META_CORE_GET_CLIENT_XWINDOW:
|
||||
*((Window*)answer) = window->xwindow;
|
||||
*((gint*)answer) = priv->client_rect.height;
|
||||
break;
|
||||
case META_CORE_GET_FRAME_FLAGS:
|
||||
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
|
||||
@@ -121,36 +125,12 @@ meta_core_get (Display *xdisplay,
|
||||
case META_CORE_GET_ICON:
|
||||
*((GdkPixbuf**)answer) = window->icon;
|
||||
break;
|
||||
case META_CORE_GET_X:
|
||||
meta_window_get_position (window, (int*)answer, NULL);
|
||||
break;
|
||||
case META_CORE_GET_Y:
|
||||
meta_window_get_position (window, NULL, (int*)answer);
|
||||
break;
|
||||
case META_CORE_GET_FRAME_WORKSPACE:
|
||||
*((gint*)answer) = meta_window_get_net_wm_desktop (window);
|
||||
break;
|
||||
case META_CORE_GET_FRAME_X:
|
||||
*((gint*)answer) = window->frame->rect.x;
|
||||
break;
|
||||
case META_CORE_GET_FRAME_Y:
|
||||
*((gint*)answer) = window->frame->rect.y;
|
||||
break;
|
||||
case META_CORE_GET_FRAME_WIDTH:
|
||||
*((gint*)answer) = window->frame->rect.width;
|
||||
break;
|
||||
case META_CORE_GET_FRAME_HEIGHT:
|
||||
*((gint*)answer) = window->frame->rect.height;
|
||||
case META_CORE_GET_FRAME_RECT:
|
||||
meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
|
||||
break;
|
||||
case META_CORE_GET_THEME_VARIANT:
|
||||
*((char**)answer) = window->gtk_theme_variant;
|
||||
break;
|
||||
case META_CORE_GET_SCREEN_WIDTH:
|
||||
*((gint*)answer) = window->screen->rect.width;
|
||||
break;
|
||||
case META_CORE_GET_SCREEN_HEIGHT:
|
||||
*((gint*)answer) = window->screen->rect.height;
|
||||
break;
|
||||
|
||||
default:
|
||||
meta_warning("Unknown window information request: %d\n", request);
|
||||
@@ -173,38 +153,6 @@ meta_core_queue_frame_resize (Display *xdisplay,
|
||||
meta_window_frame_size_changed (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_move (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_resize (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int gravity,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_resize_with_gravity (window, TRUE, width, height, gravity);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_raise (Display *xdisplay,
|
||||
Window frame_xwindow)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_raise (window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lower_window_and_transients (MetaWindow *window,
|
||||
gpointer data)
|
||||
@@ -430,9 +378,9 @@ meta_core_change_workspace (Display *xdisplay,
|
||||
void
|
||||
meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
@@ -441,121 +389,23 @@ meta_core_show_window_menu (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
meta_window_show_menu (window, root_x, root_y, button, timestamp);
|
||||
meta_window_show_menu (window, menu, root_x, root_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||
int workspace,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers)
|
||||
meta_core_show_window_menu_for_rect (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect,
|
||||
guint32 timestamp)
|
||||
{
|
||||
const char *name;
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
name = NULL;
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
switch (menu_op)
|
||||
{
|
||||
case META_MENU_OP_NONE:
|
||||
/* No keybinding for this one */
|
||||
break;
|
||||
case META_MENU_OP_DELETE:
|
||||
name = "close";
|
||||
break;
|
||||
case META_MENU_OP_MINIMIZE:
|
||||
name = "minimize";
|
||||
break;
|
||||
case META_MENU_OP_UNMAXIMIZE:
|
||||
name = "unmaximize";
|
||||
break;
|
||||
case META_MENU_OP_MAXIMIZE:
|
||||
name = "maximize";
|
||||
break;
|
||||
case META_MENU_OP_UNSHADE:
|
||||
case META_MENU_OP_SHADE:
|
||||
name = "toggle_shaded";
|
||||
break;
|
||||
case META_MENU_OP_UNSTICK:
|
||||
case META_MENU_OP_STICK:
|
||||
name = "toggle-on-all-workspaces";
|
||||
break;
|
||||
case META_MENU_OP_ABOVE:
|
||||
case META_MENU_OP_UNABOVE:
|
||||
name = "toggle-above";
|
||||
break;
|
||||
case META_MENU_OP_WORKSPACES:
|
||||
switch (workspace)
|
||||
{
|
||||
case 1:
|
||||
name = "move-to-workspace-1";
|
||||
break;
|
||||
case 2:
|
||||
name = "move-to-workspace-2";
|
||||
break;
|
||||
case 3:
|
||||
name = "move-to-workspace-3";
|
||||
break;
|
||||
case 4:
|
||||
name = "move-to-workspace-4";
|
||||
break;
|
||||
case 5:
|
||||
name = "move-to-workspace-5";
|
||||
break;
|
||||
case 6:
|
||||
name = "move-to-workspace-6";
|
||||
break;
|
||||
case 7:
|
||||
name = "move-to-workspace-7";
|
||||
break;
|
||||
case 8:
|
||||
name = "move-to-workspace-8";
|
||||
break;
|
||||
case 9:
|
||||
name = "move-to-workspace-9";
|
||||
break;
|
||||
case 10:
|
||||
name = "move-to-workspace-10";
|
||||
break;
|
||||
case 11:
|
||||
name = "move-to-workspace-11";
|
||||
break;
|
||||
case 12:
|
||||
name = "move-to-workspace-12";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case META_MENU_OP_MOVE:
|
||||
name = "begin-move";
|
||||
break;
|
||||
case META_MENU_OP_RESIZE:
|
||||
name = "begin-resize";
|
||||
break;
|
||||
case META_MENU_OP_MOVE_LEFT:
|
||||
name = "move-to-workspace-left";
|
||||
break;
|
||||
case META_MENU_OP_MOVE_RIGHT:
|
||||
name = "move-to-workspace-right";
|
||||
break;
|
||||
case META_MENU_OP_MOVE_UP:
|
||||
name = "move-to-workspace-up";
|
||||
break;
|
||||
case META_MENU_OP_MOVE_DOWN:
|
||||
name = "move-to-workspace-down";
|
||||
break;
|
||||
case META_MENU_OP_RECOVER:
|
||||
/* No keybinding for this one */
|
||||
break;
|
||||
}
|
||||
|
||||
if (name)
|
||||
{
|
||||
meta_prefs_get_window_binding (name, keysym, modifiers);
|
||||
}
|
||||
else
|
||||
{
|
||||
*keysym = 0;
|
||||
*modifiers = 0;
|
||||
}
|
||||
meta_window_show_menu_for_rect (window, menu, rect);
|
||||
}
|
||||
|
||||
const char*
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/* Don't include core headers here */
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -33,21 +34,12 @@ typedef enum
|
||||
META_CORE_WINDOW_HAS_FRAME,
|
||||
META_CORE_GET_CLIENT_WIDTH,
|
||||
META_CORE_GET_CLIENT_HEIGHT,
|
||||
META_CORE_GET_CLIENT_XWINDOW,
|
||||
META_CORE_GET_FRAME_FLAGS,
|
||||
META_CORE_GET_FRAME_TYPE,
|
||||
META_CORE_GET_MINI_ICON,
|
||||
META_CORE_GET_ICON,
|
||||
META_CORE_GET_X,
|
||||
META_CORE_GET_Y,
|
||||
META_CORE_GET_FRAME_WORKSPACE,
|
||||
META_CORE_GET_FRAME_X,
|
||||
META_CORE_GET_FRAME_Y,
|
||||
META_CORE_GET_FRAME_WIDTH,
|
||||
META_CORE_GET_FRAME_HEIGHT,
|
||||
META_CORE_GET_FRAME_RECT,
|
||||
META_CORE_GET_THEME_VARIANT,
|
||||
META_CORE_GET_SCREEN_WIDTH,
|
||||
META_CORE_GET_SCREEN_HEIGHT,
|
||||
} MetaCoreGetType;
|
||||
|
||||
/* General information function about the given window. Pass in a sequence of
|
||||
@@ -56,8 +48,8 @@ typedef enum
|
||||
* For example:
|
||||
*
|
||||
* meta_core_get (my_display, my_window,
|
||||
* META_CORE_GET_X, &x,
|
||||
* META_CORE_GET_Y, &y,
|
||||
* META_CORE_GET_FRAME_WIDTH, &width,
|
||||
* META_CORE_GET_FRAME_HEIGHT, &height,
|
||||
* META_CORE_GET_END);
|
||||
*
|
||||
* If the window doesn't have a frame, this will raise a meta_bug. To suppress
|
||||
@@ -93,19 +85,6 @@ void meta_core_get (Display *xdisplay,
|
||||
void meta_core_queue_frame_resize (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
/* Move as a result of user operation */
|
||||
void meta_core_user_move (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int x,
|
||||
int y);
|
||||
void meta_core_user_resize (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int gravity,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void meta_core_user_raise (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
void meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp);
|
||||
@@ -155,15 +134,16 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
|
||||
void meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||
int workspace,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers);
|
||||
void meta_core_show_window_menu_for_rect (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
|
||||
@@ -39,35 +39,58 @@
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
static void meta_window_present_delete_dialog (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
static void
|
||||
delete_ping_reply_func (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
void *user_data)
|
||||
{
|
||||
meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc);
|
||||
|
||||
/* we do nothing */
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
MetaWindow *ours = (MetaWindow*) user_data;
|
||||
MetaWindow *window = user_data;
|
||||
|
||||
ours->dialog_pid = -1;
|
||||
window->dialog_pid = -1;
|
||||
|
||||
/* exit status of 1 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||
meta_window_kill (ours);
|
||||
meta_window_kill (window);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_ping_timeout_func (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
void *user_data)
|
||||
present_existing_delete_dialog (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Presenting existing ping dialog for %s\n",
|
||||
window->desc);
|
||||
|
||||
if (window->dialog_pid >= 0)
|
||||
{
|
||||
GSList *windows;
|
||||
GSList *tmp;
|
||||
|
||||
/* Activate transient for window that belongs to
|
||||
* mutter-dialog
|
||||
*/
|
||||
|
||||
windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
if (w->transient_for == window && w->res_class &&
|
||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||
{
|
||||
meta_window_activate (w, timestamp);
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_delete_dialog (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
char *window_title;
|
||||
gchar *window_content, *tmp;
|
||||
@@ -79,7 +102,7 @@ delete_ping_timeout_func (MetaWindow *window,
|
||||
|
||||
if (window->dialog_pid >= 0)
|
||||
{
|
||||
meta_window_present_delete_dialog (window, timestamp);
|
||||
present_existing_delete_dialog (window, timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,15 +151,33 @@ delete_ping_timeout_func (MetaWindow *window,
|
||||
g_child_watch_add (dialog_pid, dialog_exited, window);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_delete_dialog (MetaWindow *window)
|
||||
{
|
||||
if (window->dialog_pid > -1)
|
||||
kill (window->dialog_pid, SIGTERM);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_alive (MetaWindow *window,
|
||||
gboolean is_alive)
|
||||
{
|
||||
if (window->is_alive == is_alive)
|
||||
return;
|
||||
|
||||
window->is_alive = is_alive;
|
||||
|
||||
if (window->is_alive)
|
||||
kill_delete_dialog (window);
|
||||
else
|
||||
show_delete_dialog (window, CurrentTime);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_check_alive (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_display_ping_window (window,
|
||||
timestamp,
|
||||
delete_ping_reply_func,
|
||||
delete_ping_timeout_func,
|
||||
NULL);
|
||||
meta_display_ping_window (window, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -191,39 +232,3 @@ meta_window_free_delete_dialog (MetaWindow *window)
|
||||
window->dialog_pid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
||||
{
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Presenting existing ping dialog for %s\n",
|
||||
window->desc);
|
||||
|
||||
if (window->dialog_pid >= 0)
|
||||
{
|
||||
GSList *windows;
|
||||
GSList *tmp;
|
||||
|
||||
/* Activate transient for window that belongs to
|
||||
* mutter-dialog
|
||||
*/
|
||||
|
||||
windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
if (w->transient_for == window && w->res_class &&
|
||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||
{
|
||||
meta_window_activate (w, timestamp);
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/display.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "gesture-tracker-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/barrier.h>
|
||||
#include <clutter/clutter.h>
|
||||
@@ -53,10 +54,6 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
||||
|
||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
|
||||
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||
@@ -185,7 +182,6 @@ struct _MetaDisplay
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
MetaWindow *grab_window;
|
||||
Window grab_xwindow;
|
||||
int grab_button;
|
||||
int grab_anchor_root_x;
|
||||
int grab_anchor_root_y;
|
||||
@@ -247,10 +243,6 @@ struct _MetaDisplay
|
||||
/* Managed by group.c */
|
||||
GHashTable *groups_by_leader;
|
||||
|
||||
/* currently-active window menu if any */
|
||||
MetaWindowMenu *window_menu;
|
||||
MetaWindow *window_with_menu;
|
||||
|
||||
/* Managed by window-props.c */
|
||||
MetaWindowPropHooks *prop_hooks_table;
|
||||
GHashTable *prop_hooks;
|
||||
@@ -262,6 +254,8 @@ struct _MetaDisplay
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
MetaGestureTracker *gesture_tracker;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
@@ -367,9 +361,7 @@ MetaDisplay* meta_get_display (void);
|
||||
Cursor meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor);
|
||||
|
||||
void meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
MetaGrabOp op,
|
||||
guint32 timestamp);
|
||||
void meta_display_update_cursor (MetaDisplay *display);
|
||||
|
||||
void meta_display_check_threshold_reached (MetaDisplay *display,
|
||||
int x,
|
||||
@@ -400,10 +392,7 @@ void meta_display_queue_retheme_all_windows (MetaDisplay *display);
|
||||
void meta_display_retheme_all (void);
|
||||
|
||||
void meta_display_ping_window (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
MetaWindowPingFunc ping_timeout_func,
|
||||
void *user_data);
|
||||
guint32 serial);
|
||||
void meta_display_pong_for_serial (MetaDisplay *display,
|
||||
guint32 serial);
|
||||
|
||||
@@ -456,4 +445,6 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
|
||||
guint32 *timestamp);
|
||||
|
||||
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#include "compositor-private.h"
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
@@ -99,10 +101,7 @@
|
||||
typedef struct
|
||||
{
|
||||
MetaWindow *window;
|
||||
guint32 timestamp;
|
||||
MetaWindowPingFunc ping_reply_func;
|
||||
MetaWindowPingFunc ping_timeout_func;
|
||||
void *user_data;
|
||||
guint32 serial;
|
||||
guint ping_timeout_id;
|
||||
} MetaPingData;
|
||||
|
||||
@@ -149,6 +148,11 @@ static void update_window_grab_modifiers (MetaDisplay *display);
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static void meta_display_grab_window_touch (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
static void meta_display_ungrab_window_touch (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
static void
|
||||
meta_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
@@ -416,6 +420,28 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
|
||||
gnome_wm_keybindings = wm_keybindings;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_tracker_state_changed (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state,
|
||||
MetaDisplay *display)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
int event_mode;
|
||||
|
||||
if (state == META_SEQUENCE_ACCEPTED)
|
||||
event_mode = XIAcceptTouch;
|
||||
else if (state == META_SEQUENCE_REJECTED)
|
||||
event_mode = XIRejectTouch;
|
||||
else
|
||||
return;
|
||||
|
||||
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
clutter_x11_event_sequence_get_touch_detail (sequence),
|
||||
DefaultRootWindow (display->xdisplay), event_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_open:
|
||||
*
|
||||
@@ -518,9 +544,6 @@ meta_display_open (void)
|
||||
|
||||
the_display->groups_by_leader = NULL;
|
||||
|
||||
the_display->window_with_menu = NULL;
|
||||
the_display->window_menu = NULL;
|
||||
|
||||
the_display->screen = NULL;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
@@ -811,8 +834,16 @@ meta_display_open (void)
|
||||
|
||||
enable_compositor (the_display);
|
||||
|
||||
meta_screen_init_workspaces (screen);
|
||||
meta_screen_create_guard_window (screen);
|
||||
|
||||
/* Set up touch support */
|
||||
the_display->gesture_tracker = meta_gesture_tracker_new (0);
|
||||
g_signal_connect (the_display->gesture_tracker, "state-changed",
|
||||
G_CALLBACK (gesture_tracker_state_changed), the_display);
|
||||
meta_display_grab_window_touch (the_display,
|
||||
DefaultRootWindow (the_display->xdisplay));
|
||||
|
||||
/* We know that if mutter is running as a Wayland compositor,
|
||||
* we start out with no windows.
|
||||
*/
|
||||
@@ -982,6 +1013,10 @@ meta_display_close (MetaDisplay *display,
|
||||
|
||||
meta_display_remove_autoraise_callback (display);
|
||||
|
||||
meta_display_ungrab_window_touch (display,
|
||||
DefaultRootWindow (display->xdisplay));
|
||||
g_clear_object (&display->gesture_tracker);
|
||||
|
||||
if (display->focus_timeout_id)
|
||||
g_source_remove (display->focus_timeout_id);
|
||||
display->focus_timeout_id = 0;
|
||||
@@ -1003,6 +1038,7 @@ meta_display_close (MetaDisplay *display,
|
||||
* unregister windows
|
||||
*/
|
||||
g_hash_table_destroy (display->xids);
|
||||
g_hash_table_destroy (display->wayland_windows);
|
||||
|
||||
if (display->leader_window != None)
|
||||
XDestroyWindow (display->xdisplay, display->leader_window);
|
||||
@@ -1348,23 +1384,7 @@ window_raise_with_delay_callback (void *data)
|
||||
*/
|
||||
if (meta_stack_get_top (window->screen->stack) != window)
|
||||
{
|
||||
int x, y, root_x, root_y;
|
||||
Window root, child;
|
||||
MetaRectangle frame_rect;
|
||||
unsigned int mask;
|
||||
gboolean same_screen;
|
||||
gboolean point_in_window;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
same_screen = XQueryPointer (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
&root, &child,
|
||||
&root_x, &root_y, &x, &y, &mask);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
|
||||
if (same_screen && point_in_window)
|
||||
if (meta_window_has_pointer (window))
|
||||
meta_window_raise (window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
@@ -1372,7 +1392,7 @@ window_raise_with_delay_callback (void *data)
|
||||
window->desc);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1695,35 +1715,21 @@ meta_cursor_for_grab_op (MetaGrabOp op)
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
MetaGrabOp op,
|
||||
guint32 timestamp)
|
||||
meta_display_update_cursor (MetaDisplay *display)
|
||||
{
|
||||
/* Set root cursor */
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (display->screen);
|
||||
MetaCursor cursor = meta_cursor_for_grab_op (op);
|
||||
MetaCursorReference *cursor_ref;
|
||||
|
||||
cursor_ref = meta_cursor_reference_from_theme (cursor);
|
||||
meta_cursor_tracker_set_grab_cursor (tracker, cursor_ref);
|
||||
if (cursor_ref)
|
||||
meta_cursor_reference_unref (cursor_ref);
|
||||
|
||||
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
||||
display->grab_have_pointer = TRUE;
|
||||
meta_screen_set_cursor (display->screen, meta_cursor_for_grab_op (display->grab_op));
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
get_toplevel_transient_for (MetaWindow *window)
|
||||
get_first_freefloating_window (MetaWindow *window)
|
||||
{
|
||||
while (TRUE)
|
||||
{
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
if (parent == NULL)
|
||||
while (meta_window_is_attached_dialog (window))
|
||||
window = meta_window_get_transient_for (window);
|
||||
|
||||
/* Attached dialogs should always have a non-NULL transient-for */
|
||||
g_assert (window != NULL);
|
||||
|
||||
return window;
|
||||
window = parent;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1739,24 +1745,25 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
int root_x,
|
||||
int root_y)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWindow *grab_window = NULL;
|
||||
|
||||
g_assert (window != NULL);
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
|
||||
op, window ? window->desc : "none", button, pointer_already_grabbed,
|
||||
op, window->desc, button, pointer_already_grabbed,
|
||||
root_x, root_y);
|
||||
|
||||
if (display->grab_op != META_GRAB_OP_NONE)
|
||||
{
|
||||
if (window)
|
||||
meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n",
|
||||
op, window->desc, display->grab_op,
|
||||
display->grab_window ? display->grab_window->desc : "none");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (window &&
|
||||
(meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op)))
|
||||
if (meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op))
|
||||
{
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
@@ -1770,11 +1777,11 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
|
||||
grab_window = window;
|
||||
|
||||
/* If window is a modal dialog attached to its parent,
|
||||
* grab the parent instead for moving.
|
||||
/* If we're trying to move a window, move the first
|
||||
* non-attached dialog instead.
|
||||
*/
|
||||
if (meta_grab_op_is_moving (op))
|
||||
grab_window = get_toplevel_transient_for (window);
|
||||
grab_window = get_first_freefloating_window (window);
|
||||
|
||||
g_assert (grab_window != NULL);
|
||||
g_assert (op != META_GRAB_OP_NONE);
|
||||
@@ -1793,7 +1800,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
timestamp);
|
||||
XSync (display->xdisplay, False);
|
||||
|
||||
meta_display_set_grab_op_cursor (display, op, timestamp);
|
||||
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
||||
display->grab_have_pointer = TRUE;
|
||||
|
||||
if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op))
|
||||
{
|
||||
@@ -1808,7 +1816,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
|
||||
if (!display->grab_have_keyboard)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer\n");
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
display->grab_have_pointer = FALSE;
|
||||
@@ -1832,6 +1839,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
display->grab_resize_unmaximize = 0;
|
||||
display->grab_timestamp = timestamp;
|
||||
|
||||
meta_display_update_cursor (display);
|
||||
|
||||
if (display->grab_resize_timeout_id)
|
||||
{
|
||||
g_source_remove (display->grab_resize_timeout_id);
|
||||
@@ -1842,7 +1851,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
"Grab op %u on window %s successful\n",
|
||||
display->grab_op, window ? window->desc : "(null)");
|
||||
|
||||
meta_window_get_client_root_coords (display->grab_window,
|
||||
meta_window_get_frame_rect (display->grab_window,
|
||||
&display->grab_initial_window_pos);
|
||||
display->grab_anchor_window_pos = display->grab_initial_window_pos;
|
||||
|
||||
@@ -1861,8 +1870,6 @@ void
|
||||
meta_display_end_grab_op (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaCursorTracker *tracker;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
|
||||
|
||||
@@ -1903,15 +1910,14 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
meta_window_ungrab_all_keys (display->grab_window, timestamp);
|
||||
}
|
||||
|
||||
tracker = meta_cursor_tracker_get_for_screen (display->screen);
|
||||
meta_cursor_tracker_set_grab_cursor (tracker, NULL);
|
||||
|
||||
display->grab_timestamp = 0;
|
||||
display->grab_window = NULL;
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
|
||||
meta_display_update_cursor (display);
|
||||
|
||||
if (display->grab_resize_timeout_id)
|
||||
{
|
||||
g_source_remove (display->grab_resize_timeout_id);
|
||||
@@ -2011,10 +2017,7 @@ void
|
||||
meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
/* Grab Alt + button1 for moving window.
|
||||
@@ -2067,15 +2070,12 @@ void
|
||||
meta_display_ungrab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
gboolean debug;
|
||||
int i;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return;
|
||||
|
||||
@@ -2095,16 +2095,42 @@ meta_display_ungrab_window_buttons (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_display_grab_window_touch (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
|
||||
XIGrabModifiers mods = { XIAnyModifier, 0 };
|
||||
|
||||
XISetMask (mask.mask, XI_TouchBegin);
|
||||
XISetMask (mask.mask, XI_TouchUpdate);
|
||||
XISetMask (mask.mask, XI_TouchEnd);
|
||||
|
||||
XIGrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
xwindow, False, &mask, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_display_ungrab_window_touch (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
XIGrabModifiers mods = { XIAnyModifier, 0 };
|
||||
|
||||
XIUngrabTouchBegin (meta_backend_x11_get_xdisplay (backend),
|
||||
META_VIRTUAL_CORE_POINTER_ID, xwindow, 1, &mods);
|
||||
}
|
||||
|
||||
/* Grab buttons we only grab while unfocused in click-to-focus mode */
|
||||
#define MAX_FOCUS_BUTTON 4
|
||||
void
|
||||
meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
/* Grab button 1 for activating unfocused windows */
|
||||
@@ -2156,10 +2182,7 @@ void
|
||||
meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc);
|
||||
@@ -2331,15 +2354,16 @@ static gboolean
|
||||
meta_display_ping_timeout (gpointer data)
|
||||
{
|
||||
MetaPingData *ping_data = data;
|
||||
MetaDisplay *display = ping_data->window->display;
|
||||
MetaWindow *window = ping_data->window;
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
meta_window_set_alive (window, FALSE);
|
||||
|
||||
ping_data->ping_timeout_id = 0;
|
||||
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Ping %u on window %s timed out\n",
|
||||
ping_data->timestamp, ping_data->window->desc);
|
||||
|
||||
(* ping_data->ping_timeout_func) (ping_data->window, ping_data->timestamp, ping_data->user_data);
|
||||
ping_data->serial, ping_data->window->desc);
|
||||
|
||||
display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
|
||||
ping_data_free (ping_data);
|
||||
@@ -2353,11 +2377,6 @@ meta_display_ping_timeout (gpointer data)
|
||||
* @window: The #MetaWindow to send the ping to
|
||||
* @timestamp: The timestamp of the ping. Used for uniqueness.
|
||||
* Cannot be CurrentTime; use a real timestamp!
|
||||
* @ping_reply_func: The callback to call if we get a response.
|
||||
* @ping_timeout_func: The callback to call if we don't get a response.
|
||||
* @user_data: Arbitrary data that will be passed to the callback
|
||||
* function. (In practice it's often a pointer to
|
||||
* the window.)
|
||||
*
|
||||
* Sends a ping request to a window. The window must respond to
|
||||
* the request within a certain amount of time. If it does, we
|
||||
@@ -2370,34 +2389,23 @@ meta_display_ping_timeout (gpointer data)
|
||||
*/
|
||||
void
|
||||
meta_display_ping_window (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
MetaWindowPingFunc ping_timeout_func,
|
||||
gpointer user_data)
|
||||
guint32 serial)
|
||||
{
|
||||
MetaDisplay *display = window->display;
|
||||
MetaPingData *ping_data;
|
||||
|
||||
if (timestamp == CurrentTime)
|
||||
if (serial == 0)
|
||||
{
|
||||
meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
|
||||
meta_warning ("Tried to ping a window with a bad serial! Not allowed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window->can_ping)
|
||||
{
|
||||
if (ping_reply_func)
|
||||
(* ping_reply_func) (window, timestamp, user_data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ping_data = g_new (MetaPingData, 1);
|
||||
ping_data->window = window;
|
||||
ping_data->timestamp = timestamp;
|
||||
ping_data->ping_reply_func = ping_reply_func;
|
||||
ping_data->ping_timeout_func = ping_timeout_func;
|
||||
ping_data->user_data = user_data;
|
||||
ping_data->serial = serial;
|
||||
ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
|
||||
meta_display_ping_timeout,
|
||||
ping_data);
|
||||
@@ -2406,10 +2414,10 @@ meta_display_ping_window (MetaWindow *window,
|
||||
display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
|
||||
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Sending ping with timestamp %u to window %s\n",
|
||||
timestamp, window->desc);
|
||||
"Sending ping with serial %u to window %s\n",
|
||||
serial, window->desc);
|
||||
|
||||
META_WINDOW_GET_CLASS (window)->ping (window, timestamp);
|
||||
META_WINDOW_GET_CLASS (window)->ping (window, serial);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2433,11 +2441,11 @@ meta_display_pong_for_serial (MetaDisplay *display,
|
||||
{
|
||||
MetaPingData *ping_data = tmp->data;
|
||||
|
||||
if (serial == ping_data->timestamp)
|
||||
if (serial == ping_data->serial)
|
||||
{
|
||||
meta_topic (META_DEBUG_PING,
|
||||
"Matching ping found for pong %u\n",
|
||||
ping_data->timestamp);
|
||||
ping_data->serial);
|
||||
|
||||
/* Remove the ping data from the list */
|
||||
display->pending_pings = g_slist_remove (display->pending_pings,
|
||||
@@ -2450,13 +2458,8 @@ meta_display_pong_for_serial (MetaDisplay *display,
|
||||
ping_data->ping_timeout_id = 0;
|
||||
}
|
||||
|
||||
/* Call callback */
|
||||
(* ping_data->ping_reply_func) (ping_data->window,
|
||||
ping_data->timestamp,
|
||||
ping_data->user_data);
|
||||
|
||||
meta_window_set_alive (ping_data->window, TRUE);
|
||||
ping_data_free (ping_data);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2576,21 +2579,19 @@ mru_cmp (gconstpointer a,
|
||||
* meta_display_get_tab_list:
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @screen: a #MetaScreen
|
||||
* @workspace: (allow-none): origin workspace
|
||||
* @workspace: (nullable): origin workspace
|
||||
*
|
||||
* Determine the list of windows that should be displayed for Alt-TAB
|
||||
* functionality. The windows are returned in most recently used order.
|
||||
* If @workspace is not %NULL, the list only conains windows that are on
|
||||
* @workspace or have the demands-attention hint set; otherwise it contains
|
||||
* all windows on @screen.
|
||||
* all windows.
|
||||
*
|
||||
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||
*/
|
||||
GList*
|
||||
meta_display_get_tab_list (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
GList *tab_list = NULL;
|
||||
@@ -2646,7 +2647,7 @@ meta_display_get_tab_list (MetaDisplay *display,
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @workspace: origin workspace
|
||||
* @window: (allow-none): starting window
|
||||
* @window: (nullable): starting window
|
||||
* @backward: If %TRUE, look for the previous window.
|
||||
*
|
||||
* Determine the next window that should be displayed for Alt-TAB
|
||||
@@ -2665,7 +2666,7 @@ meta_display_get_tab_next (MetaDisplay *display,
|
||||
gboolean skip;
|
||||
GList *tab_list;
|
||||
MetaWindow *ret;
|
||||
tab_list = meta_display_get_tab_list (display, type, NULL, workspace);
|
||||
tab_list = meta_display_get_tab_list (display, type, workspace);
|
||||
|
||||
if (tab_list == NULL)
|
||||
return NULL;
|
||||
@@ -3220,3 +3221,9 @@ meta_display_create_x_cursor (MetaDisplay *display,
|
||||
{
|
||||
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
|
||||
}
|
||||
|
||||
MetaGestureTracker *
|
||||
meta_display_get_gesture_tracker (MetaDisplay *display)
|
||||
{
|
||||
return display->gesture_tracker;
|
||||
}
|
||||
|
||||
@@ -1134,13 +1134,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
initialize_grab_edge_resistance_data (display);
|
||||
}
|
||||
|
||||
/* Note that old_[xy] and new_[xy] are with respect to inner positions of
|
||||
* the window.
|
||||
*/
|
||||
void
|
||||
meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
GSourceFunc timeout_func,
|
||||
@@ -1153,8 +1148,8 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
meta_window_get_frame_rect (window, &old_outer);
|
||||
|
||||
proposed_outer = old_outer;
|
||||
proposed_outer.x += (*new_x - old_x);
|
||||
proposed_outer.y += (*new_y - old_y);
|
||||
proposed_outer.x = *new_x;
|
||||
proposed_outer.y = *new_y;
|
||||
new_outer = proposed_outer;
|
||||
|
||||
window->display->grab_last_user_action_was_snap = snap;
|
||||
@@ -1205,26 +1200,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
else
|
||||
smaller_y_change = bottom_change;
|
||||
|
||||
*new_x = old_x + smaller_x_change +
|
||||
*new_x = old_outer.x + smaller_x_change +
|
||||
(BOX_LEFT (*reference) - BOX_LEFT (old_outer));
|
||||
*new_y = old_y + smaller_y_change +
|
||||
*new_y = old_outer.y + smaller_y_change +
|
||||
(BOX_TOP (*reference) - BOX_TOP (old_outer));
|
||||
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"outer x & y move-to coordinate changed from %d,%d to %d,%d\n",
|
||||
proposed_outer.x, proposed_outer.y,
|
||||
old_outer.x + (*new_x - old_x),
|
||||
old_outer.y + (*new_y - old_y));
|
||||
*new_x, *new_y);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note that old_(width|height) and new_(width|height) are with respect to
|
||||
* sizes of the inner window.
|
||||
*/
|
||||
void
|
||||
meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
@@ -1237,8 +1226,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_frame_rect (window, &old_outer);
|
||||
proposed_outer_width = old_outer.width + (*new_width - old_width);
|
||||
proposed_outer_height = old_outer.height + (*new_height - old_height);
|
||||
proposed_outer_width = *new_width;
|
||||
proposed_outer_height = *new_height;
|
||||
meta_rectangle_resize_with_gravity (&old_outer,
|
||||
&new_outer,
|
||||
gravity,
|
||||
@@ -1256,8 +1245,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
is_keyboard_op,
|
||||
is_resize))
|
||||
{
|
||||
*new_width = old_width + (new_outer.width - old_outer.width);
|
||||
*new_height = old_height + (new_outer.height - old_outer.height);
|
||||
*new_width = new_outer.width;
|
||||
*new_height = new_outer.height;
|
||||
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"outer width & height got changed from %d,%d to %d,%d\n",
|
||||
|
||||
@@ -25,16 +25,12 @@
|
||||
#include "window-private.h"
|
||||
|
||||
void meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op);
|
||||
void meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
|
||||
2050
src/core/events.c
2050
src/core/events.c
File diff suppressed because it is too large
Load Diff
@@ -29,4 +29,3 @@ void meta_display_init_events (MetaDisplay *display);
|
||||
void meta_display_free_events (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -109,6 +109,19 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
XChangeWindowAttributes (window->display->xdisplay,
|
||||
frame->xwindow, CWEventMask, &attrs);
|
||||
|
||||
{
|
||||
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_Motion);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
|
||||
XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
|
||||
}
|
||||
|
||||
meta_display_register_x_window (window->display, &frame->xwindow, window);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
@@ -121,9 +134,6 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
"Incrementing unmaps_pending on %s for reparent\n", window->desc);
|
||||
window->unmaps_pending += 1;
|
||||
}
|
||||
/* window was reparented to this position */
|
||||
window->rect.x = 0;
|
||||
window->rect.y = 0;
|
||||
|
||||
stack_window.x11.xwindow = window->xwindow;
|
||||
meta_stack_tracker_record_remove (window->screen->stack_tracker,
|
||||
@@ -132,8 +142,8 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
XReparentWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
frame->xwindow,
|
||||
window->rect.x,
|
||||
window->rect.y);
|
||||
frame->child_x,
|
||||
frame->child_y);
|
||||
/* FIXME handle this error */
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
@@ -151,10 +161,15 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
window->frame->xwindow,
|
||||
window->title);
|
||||
|
||||
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
|
||||
|
||||
/* Since the backend takes keygrabs on another connection, make sure
|
||||
* to sync the GTK+ connection to ensure that the frame window has
|
||||
* been created on the server at this point. */
|
||||
XSync (window->display->xdisplay, False);
|
||||
|
||||
/* Move keybindings to frame instead of window */
|
||||
meta_window_grab_keys (window);
|
||||
|
||||
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -197,7 +212,7 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
XReparentWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
window->screen->xroot,
|
||||
/* Using anything other than meta_window_get_position()
|
||||
/* Using anything other than client root window coordinates
|
||||
* coordinates here means we'll need to ensure a configure
|
||||
* notify event is sent; see bug 399552.
|
||||
*/
|
||||
@@ -245,6 +260,10 @@ meta_frame_get_flags (MetaFrame *frame)
|
||||
{
|
||||
flags |= META_FRAME_ALLOWS_MENU;
|
||||
|
||||
if (meta_prefs_get_show_fallback_app_menu () &&
|
||||
frame->window->gtk_app_menu_object_path)
|
||||
flags |= META_FRAME_ALLOWS_APPMENU;
|
||||
|
||||
if (frame->window->has_close_func)
|
||||
flags |= META_FRAME_ALLOWS_DELETE;
|
||||
|
||||
|
||||
83
src/core/gesture-tracker-private.h
Normal file
83
src/core/gesture-tracker-private.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file gesture-tracker-private.h Manages gestures on windows/desktop
|
||||
*
|
||||
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
|
||||
* based on the outcome of those.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_GESTURE_TRACKER_PRIVATE_H
|
||||
#define META_GESTURE_TRACKER_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
|
||||
#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
|
||||
#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
|
||||
#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER))
|
||||
#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER))
|
||||
#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
|
||||
|
||||
typedef struct _MetaGestureTracker MetaGestureTracker;
|
||||
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
|
||||
|
||||
typedef enum {
|
||||
META_SEQUENCE_NONE,
|
||||
META_SEQUENCE_ACCEPTED,
|
||||
META_SEQUENCE_REJECTED,
|
||||
META_SEQUENCE_PENDING_END
|
||||
} MetaSequenceState;
|
||||
|
||||
struct _MetaGestureTracker
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaGestureTrackerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* state_changed) (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
};
|
||||
|
||||
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaGestureTracker * meta_gesture_tracker_new (guint autodeny_timeout);
|
||||
|
||||
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence);
|
||||
gboolean meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#endif /* META_GESTURE_TRACKER_PRIVATE_H */
|
||||
555
src/core/gesture-tracker.c
Normal file
555
src/core/gesture-tracker.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gesture-tracker-private.h"
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#define DISTANCE_THRESHOLD 30
|
||||
|
||||
typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate;
|
||||
typedef struct _GestureActionData GestureActionData;
|
||||
typedef struct _MetaSequenceInfo MetaSequenceInfo;
|
||||
|
||||
struct _MetaSequenceInfo
|
||||
{
|
||||
MetaGestureTracker *tracker;
|
||||
ClutterEventSequence *sequence;
|
||||
MetaSequenceState state;
|
||||
guint autodeny_timeout_id;
|
||||
gfloat start_x;
|
||||
gfloat start_y;
|
||||
};
|
||||
|
||||
struct _GestureActionData
|
||||
{
|
||||
ClutterGestureAction *gesture;
|
||||
MetaSequenceState state;
|
||||
guint gesture_begin_id;
|
||||
guint gesture_end_id;
|
||||
guint gesture_cancel_id;
|
||||
};
|
||||
|
||||
struct _MetaGestureTrackerPrivate
|
||||
{
|
||||
GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */
|
||||
|
||||
MetaSequenceState stage_state;
|
||||
GArray *stage_gestures; /* Array of GestureActionData */
|
||||
GList *listeners; /* List of ClutterGestureAction */
|
||||
guint autodeny_timeout;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_AUTODENY_TIMEOUT = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
#define DEFAULT_AUTODENY_TIMEOUT 150
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_finalize (GObject *object)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
g_hash_table_destroy (priv->sequences);
|
||||
g_array_free (priv->stage_gestures, TRUE);
|
||||
g_list_free (priv->listeners);
|
||||
|
||||
G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTODENY_TIMEOUT:
|
||||
priv->autodeny_timeout = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTODENY_TIMEOUT:
|
||||
g_value_set_uint (value, priv->autodeny_timeout);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_gesture_tracker_finalize;
|
||||
object_class->set_property = meta_gesture_tracker_set_property;
|
||||
object_class->get_property = meta_gesture_tracker_get_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_AUTODENY_TIMEOUT,
|
||||
g_param_spec_uint ("autodeny-timeout",
|
||||
"Auto-deny timeout",
|
||||
"Auto-deny timeout",
|
||||
0, G_MAXUINT, 0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new ("state-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
autodeny_sequence (gpointer user_data)
|
||||
{
|
||||
MetaSequenceInfo *info = user_data;
|
||||
|
||||
/* Deny the sequence automatically after the given timeout */
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
|
||||
info->autodeny_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static MetaSequenceInfo *
|
||||
meta_sequence_info_new (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
guint ms;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
ms = (priv->autodeny_timeout) ?
|
||||
priv->autodeny_timeout : DEFAULT_AUTODENY_TIMEOUT;
|
||||
|
||||
info = g_slice_new0 (MetaSequenceInfo);
|
||||
info->tracker = tracker;
|
||||
info->sequence = event->touch.sequence;
|
||||
info->state = META_SEQUENCE_NONE;
|
||||
info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info);
|
||||
|
||||
clutter_event_get_coords (event, &info->start_x, &info->start_y);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sequence_info_free (MetaSequenceInfo *info)
|
||||
{
|
||||
if (info->autodeny_timeout_id)
|
||||
g_source_remove (info->autodeny_timeout_id);
|
||||
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
g_slice_free (MetaSequenceInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
state_is_applicable (MetaSequenceState prev_state,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
if (prev_state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Don't allow reverting to none */
|
||||
if (state == META_SEQUENCE_NONE)
|
||||
return FALSE;
|
||||
|
||||
/* PENDING_END state is final */
|
||||
if (prev_state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Sequences must be accepted/denied before PENDING_END */
|
||||
if (prev_state == META_SEQUENCE_NONE &&
|
||||
state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Make sequences stick to their accepted/denied state */
|
||||
if (state != META_SEQUENCE_PENDING_END &&
|
||||
prev_state != META_SEQUENCE_NONE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_gesture_tracker_set_state (MetaGestureTracker *tracker,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
ClutterEventSequence *sequence;
|
||||
GHashTableIter iter;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (priv->stage_state != state &&
|
||||
!state_is_applicable (priv->stage_state, state))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->sequences);
|
||||
priv->stage_state = state;
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL))
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence, state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gesture_begin_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (!g_list_find (priv->listeners, gesture) &&
|
||||
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED))
|
||||
priv->listeners = g_list_prepend (priv->listeners, gesture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_end_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->listeners = g_list_remove (priv->listeners, gesture);
|
||||
|
||||
if (!priv->listeners)
|
||||
meta_gesture_tracker_untrack_stage (tracker);
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_cancel_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (g_list_find (priv->listeners, gesture))
|
||||
{
|
||||
priv->listeners = g_list_remove (priv->listeners, gesture);
|
||||
|
||||
if (!priv->listeners)
|
||||
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cancel_and_unref_gesture_cb (ClutterGestureAction *action)
|
||||
{
|
||||
clutter_gesture_action_cancel (action);
|
||||
g_object_unref (action);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_gesture_data (GestureActionData *data)
|
||||
{
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_begin_id);
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_end_id);
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_cancel_id);
|
||||
|
||||
/* Defer cancellation to an idle, as it may happen within event handling */
|
||||
g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_init (MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->sequences = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_sequence_info_free);
|
||||
priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData));
|
||||
g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data);
|
||||
}
|
||||
|
||||
MetaGestureTracker *
|
||||
meta_gesture_tracker_new (guint autodeny_timeout)
|
||||
{
|
||||
return g_object_new (META_TYPE_GESTURE_TRACKER,
|
||||
"autodeny-timeout", autodeny_timeout,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_track_stage (MetaGestureTracker *tracker,
|
||||
ClutterActor *stage)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
GList *actions, *l;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
actions = clutter_actor_get_actions (stage);
|
||||
|
||||
for (l = actions; l; l = l->next)
|
||||
{
|
||||
GestureActionData data;
|
||||
|
||||
if (!CLUTTER_IS_GESTURE_ACTION (l->data))
|
||||
continue;
|
||||
|
||||
data.gesture = g_object_ref (l->data);
|
||||
data.state = META_SEQUENCE_NONE;
|
||||
data.gesture_begin_id =
|
||||
g_signal_connect (data.gesture, "gesture-begin",
|
||||
G_CALLBACK (gesture_begin_cb), tracker);
|
||||
data.gesture_end_id =
|
||||
g_signal_connect (data.gesture, "gesture-end",
|
||||
G_CALLBACK (gesture_end_cb), tracker);
|
||||
data.gesture_cancel_id =
|
||||
g_signal_connect (data.gesture, "gesture-cancel",
|
||||
G_CALLBACK (gesture_cancel_cb), tracker);
|
||||
g_array_append_val (priv->stage_gestures, data);
|
||||
}
|
||||
|
||||
g_list_free (actions);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->stage_state = META_SEQUENCE_NONE;
|
||||
|
||||
g_hash_table_remove_all (priv->sequences);
|
||||
|
||||
if (priv->stage_gestures->len > 0)
|
||||
g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len);
|
||||
|
||||
g_list_free (priv->listeners);
|
||||
priv->listeners = NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
ClutterEventSequence *sequence;
|
||||
MetaSequenceInfo *info;
|
||||
ClutterActor *stage;
|
||||
gfloat x, y;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
if (!sequence)
|
||||
return FALSE;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
stage = CLUTTER_ACTOR (clutter_event_get_stage (event));
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
if (g_hash_table_size (priv->sequences) == 0)
|
||||
meta_gesture_tracker_track_stage (tracker, stage);
|
||||
|
||||
info = meta_sequence_info_new (tracker, event);
|
||||
g_hash_table_insert (priv->sequences, sequence, info);
|
||||
|
||||
if (priv->stage_gestures->len == 0)
|
||||
{
|
||||
/* If no gestures are attached, reject the sequence right away */
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
}
|
||||
else if (priv->stage_state != META_SEQUENCE_NONE)
|
||||
{
|
||||
/* Make the sequence state match the general state */
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
priv->stage_state);
|
||||
}
|
||||
break;
|
||||
case CLUTTER_TOUCH_END:
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
/* If nothing was done yet about the sequence, reject it so X11
|
||||
* clients may see it
|
||||
*/
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
|
||||
g_hash_table_remove (priv->sequences, sequence);
|
||||
|
||||
if (g_hash_table_size (priv->sequences) == 0)
|
||||
meta_gesture_tracker_untrack_stage (tracker);
|
||||
break;
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
if (info->state == META_SEQUENCE_NONE &&
|
||||
(ABS (info->start_x - x) > DISTANCE_THRESHOLD ||
|
||||
ABS (info->start_y - y) > DISTANCE_THRESHOLD))
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
else if (state == info->state)
|
||||
return TRUE;
|
||||
|
||||
if (!state_is_applicable (info->state, state))
|
||||
return FALSE;
|
||||
|
||||
/* Unset autodeny timeout */
|
||||
if (info->autodeny_timeout_id)
|
||||
{
|
||||
g_source_remove (info->autodeny_timeout_id);
|
||||
info->autodeny_timeout_id = 0;
|
||||
}
|
||||
|
||||
info->state = state;
|
||||
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
|
||||
|
||||
/* If the sequence was denied, set immediately to PENDING_END after emission */
|
||||
if (state == META_SEQUENCE_REJECTED)
|
||||
{
|
||||
info->state = META_SEQUENCE_PENDING_END;
|
||||
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MetaSequenceState
|
||||
meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END);
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return META_SEQUENCE_PENDING_END;
|
||||
|
||||
return info->state;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
MetaSequenceState state;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
if (!sequence)
|
||||
return FALSE;
|
||||
|
||||
state = meta_gesture_tracker_get_sequence_state (tracker, sequence);
|
||||
|
||||
return (event->type != CLUTTER_TOUCH_END &&
|
||||
(state == META_SEQUENCE_REJECTED || state == META_SEQUENCE_PENDING_END));
|
||||
}
|
||||
@@ -100,9 +100,9 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
gboolean meta_keybindings_process_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event);
|
||||
const ClutterEvent *event);
|
||||
void meta_display_process_mapping_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
|
||||
@@ -57,7 +57,11 @@
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "x11/window-x11.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#endif
|
||||
|
||||
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
|
||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
||||
@@ -1081,7 +1085,7 @@ typedef struct
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Window xwindow;
|
||||
gboolean binding_per_window;
|
||||
gboolean only_per_window;
|
||||
gboolean grab;
|
||||
} ChangeKeygrabData;
|
||||
|
||||
@@ -1092,29 +1096,31 @@ change_keygrab_foreach (gpointer key,
|
||||
{
|
||||
ChangeKeygrabData *data = user_data;
|
||||
MetaKeyBinding *binding = value;
|
||||
gboolean binding_is_per_window = (binding->flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
|
||||
if (data->only_per_window != binding_is_per_window)
|
||||
return;
|
||||
|
||||
if (binding->keycode == 0)
|
||||
return;
|
||||
|
||||
if (!!data->binding_per_window ==
|
||||
!!(binding->flags & META_KEY_BINDING_PER_WINDOW) &&
|
||||
binding->keycode != 0)
|
||||
{
|
||||
meta_change_keygrab (data->display, data->xwindow, data->grab,
|
||||
binding->keysym,
|
||||
binding->keycode,
|
||||
binding->mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
change_binding_keygrabs (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
gboolean binding_per_window,
|
||||
gboolean only_per_window,
|
||||
gboolean grab)
|
||||
{
|
||||
ChangeKeygrabData data;
|
||||
|
||||
data.display = display;
|
||||
data.xwindow = xwindow;
|
||||
data.binding_per_window = binding_per_window;
|
||||
data.only_per_window = only_per_window;
|
||||
data.grab = grab;
|
||||
|
||||
g_hash_table_foreach (display->key_bindings, change_keygrab_foreach, &data);
|
||||
@@ -1218,7 +1224,7 @@ meta_window_grab_keys (MetaWindow *window)
|
||||
}
|
||||
|
||||
meta_window_change_keygrabs (window,
|
||||
meta_window_get_toplevel_xwindow (window),
|
||||
meta_window_x11_get_toplevel_xwindow (window),
|
||||
TRUE);
|
||||
|
||||
window->keys_grabbed = TRUE;
|
||||
@@ -1259,6 +1265,7 @@ guint
|
||||
meta_display_grab_accelerator (MetaDisplay *display,
|
||||
const char *accelerator)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaKeyBinding *binding;
|
||||
MetaKeyGrab *grab;
|
||||
guint keysym = 0;
|
||||
@@ -1284,6 +1291,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
|
||||
if (display_get_keybinding (display, keycode, mask))
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
meta_change_keygrab (display, display->screen->xroot, TRUE, keysym, keycode, mask);
|
||||
|
||||
grab = g_new0 (MetaKeyGrab, 1);
|
||||
@@ -1314,6 +1322,7 @@ gboolean
|
||||
meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
guint action)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaKeyBinding *binding;
|
||||
MetaKeyGrab *grab;
|
||||
char *key;
|
||||
@@ -1335,6 +1344,7 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
{
|
||||
guint32 index_key;
|
||||
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
meta_change_keygrab (display, display->screen->xroot, FALSE,
|
||||
binding->keysym,
|
||||
binding->keycode,
|
||||
@@ -1428,7 +1438,7 @@ meta_window_grab_all_keys (MetaWindow *window,
|
||||
window->desc);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
grabwindow = meta_window_get_toplevel_xwindow (window);
|
||||
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Grabbing all keys on window %s\n", window->desc);
|
||||
@@ -1594,11 +1604,12 @@ process_overlay_key (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay;
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return FALSE;
|
||||
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
else
|
||||
xdisplay = NULL;
|
||||
|
||||
if (display->overlay_key_only_pressed)
|
||||
{
|
||||
@@ -1624,6 +1635,8 @@ process_overlay_key (MetaDisplay *display,
|
||||
* binding, we unfreeze the keyboard but keep the grab
|
||||
* (this is important for something like cycling
|
||||
* windows */
|
||||
|
||||
if (xdisplay)
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
@@ -1632,9 +1645,12 @@ process_overlay_key (MetaDisplay *display,
|
||||
{
|
||||
/* Replay the event so it gets delivered to our
|
||||
* per-window key bindings or to the application */
|
||||
if (xdisplay)
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIReplayDevice, event->time);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (event->type == CLUTTER_KEY_RELEASE)
|
||||
@@ -1645,6 +1661,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
|
||||
/* We want to unfreeze events, but keep the grab so that if the user
|
||||
* starts typing into the overlay we get all the keys */
|
||||
if (xdisplay)
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
@@ -1671,6 +1688,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
|
||||
*/
|
||||
if (xdisplay)
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
@@ -1684,6 +1702,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
display->overlay_key_only_pressed = TRUE;
|
||||
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
|
||||
* on the next event if it's not the release of the overlay key */
|
||||
if (xdisplay)
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XISyncDevice, event->time);
|
||||
@@ -1725,22 +1744,8 @@ process_iso_next_group (MetaDisplay *display,
|
||||
return activate;
|
||||
}
|
||||
|
||||
/* Handle a key event. May be called recursively: some key events cause
|
||||
* grabs to be ended and then need to be processed again in their own
|
||||
* right. This cannot cause infinite recursion because we never call
|
||||
* ourselves when there wasn't a grab, and we always clear the grab
|
||||
* first; the invariant is enforced using an assertion. See #112560.
|
||||
*
|
||||
* The return value is whether we handled the key event.
|
||||
*
|
||||
* FIXME: We need to prove there are no race conditions here.
|
||||
* FIXME: Does it correctly handle alt-Tab being followed by another
|
||||
* grabbing keypress without letting go of alt?
|
||||
* FIXME: An iterative solution would probably be simpler to understand
|
||||
* (and help us solve the other fixmes).
|
||||
*/
|
||||
gboolean
|
||||
meta_display_process_key_event (MetaDisplay *display,
|
||||
static gboolean
|
||||
process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
@@ -1840,6 +1845,41 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
return process_event (display, screen, window, event);
|
||||
}
|
||||
|
||||
/* Handle a key event. May be called recursively: some key events cause
|
||||
* grabs to be ended and then need to be processed again in their own
|
||||
* right. This cannot cause infinite recursion because we never call
|
||||
* ourselves when there wasn't a grab, and we always clear the grab
|
||||
* first; the invariant is enforced using an assertion. See #112560.
|
||||
*
|
||||
* The return value is whether we handled the key event.
|
||||
*
|
||||
* FIXME: We need to prove there are no race conditions here.
|
||||
* FIXME: Does it correctly handle alt-Tab being followed by another
|
||||
* grabbing keypress without letting go of alt?
|
||||
* FIXME: An iterative solution would probably be simpler to understand
|
||||
* (and help us solve the other fixmes).
|
||||
*/
|
||||
gboolean
|
||||
meta_keybindings_process_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
return FALSE;
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
return process_key_event (display, window, (ClutterKeyEvent *) event);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_mouse_move_resize_grab (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@@ -1870,7 +1910,7 @@ process_mouse_move_resize_grab (MetaDisplay *display,
|
||||
else if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else
|
||||
meta_window_move_resize (display->grab_window,
|
||||
meta_window_move_resize_frame (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
@@ -1891,6 +1931,7 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
gboolean handled;
|
||||
MetaRectangle frame_rect;
|
||||
int x, y;
|
||||
int incr;
|
||||
gboolean smart_snap;
|
||||
@@ -1905,7 +1946,9 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
if (is_modifier (event->keyval))
|
||||
return TRUE;
|
||||
|
||||
meta_window_get_position (window, &x, &y);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
x = frame_rect.x;
|
||||
y = frame_rect.y;
|
||||
|
||||
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
|
||||
|
||||
@@ -1929,7 +1972,7 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
if (window->shaken_loose)
|
||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
||||
else
|
||||
meta_window_move_resize (display->grab_window,
|
||||
meta_window_move_resize_frame (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
@@ -1980,23 +2023,18 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
|
||||
if (handled)
|
||||
{
|
||||
MetaRectangle old_rect;
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Computed new window location %d,%d due to keypress\n",
|
||||
x, y);
|
||||
|
||||
meta_window_get_client_root_coords (window, &old_rect);
|
||||
|
||||
meta_window_edge_resistance_for_move (window,
|
||||
old_rect.x,
|
||||
old_rect.y,
|
||||
&x,
|
||||
&y,
|
||||
NULL,
|
||||
smart_snap,
|
||||
TRUE);
|
||||
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
meta_window_move_frame (window, TRUE, x, y);
|
||||
meta_window_update_keyboard_move (window);
|
||||
}
|
||||
|
||||
@@ -2130,6 +2168,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event)
|
||||
{
|
||||
MetaRectangle frame_rect;
|
||||
gboolean handled;
|
||||
int height_inc;
|
||||
int width_inc;
|
||||
@@ -2150,7 +2189,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
if (event->keyval == CLUTTER_KEY_Escape)
|
||||
{
|
||||
/* End resize and restore to original state. */
|
||||
meta_window_move_resize (display->grab_window,
|
||||
meta_window_move_resize_frame (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
@@ -2166,6 +2205,10 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
width = window->rect.width;
|
||||
height = window->rect.height;
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
width = frame_rect.width;
|
||||
height = frame_rect.height;
|
||||
|
||||
gravity = meta_resize_gravity_from_grab_op (display->grab_op);
|
||||
|
||||
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
|
||||
@@ -2323,18 +2366,13 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
|
||||
if (handled)
|
||||
{
|
||||
MetaRectangle old_rect;
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Computed new window size due to keypress: "
|
||||
"%dx%d, gravity %s\n",
|
||||
width, height, meta_gravity_to_string (gravity));
|
||||
|
||||
old_rect = window->rect; /* Don't actually care about x,y */
|
||||
|
||||
/* Do any edge resistance/snapping */
|
||||
meta_window_edge_resistance_for_resize (window,
|
||||
old_rect.width,
|
||||
old_rect.height,
|
||||
&width,
|
||||
&height,
|
||||
gravity,
|
||||
@@ -2342,11 +2380,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
smart_snap,
|
||||
TRUE);
|
||||
|
||||
/* We don't need to update unless the specified width and height
|
||||
* are actually different from what we had before.
|
||||
*/
|
||||
if (window->rect.width != width || window->rect.height != height)
|
||||
meta_window_resize_with_gravity (window,
|
||||
meta_window_resize_frame_with_gravity (window,
|
||||
TRUE,
|
||||
width,
|
||||
height,
|
||||
@@ -2455,45 +2489,57 @@ handle_always_on_top (MetaDisplay *display,
|
||||
meta_window_unmake_above (window);
|
||||
}
|
||||
|
||||
/* Move a window to a corner; to_bottom/to_right are FALSE for the
|
||||
* top or left edge, or TRUE for the bottom/right edge. xchange/ychange
|
||||
* are FALSE if that dimension is not to be changed, TRUE otherwise.
|
||||
* Together they describe which of the four corners, or four sides,
|
||||
* is desired.
|
||||
*/
|
||||
static void
|
||||
handle_move_to_corner_backend (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
gboolean xchange,
|
||||
gboolean ychange,
|
||||
gboolean to_right,
|
||||
gboolean to_bottom,
|
||||
gpointer dummy)
|
||||
int gravity)
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle frame_rect;
|
||||
int orig_x, orig_y;
|
||||
int new_x, new_y;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
if (xchange) {
|
||||
new_x = work_area.x + (to_right ?
|
||||
work_area.width - frame_rect.width :
|
||||
0);
|
||||
} else {
|
||||
new_x = orig_x;
|
||||
switch (gravity)
|
||||
{
|
||||
case NorthWestGravity:
|
||||
case WestGravity:
|
||||
case SouthWestGravity:
|
||||
new_x = work_area.x;
|
||||
break;
|
||||
case NorthGravity:
|
||||
case SouthGravity:
|
||||
new_x = frame_rect.x;
|
||||
break;
|
||||
case NorthEastGravity:
|
||||
case EastGravity:
|
||||
case SouthEastGravity:
|
||||
new_x = work_area.x + work_area.width - frame_rect.width;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (ychange) {
|
||||
new_y = work_area.y + (to_bottom ?
|
||||
work_area.height - frame_rect.height :
|
||||
0);
|
||||
} else {
|
||||
new_y = orig_y;
|
||||
switch (gravity)
|
||||
{
|
||||
case NorthWestGravity:
|
||||
case NorthGravity:
|
||||
case NorthEastGravity:
|
||||
new_y = work_area.y;
|
||||
break;
|
||||
case WestGravity:
|
||||
case EastGravity:
|
||||
new_y = frame_rect.y;
|
||||
break;
|
||||
case SouthWestGravity:
|
||||
case SouthGravity:
|
||||
case SouthEastGravity:
|
||||
new_y = work_area.y + work_area.height - frame_rect.height;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
meta_window_move_frame (window,
|
||||
@@ -2510,7 +2556,7 @@ handle_move_to_corner_nw (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, NorthWestGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2521,7 +2567,7 @@ handle_move_to_corner_ne (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, NorthEastGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2532,7 +2578,7 @@ handle_move_to_corner_sw (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, SouthWestGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2543,7 +2589,7 @@ handle_move_to_corner_se (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, SouthEastGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2554,7 +2600,7 @@ handle_move_to_side_n (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, NorthGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2565,7 +2611,7 @@ handle_move_to_side_s (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, SouthGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2576,7 +2622,7 @@ handle_move_to_side_e (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, EastGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2587,7 +2633,7 @@ handle_move_to_side_w (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE, dummy);
|
||||
handle_move_to_corner_backend (display, screen, window, WestGravity);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2600,22 +2646,14 @@ handle_move_to_center (MetaDisplay *display,
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle frame_rect;
|
||||
int orig_x, orig_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
frame_width = (window->frame ? window->frame->child_x : 0);
|
||||
frame_height = (window->frame ? window->frame->child_y : 0);
|
||||
|
||||
meta_window_move_resize (window,
|
||||
meta_window_move_frame (window,
|
||||
TRUE,
|
||||
work_area.x + (work_area.width +frame_width -frame_rect.width )/2,
|
||||
work_area.y + (work_area.height+frame_height-frame_rect.height)/2,
|
||||
window->rect.width,
|
||||
window->rect.height);
|
||||
work_area.x + (work_area.width - frame_rect.width ) / 2,
|
||||
work_area.y + (work_area.height - frame_rect.height) / 2);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2700,17 +2738,18 @@ handle_activate_window_menu (MetaDisplay *display,
|
||||
if (display->focus_window)
|
||||
{
|
||||
int x, y;
|
||||
MetaRectangle frame_rect;
|
||||
cairo_rectangle_int_t child_rect;
|
||||
|
||||
meta_window_get_position (display->focus_window,
|
||||
&x, &y);
|
||||
meta_window_get_frame_rect (display->focus_window, &frame_rect);
|
||||
meta_window_get_client_area_rect (display->focus_window, &child_rect);
|
||||
|
||||
x = frame_rect.x + child_rect.x;
|
||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||
x += display->focus_window->rect.width;
|
||||
x += child_rect.width;
|
||||
|
||||
meta_window_show_menu (display->focus_window,
|
||||
x, y,
|
||||
0,
|
||||
event->time);
|
||||
y = frame_rect.y + child_rect.y;
|
||||
meta_window_show_menu (display->focus_window, META_WINDOW_MENU_WM, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2723,7 +2762,7 @@ do_choose_window (MetaDisplay *display,
|
||||
gboolean backward)
|
||||
{
|
||||
MetaTabList type = binding->handler->data;
|
||||
MetaWindow *initial_selection;
|
||||
MetaWindow *window;
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Tab list = %u\n", type);
|
||||
@@ -2732,13 +2771,14 @@ do_choose_window (MetaDisplay *display,
|
||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||
backward = !backward;
|
||||
|
||||
initial_selection = meta_display_get_tab_next (display,
|
||||
window = meta_display_get_tab_next (display,
|
||||
type,
|
||||
screen->active_workspace,
|
||||
NULL,
|
||||
backward);
|
||||
|
||||
meta_window_activate (initial_selection, event->time);
|
||||
if (window)
|
||||
meta_window_activate (window, event->time);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3130,6 +3170,7 @@ handle_set_spew_mark (MetaDisplay *display,
|
||||
meta_verbose ("-- MARK MARK MARK MARK --\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
handle_switch_vt (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@@ -3147,11 +3188,12 @@ handle_switch_vt (MetaDisplay *display,
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NATIVE_BACKEND */
|
||||
|
||||
/**
|
||||
* meta_keybindings_set_custom_handler:
|
||||
* @name: The name of the keybinding to set
|
||||
* @handler: (allow-none): The new handler function
|
||||
* @handler: (nullable): The new handler function
|
||||
* @user_data: User data to pass to the callback
|
||||
* @free_data: Will be called when this handler is overridden.
|
||||
*
|
||||
@@ -3439,7 +3481,9 @@ init_builtin_key_bindings (MetaDisplay *display)
|
||||
META_KEYBINDING_ACTION_SET_SPEW_MARK,
|
||||
handle_set_spew_mark, 0);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
add_builtin_keybinding (display,
|
||||
"switch-to-session-1",
|
||||
@@ -3490,6 +3534,7 @@ init_builtin_key_bindings (MetaDisplay *display)
|
||||
META_KEYBINDING_ACTION_NONE,
|
||||
handle_switch_vt, 7);
|
||||
}
|
||||
#endif /* HAVE_NATIVE_BACKEND */
|
||||
|
||||
#undef REVERSES_AND_REVERSED
|
||||
|
||||
|
||||
@@ -181,7 +181,9 @@ static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
static gboolean opt_wayland;
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static gboolean opt_display_server;
|
||||
#endif
|
||||
|
||||
static GOptionEntry meta_options[] = {
|
||||
{
|
||||
@@ -225,11 +227,13 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_display_server,
|
||||
N_("Run as a full display server, rather than nested")
|
||||
},
|
||||
#endif
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -332,8 +336,10 @@ meta_init (void)
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
|
||||
if (opt_display_server)
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
#endif
|
||||
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ main (int argc, char **argv)
|
||||
g_printerr ("mutter: %s\n", error->message);
|
||||
exit (1);
|
||||
}
|
||||
g_option_context_free (ctx);
|
||||
|
||||
if (plugin)
|
||||
meta_plugin_manager_load (plugin);
|
||||
|
||||
@@ -82,6 +82,7 @@ find_next_cascade (MetaWindow *window,
|
||||
GList *tmp;
|
||||
GList *sorted;
|
||||
int cascade_x, cascade_y;
|
||||
MetaRectangle titlebar_rect;
|
||||
int x_threshold, y_threshold;
|
||||
MetaRectangle frame_rect;
|
||||
int window_width, window_height;
|
||||
@@ -102,19 +103,9 @@ find_next_cascade (MetaWindow *window,
|
||||
* manually cascade.
|
||||
*/
|
||||
#define CASCADE_FUZZ 15
|
||||
if (window->frame)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
x_threshold = MAX (borders.visible.left, CASCADE_FUZZ);
|
||||
y_threshold = MAX (borders.visible.top, CASCADE_FUZZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
x_threshold = CASCADE_FUZZ;
|
||||
y_threshold = CASCADE_FUZZ;
|
||||
}
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
x_threshold = MAX (titlebar_rect.x, CASCADE_FUZZ);
|
||||
y_threshold = MAX (titlebar_rect.y, CASCADE_FUZZ);
|
||||
|
||||
/* Find furthest-SE origin of all workspaces.
|
||||
* cascade_x, cascade_y are the target position
|
||||
@@ -151,13 +142,11 @@ find_next_cascade (MetaWindow *window,
|
||||
if (ABS (wx - cascade_x) < x_threshold &&
|
||||
ABS (wy - cascade_y) < y_threshold)
|
||||
{
|
||||
/* This window is "in the way", move to next cascade
|
||||
* point. The new window frame should go at the origin
|
||||
* of the client window we're stacking above.
|
||||
*/
|
||||
meta_window_get_position (w, &wx, &wy);
|
||||
cascade_x = wx;
|
||||
cascade_y = wy;
|
||||
meta_window_get_titlebar_rect (w, &titlebar_rect);
|
||||
|
||||
/* Cascade the window evenly by the titlebar height; this isn't a typo. */
|
||||
cascade_x = wx + titlebar_rect.height;
|
||||
cascade_y = wy + titlebar_rect.height;
|
||||
|
||||
/* If we go off the screen, start over with a new cascade */
|
||||
if (((cascade_x + window_width) >
|
||||
@@ -604,7 +593,6 @@ find_first_fit (MetaWindow *window,
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
g_list_free (below_sorted);
|
||||
g_list_free (right_sorted);
|
||||
return retval;
|
||||
@@ -617,13 +605,11 @@ meta_window_place (MetaWindow *window,
|
||||
int *new_x,
|
||||
int *new_y)
|
||||
{
|
||||
GList *windows;
|
||||
GList *windows = NULL;
|
||||
const MetaMonitorInfo *xi;
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||
|
||||
windows = NULL;
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
/* Run placement algorithm on these. */
|
||||
@@ -649,7 +635,7 @@ meta_window_place (MetaWindow *window,
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_DND:
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
goto done_no_constraints;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
@@ -694,7 +680,7 @@ meta_window_place (MetaWindow *window,
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing non-normal non-dialog window with PPosition set\n");
|
||||
goto done_no_constraints;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -709,7 +695,7 @@ meta_window_place (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing window with PPosition or USPosition set\n");
|
||||
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
|
||||
goto done_no_constraints;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,15 +791,6 @@ meta_window_place (MetaWindow *window,
|
||||
/* Warning, this is a round trip! */
|
||||
xi = meta_screen_get_current_monitor_info (window->screen);
|
||||
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
y = xi->rect.y;
|
||||
|
||||
if (find_first_fit (window, windows,
|
||||
xi->number,
|
||||
x, y, &x, &y))
|
||||
goto done_check_denied_focus;
|
||||
|
||||
/* Maximize windows if they are too big for their work area (bit of
|
||||
* a hack here). Assume undecorated windows probably don't intend to
|
||||
* be maximized.
|
||||
@@ -839,10 +816,16 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
/* If no placement has been done, revert to cascade to avoid
|
||||
* fully overlapping window (e.g. starting multiple terminals)
|
||||
* */
|
||||
if (x == xi->rect.x && y == xi->rect.y)
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
y = xi->rect.y;
|
||||
|
||||
if (find_first_fit (window, windows,
|
||||
xi->number,
|
||||
x, y, &x, &y))
|
||||
goto done_check_denied_focus;
|
||||
|
||||
/* No good fit? Fall back to cascading... */
|
||||
find_next_cascade (window, windows, x, y, &x, &y);
|
||||
|
||||
done_check_denied_focus:
|
||||
@@ -888,10 +871,9 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
|
||||
done:
|
||||
if (windows)
|
||||
g_list_free (windows);
|
||||
|
||||
done_no_constraints:
|
||||
|
||||
*new_x = x;
|
||||
*new_y = y;
|
||||
}
|
||||
|
||||
130
src/core/prefs.c
130
src/core/prefs.c
@@ -55,6 +55,7 @@
|
||||
#define KEY_GNOME_CURSOR_THEME "cursor-theme"
|
||||
#define KEY_GNOME_CURSOR_SIZE "cursor-size"
|
||||
#define KEY_XKB_OPTIONS "xkb-options"
|
||||
#define KEY_XSETTINGS_OVERRIDES "overrides"
|
||||
|
||||
#define KEY_OVERLAY_KEY "overlay-key"
|
||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||
@@ -65,6 +66,7 @@
|
||||
#define SCHEMA_MUTTER "org.gnome.mutter"
|
||||
#define SCHEMA_INTERFACE "org.gnome.desktop.interface"
|
||||
#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources"
|
||||
#define SCHEMA_XSETTINGS "org.gnome.settings-daemon.plugins.xsettings"
|
||||
|
||||
#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
|
||||
|
||||
@@ -104,6 +106,7 @@ static gboolean edge_tiling = FALSE;
|
||||
static gboolean force_fullscreen = TRUE;
|
||||
static gboolean ignore_request_hide_titlebar = FALSE;
|
||||
static gboolean auto_maximize = TRUE;
|
||||
static gboolean show_fallback_app_menu = FALSE;
|
||||
|
||||
static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
|
||||
static MetaButtonLayout button_layout;
|
||||
@@ -129,6 +132,10 @@ static void bindings_changed (GSettings *settings,
|
||||
gchar *key,
|
||||
gpointer data);
|
||||
|
||||
static void xsettings_overrides_changed (GSettings *settings,
|
||||
gchar *key,
|
||||
gpointer data);
|
||||
|
||||
static void queue_changed (MetaPreference pref);
|
||||
|
||||
static void maybe_give_disable_workarounds_warning (void);
|
||||
@@ -173,7 +180,7 @@ typedef struct
|
||||
|
||||
/**
|
||||
* MetaStringPreference:
|
||||
* @handler: (allow-none): A handler. Many of the string preferences
|
||||
* @handler: (nullable): A handler. Many of the string preferences
|
||||
* aren't stored as strings and need parsing; others of them have
|
||||
* default values which can't be solved in the general case. If you
|
||||
* include a function pointer here, it will be called instead of writing
|
||||
@@ -185,7 +192,7 @@ typedef struct
|
||||
* in particular the @result (out) parameter as returned by
|
||||
* g_settings_get_mapped() will be ignored in all cases.
|
||||
* This may be %NULL. If it is, see "target", below.
|
||||
* @target: (allow-none): Where to write the incoming string.
|
||||
* @target: (nullable): Where to write the incoming string.
|
||||
* This must be %NULL if the handler is non-%NULL.
|
||||
* If the incoming string is %NULL, no change will be made.
|
||||
*/
|
||||
@@ -802,7 +809,7 @@ handle_preference_update_int (GSettings *settings,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Listeners. */
|
||||
/****************************************************************************/
|
||||
@@ -931,11 +938,29 @@ queue_changed (MetaPreference pref)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Initialisation. */
|
||||
/****************************************************************************/
|
||||
|
||||
static GSettings *
|
||||
get_xsettings_settings (void)
|
||||
{
|
||||
GSettings *settings = NULL;
|
||||
GSettingsSchema *schema;
|
||||
|
||||
schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
|
||||
SCHEMA_XSETTINGS, FALSE);
|
||||
|
||||
if (schema)
|
||||
{
|
||||
settings = g_settings_new_full (schema, NULL, NULL);
|
||||
g_settings_schema_unref (schema);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_init (void)
|
||||
{
|
||||
@@ -965,6 +990,16 @@ meta_prefs_init (void)
|
||||
G_CALLBACK (settings_changed), NULL);
|
||||
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
|
||||
|
||||
settings = get_xsettings_settings ();
|
||||
if (settings)
|
||||
{
|
||||
g_signal_connect (settings, "changed::" KEY_XSETTINGS_OVERRIDES,
|
||||
G_CALLBACK (xsettings_overrides_changed), NULL);
|
||||
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_XSETTINGS), settings);
|
||||
|
||||
xsettings_overrides_changed (settings, KEY_XSETTINGS_OVERRIDES, NULL);
|
||||
}
|
||||
|
||||
settings = g_settings_new (SCHEMA_INPUT_SOURCES);
|
||||
g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS,
|
||||
G_CALLBACK (settings_changed), NULL);
|
||||
@@ -1117,7 +1152,7 @@ meta_prefs_override_preference_schema (const char *key, const char *schema)
|
||||
do_override (overridden->key, overridden->new_schema);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Updates. */
|
||||
/****************************************************************************/
|
||||
@@ -1184,6 +1219,44 @@ bindings_changed (GSettings *settings,
|
||||
g_strfreev (strokes);
|
||||
}
|
||||
|
||||
/* The fallback app menu should be enabled if either we are not
|
||||
* showing the app menu (e.g. when using the default plugin) or
|
||||
* with a corresponding XSettings override; we ignore the former
|
||||
* and assume that we always show the app menu, not least
|
||||
* because we rely on the compositor implementation to display
|
||||
* the fallback ...
|
||||
*/
|
||||
static void
|
||||
xsettings_overrides_changed (GSettings *settings,
|
||||
gchar *key,
|
||||
gpointer data)
|
||||
{
|
||||
GVariant *value;
|
||||
GVariantDict overrides;
|
||||
int shell_shows_app_menu = 1;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (!g_settings_get_boolean (settings, "active"))
|
||||
goto out;
|
||||
|
||||
value = g_settings_get_value (settings, KEY_XSETTINGS_OVERRIDES);
|
||||
|
||||
g_variant_dict_init (&overrides, value);
|
||||
g_variant_unref (value);
|
||||
|
||||
g_variant_dict_lookup (&overrides,
|
||||
"Gtk/ShellShowsAppMenu", "i", &shell_shows_app_menu);
|
||||
g_variant_dict_clear (&overrides);
|
||||
|
||||
changed = (show_fallback_app_menu == !!shell_shows_app_menu);
|
||||
|
||||
out:
|
||||
show_fallback_app_menu = !shell_shows_app_menu;
|
||||
|
||||
if (changed)
|
||||
queue_changed (META_PREF_BUTTON_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* maybe_give_disable_workaround_warning:
|
||||
*
|
||||
@@ -1243,6 +1316,12 @@ meta_prefs_get_raise_on_click (void)
|
||||
return raise_on_click || focus_mode == G_DESKTOP_FOCUS_MODE_CLICK;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_show_fallback_app_menu (void)
|
||||
{
|
||||
return show_fallback_app_menu;
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_prefs_get_theme (void)
|
||||
{
|
||||
@@ -1261,7 +1340,7 @@ meta_prefs_get_cursor_size (void)
|
||||
return cursor_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Handlers for string preferences. */
|
||||
/****************************************************************************/
|
||||
@@ -1398,6 +1477,8 @@ button_function_from_string (const char *str)
|
||||
{
|
||||
if (strcmp (str, "menu") == 0)
|
||||
return META_BUTTON_FUNCTION_MENU;
|
||||
else if (strcmp (str, "appmenu") == 0)
|
||||
return META_BUTTON_FUNCTION_APPMENU;
|
||||
else if (strcmp (str, "minimize") == 0)
|
||||
return META_BUTTON_FUNCTION_MINIMIZE;
|
||||
else if (strcmp (str, "maximize") == 0)
|
||||
@@ -2262,43 +2343,6 @@ meta_prefs_get_keybinding_action (const char *name)
|
||||
: META_KEYBINDING_ACTION_NONE;
|
||||
}
|
||||
|
||||
/* This is used by the menu system to decide what key binding
|
||||
* to display next to an option. We return the first non-disabled
|
||||
* binding, if any.
|
||||
*/
|
||||
void
|
||||
meta_prefs_get_window_binding (const char *name,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers)
|
||||
{
|
||||
MetaKeyPref *pref = g_hash_table_lookup (key_bindings, name);
|
||||
|
||||
if (pref->per_window)
|
||||
{
|
||||
GSList *s = pref->combos;
|
||||
|
||||
while (s)
|
||||
{
|
||||
MetaKeyCombo *c = s->data;
|
||||
|
||||
if (c->keysym != 0 || c->modifiers != 0)
|
||||
{
|
||||
*keysym = c->keysym;
|
||||
*modifiers = c->modifiers;
|
||||
return;
|
||||
}
|
||||
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
/* Not found; return the disabled value */
|
||||
*keysym = *modifiers = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
gint
|
||||
meta_prefs_get_mouse_button_resize (void)
|
||||
{
|
||||
|
||||
@@ -135,6 +135,7 @@ MetaScreen* meta_screen_new (MetaDisplay *displ
|
||||
guint32 timestamp);
|
||||
void meta_screen_free (MetaScreen *screen,
|
||||
guint32 timestamp);
|
||||
void meta_screen_init_workspaces (MetaScreen *screen);
|
||||
void meta_screen_manage_all_windows (MetaScreen *screen);
|
||||
void meta_screen_foreach_window (MetaScreen *screen,
|
||||
MetaScreenWindowFunc func,
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "x11/window-x11.h"
|
||||
#include "x11/xprops.h"
|
||||
|
||||
static char* get_screen_name (MetaDisplay *display,
|
||||
@@ -296,6 +297,7 @@ set_supported_hint (MetaScreen *screen)
|
||||
#undef EWMH_ATOMS_ONLY
|
||||
|
||||
screen->display->atom__GTK_FRAME_EXTENTS,
|
||||
screen->display->atom__GTK_SHOW_WINDOW_MENU,
|
||||
};
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
@@ -504,7 +506,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
Atom wm_sn_atom;
|
||||
char buf[128];
|
||||
guint32 manager_timestamp;
|
||||
gulong current_workspace;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
replace_current_wm = meta_get_replace_current_wm ();
|
||||
@@ -719,24 +720,10 @@ meta_screen_new (MetaDisplay *display,
|
||||
|
||||
meta_screen_update_workspace_layout (screen);
|
||||
|
||||
/* Get current workspace */
|
||||
current_workspace = 0;
|
||||
if (meta_prop_get_cardinal (screen->display,
|
||||
screen->xroot,
|
||||
screen->display->atom__NET_CURRENT_DESKTOP,
|
||||
¤t_workspace))
|
||||
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
|
||||
(int) current_workspace);
|
||||
else
|
||||
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
|
||||
|
||||
/* Screens must have at least one workspace at all times,
|
||||
* so create that required workspace.
|
||||
*/
|
||||
meta_workspace_activate (meta_workspace_new (screen), timestamp);
|
||||
update_num_workspaces (screen, timestamp);
|
||||
|
||||
set_workspace_names (screen);
|
||||
meta_workspace_new (screen);
|
||||
|
||||
screen->keys_grabbed = FALSE;
|
||||
meta_screen_grab_keys (screen);
|
||||
@@ -762,23 +749,46 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->startup_sequence_timeout = 0;
|
||||
#endif
|
||||
|
||||
/* Switch to the _NET_CURRENT_DESKTOP workspace */
|
||||
{
|
||||
MetaWorkspace *space;
|
||||
|
||||
space = meta_screen_get_workspace_by_index (screen,
|
||||
current_workspace);
|
||||
|
||||
if (space != NULL)
|
||||
meta_workspace_activate (space, timestamp);
|
||||
}
|
||||
|
||||
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
|
||||
screen->number, screen->screen_name, screen->xroot);
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_init_workspaces (MetaScreen *screen)
|
||||
{
|
||||
MetaWorkspace *current_workspace;
|
||||
gulong current_workspace_index = 0;
|
||||
guint32 timestamp;
|
||||
|
||||
g_return_if_fail (META_IS_SCREEN (screen));
|
||||
|
||||
timestamp = screen->wm_sn_timestamp;
|
||||
|
||||
/* Get current workspace */
|
||||
if (meta_prop_get_cardinal (screen->display,
|
||||
screen->xroot,
|
||||
screen->display->atom__NET_CURRENT_DESKTOP,
|
||||
¤t_workspace_index))
|
||||
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
|
||||
(int) current_workspace_index);
|
||||
else
|
||||
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
|
||||
|
||||
meta_workspace_activate (screen->workspaces->data, timestamp);
|
||||
update_num_workspaces (screen, timestamp);
|
||||
|
||||
set_workspace_names (screen);
|
||||
|
||||
/* Switch to the _NET_CURRENT_DESKTOP workspace */
|
||||
current_workspace = meta_screen_get_workspace_by_index (screen,
|
||||
current_workspace_index);
|
||||
|
||||
if (current_workspace != NULL)
|
||||
meta_workspace_activate (current_workspace, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_free (MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
|
||||
@@ -541,6 +541,8 @@ static void
|
||||
stack_tracker_apply_prediction (MetaStackTracker *tracker,
|
||||
MetaStackOp *op)
|
||||
{
|
||||
gboolean free_at_end = FALSE;
|
||||
|
||||
/* If this is a wayland operation then it's implicitly verified so
|
||||
* we can apply it immediately so long as it doesn't depend on any
|
||||
* unverified X operations...
|
||||
@@ -550,6 +552,8 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker,
|
||||
{
|
||||
if (meta_stack_op_apply (op, tracker->verified_stack))
|
||||
meta_stack_tracker_queue_sync_stack (tracker);
|
||||
|
||||
free_at_end = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -561,6 +565,9 @@ stack_tracker_apply_prediction (MetaStackTracker *tracker,
|
||||
meta_stack_op_apply (op, tracker->predicted_stack))
|
||||
meta_stack_tracker_queue_sync_stack (tracker);
|
||||
|
||||
if (free_at_end)
|
||||
meta_stack_op_free (op);
|
||||
|
||||
meta_stack_tracker_dump (tracker);
|
||||
}
|
||||
|
||||
@@ -895,7 +902,10 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
requery_xserver_stack (tracker);
|
||||
|
||||
for (l = tracker->unverified_predictions->head; l; l = l->next)
|
||||
{
|
||||
meta_stack_op_apply (l->data, tracker->verified_stack);
|
||||
meta_stack_op_free (l->data);
|
||||
}
|
||||
g_queue_clear (tracker->unverified_predictions);
|
||||
|
||||
j = 0;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdio.h>
|
||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||
#include <time.h> /* To initialize random seed */
|
||||
#include <math.h>
|
||||
|
||||
#define NUM_RANDOM_RUNS 10000
|
||||
|
||||
@@ -238,7 +239,7 @@ static GSList*
|
||||
get_strut_list (int which)
|
||||
{
|
||||
GSList *ans;
|
||||
MetaDirection wc = 0; /* wc == who cares? ;-) */
|
||||
MetaSide wc = 0; /* wc == who cares? ;-) */
|
||||
|
||||
ans = NULL;
|
||||
|
||||
@@ -248,32 +249,32 @@ get_strut_list (int which)
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, META_SIDE_BOTTOM));
|
||||
break;
|
||||
case 2:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_BOTTOM));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, META_SIDE_BOTTOM));
|
||||
break;
|
||||
case 3:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_LEFT));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, META_SIDE_BOTTOM));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
|
||||
break;
|
||||
case 4:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
|
||||
break;
|
||||
case 5:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, META_SIDE_RIGHT));
|
||||
break;
|
||||
case 6:
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, META_SIDE_TOP));
|
||||
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -623,15 +624,9 @@ test_regions_okay ()
|
||||
/*************************************************************/
|
||||
region = get_screen_region (3);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 675, 420, 525)); /* 220500 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); /* 354000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 320, 1180)); /* 377600 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 800, 475)); /* 380000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); /* 472000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 1600, 425)); /* 680000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 900, 20, 700, 1080)); /* 756000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 700, 1130)); /* 791000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 505)); /* 808000 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 1220, 1180)); /* 377600 */
|
||||
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1130)); /* 791000 */
|
||||
#if 0
|
||||
printf ("Got to here...\n");
|
||||
char region_list[(RECT_LENGTH+2) * g_list_length (region)];
|
||||
@@ -1332,6 +1327,7 @@ test_gravity_resize ()
|
||||
printf ("%s passed.\n", G_STRFUNC);
|
||||
}
|
||||
|
||||
#define EPSILON 0.000000001
|
||||
static void
|
||||
test_find_closest_point_to_line ()
|
||||
{
|
||||
@@ -1346,7 +1342,7 @@ test_find_closest_point_to_line ()
|
||||
x2, y2,
|
||||
px, py,
|
||||
&rx, &ry);
|
||||
g_assert (rx == answer_x && ry == answer_y);
|
||||
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
|
||||
|
||||
/* Special test for x1 == x2, so that slop of line is infinite */
|
||||
x1 = 3.0; y1 = 49.0;
|
||||
@@ -1357,7 +1353,7 @@ test_find_closest_point_to_line ()
|
||||
x2, y2,
|
||||
px, py,
|
||||
&rx, &ry);
|
||||
g_assert (rx == answer_x && ry == answer_y);
|
||||
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
|
||||
|
||||
/* Special test for y1 == y2, so perp line has slope of infinity */
|
||||
x1 = 3.14; y1 = 7.0;
|
||||
@@ -1368,7 +1364,7 @@ test_find_closest_point_to_line ()
|
||||
x2, y2,
|
||||
px, py,
|
||||
&rx, &ry);
|
||||
g_assert (rx == answer_x && ry == answer_y);
|
||||
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
|
||||
|
||||
/* Test when we the point we want to be closest to is actually on the line */
|
||||
x1 = 3.0; y1 = 49.0;
|
||||
@@ -1379,7 +1375,7 @@ test_find_closest_point_to_line ()
|
||||
x2, y2,
|
||||
px, py,
|
||||
&rx, &ry);
|
||||
g_assert (rx == answer_x && ry == answer_y);
|
||||
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
|
||||
|
||||
printf ("%s passed.\n", G_STRFUNC);
|
||||
}
|
||||
|
||||
@@ -74,11 +74,10 @@ typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||
META_DO_GRAVITY_ADJUST = 1 << 1,
|
||||
META_IS_USER_ACTION = 1 << 2,
|
||||
META_IS_MOVE_ACTION = 1 << 3,
|
||||
META_IS_RESIZE_ACTION = 1 << 4,
|
||||
META_IS_WAYLAND_RESIZE = 1 << 5
|
||||
META_IS_USER_ACTION = 1 << 1,
|
||||
META_IS_MOVE_ACTION = 1 << 2,
|
||||
META_IS_RESIZE_ACTION = 1 << 3,
|
||||
META_IS_WAYLAND_RESIZE = 1 << 4,
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
@@ -167,6 +166,7 @@ struct _MetaWindow
|
||||
* that to toggle between normal/tiled or maximized/tiled states. */
|
||||
guint saved_maximize : 1;
|
||||
int tile_monitor_number;
|
||||
int preferred_output_id;
|
||||
|
||||
/* Whether we're shaded */
|
||||
guint shaded : 1;
|
||||
@@ -303,9 +303,6 @@ struct _MetaWindow
|
||||
/* Have we placed this window? */
|
||||
guint placed : 1;
|
||||
|
||||
/* Must we force_save_user_window_placement? */
|
||||
guint force_save_user_rect : 1;
|
||||
|
||||
/* Is this not a transient of the focus window which is being denied focus? */
|
||||
guint denied_focus_and_not_transient : 1;
|
||||
|
||||
@@ -361,7 +358,8 @@ struct _MetaWindow
|
||||
/* if non-NULL, the bounds of the window frame */
|
||||
cairo_region_t *frame_bounds;
|
||||
|
||||
/* if non-NULL, the bounding shape region of the window */
|
||||
/* if non-NULL, the bounding shape region of the window. Relative to
|
||||
* the server-side client window. */
|
||||
cairo_region_t *shape_region;
|
||||
|
||||
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
|
||||
@@ -404,41 +402,38 @@ struct _MetaWindow
|
||||
/* window that gets updated net_wm_user_time values */
|
||||
Window user_time_window;
|
||||
|
||||
/* The size we set the window to last (i.e. what we believe
|
||||
* to be its actual size on the server). The x, y are
|
||||
* the actual server-side x,y so are relative to the frame
|
||||
* (meaning that they just hold the frame width and height)
|
||||
* or the root window (meaning they specify the location
|
||||
* of the top left of the inner window) as appropriate.
|
||||
*/
|
||||
MetaRectangle rect;
|
||||
|
||||
gboolean has_custom_frame_extents;
|
||||
GtkBorder custom_frame_extents;
|
||||
|
||||
/* The geometry to restore when we unmaximize. The position is in
|
||||
* root window coords, even if there's a frame, which contrasts with
|
||||
* window->rect above. Note that this gives the position and size
|
||||
* of the client window (i.e. ignoring the frame).
|
||||
*/
|
||||
/* The rectangles here are in "frame rect" coordinates. See the
|
||||
* comment at the top of meta_window_move_resize_internal() for more
|
||||
* information. */
|
||||
|
||||
/* The current window geometry of the window. */
|
||||
MetaRectangle rect;
|
||||
|
||||
/* The geometry to restore when we unmaximize. */
|
||||
MetaRectangle saved_rect;
|
||||
|
||||
/* This is the geometry the window had after the last user-initiated
|
||||
* move/resize operations. We use this whenever we are moving the
|
||||
* implicitly (for example, if we move to avoid a panel, we can snap
|
||||
* back to this position if the panel moves again). Note that this
|
||||
* gives the position and size of the client window (i.e. ignoring
|
||||
* the frame).
|
||||
*
|
||||
* Position always in root coords, unlike window->rect.
|
||||
/* This is the geometry the window will have if no constraints have
|
||||
* applied. We use this whenever we are moving implicitly (for example,
|
||||
* if we move to avoid a panel, we can snap back to this position if
|
||||
* the panel moves again).
|
||||
*/
|
||||
MetaRectangle user_rect;
|
||||
MetaRectangle unconstrained_rect;
|
||||
|
||||
/* The rectangle of the "server-side" geometry of the buffer,
|
||||
* in root coordinates.
|
||||
*
|
||||
* For X11 windows, this matches XGetGeometry of the toplevel.
|
||||
*
|
||||
* For Wayland windows, this matches the buffer size and where
|
||||
* the surface actor is positioned. */
|
||||
MetaRectangle buffer_rect;
|
||||
|
||||
/* Cached net_wm_icon_geometry */
|
||||
MetaRectangle icon_geometry;
|
||||
|
||||
/* Requested geometry */
|
||||
int border_width;
|
||||
/* x/y/w/h here get filled with ConfigureRequest values */
|
||||
XSizeHints size_hints;
|
||||
|
||||
@@ -446,8 +441,9 @@ struct _MetaWindow
|
||||
MetaStackLayer layer;
|
||||
int stack_position; /* see comment in stack.h */
|
||||
|
||||
/* Current dialog open for this window */
|
||||
/* Managed by delete.c */
|
||||
int dialog_pid;
|
||||
guint is_alive : 1;
|
||||
|
||||
/* maintained by group.c */
|
||||
MetaGroup *group;
|
||||
@@ -481,9 +477,10 @@ struct _MetaWindowClass
|
||||
MetaGrabOp op);
|
||||
void (*grab_op_ended) (MetaWindow *window,
|
||||
MetaGrabOp op);
|
||||
void (*current_workspace_changed) (MetaWindow *window);
|
||||
void (*move_resize_internal) (MetaWindow *window,
|
||||
int gravity,
|
||||
MetaRectangle requested_rect,
|
||||
MetaRectangle unconstrained_rect,
|
||||
MetaRectangle constrained_rect,
|
||||
MetaMoveResizeFlags flags,
|
||||
MetaMoveResizeResultFlags *result);
|
||||
@@ -527,13 +524,6 @@ MetaWindow * _meta_window_shared_new (MetaDisplay *display,
|
||||
MetaCompEffect effect,
|
||||
XWindowAttributes *attrs);
|
||||
|
||||
MetaWindow * meta_window_x11_new (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
gboolean must_be_viewable,
|
||||
MetaCompEffect effect);
|
||||
MetaWindow * meta_window_wayland_new (MetaDisplay *display,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
void meta_window_unmanage (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_calc_showing (MetaWindow *window);
|
||||
@@ -543,11 +533,6 @@ void meta_window_tile (MetaWindow *window);
|
||||
void meta_window_maximize_internal (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
MetaRectangle *saved_rect);
|
||||
void meta_window_unmaximize_with_gravity (MetaWindow *window,
|
||||
MetaMaximizeFlags directions,
|
||||
int new_width,
|
||||
int new_height,
|
||||
int gravity);
|
||||
|
||||
void meta_window_make_fullscreen_internal (MetaWindow *window);
|
||||
void meta_window_update_fullscreen_monitors (MetaWindow *window,
|
||||
@@ -556,27 +541,12 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
|
||||
unsigned long left,
|
||||
unsigned long right);
|
||||
|
||||
|
||||
/* args to move are window pos, not frame pos */
|
||||
void meta_window_move (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int root_x_nw,
|
||||
int root_y_nw);
|
||||
void meta_window_resize (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int w,
|
||||
int h);
|
||||
void meta_window_move_resize (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int root_x_nw,
|
||||
int root_y_nw,
|
||||
int w,
|
||||
int h);
|
||||
void meta_window_resize_with_gravity (MetaWindow *window,
|
||||
void meta_window_resize_frame_with_gravity (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int w,
|
||||
int h,
|
||||
int gravity);
|
||||
|
||||
void meta_window_change_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
@@ -585,17 +555,6 @@ gboolean meta_window_should_be_showing (MetaWindow *window);
|
||||
|
||||
void meta_window_update_struts (MetaWindow *window);
|
||||
|
||||
/* this gets root coords */
|
||||
void meta_window_get_position (MetaWindow *window,
|
||||
int *x,
|
||||
int *y);
|
||||
|
||||
/* Gets root coords for x, y, width & height of client window; uses
|
||||
* meta_window_get_position for x & y.
|
||||
*/
|
||||
void meta_window_get_client_root_coords (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/* gets position we need to set to stay in current position,
|
||||
* assuming position will be gravity-compensated. i.e.
|
||||
* this is the position a client would send in a configure
|
||||
@@ -608,7 +567,7 @@ void meta_window_get_gravity_position (MetaWindow *window,
|
||||
/* Get geometry for saving in the session; x/y are gravity
|
||||
* position, and w/h are in resize inc above the base size.
|
||||
*/
|
||||
void meta_window_get_geometry (MetaWindow *window,
|
||||
void meta_window_get_session_geometry (MetaWindow *window,
|
||||
int *x,
|
||||
int *y,
|
||||
int *width,
|
||||
@@ -619,15 +578,16 @@ void meta_window_update_unfocused_button_grabs (MetaWindow *window);
|
||||
void meta_window_set_focused_internal (MetaWindow *window,
|
||||
gboolean focused);
|
||||
|
||||
void meta_window_set_current_workspace_hint (MetaWindow *window);
|
||||
|
||||
unsigned long meta_window_get_net_wm_desktop (MetaWindow *window);
|
||||
void meta_window_current_workspace_changed (MetaWindow *window);
|
||||
|
||||
void meta_window_show_menu (MetaWindow *window,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp);
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_window_show_menu_for_rect (MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
gboolean meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
@@ -677,9 +637,6 @@ void meta_window_update_icon_now (MetaWindow *window);
|
||||
void meta_window_update_for_monitors_changed (MetaWindow *window);
|
||||
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
||||
|
||||
void meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
gboolean focused);
|
||||
|
||||
gboolean meta_window_should_attach_to_parent (MetaWindow *window);
|
||||
gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
|
||||
|
||||
@@ -713,14 +670,18 @@ void meta_window_handle_enter (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
guint root_x,
|
||||
guint root_y);
|
||||
void meta_window_handle_leave (MetaWindow *window);
|
||||
|
||||
gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_window_set_surface_mapped (MetaWindow *window,
|
||||
gboolean surface_mapped);
|
||||
|
||||
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
|
||||
|
||||
void meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
void meta_window_get_titlebar_rect (MetaWindow *window,
|
||||
MetaRectangle *titlebar_rect);
|
||||
|
||||
void meta_window_activate_full (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
@@ -729,7 +690,8 @@ void meta_window_activate_full (MetaWindow *window,
|
||||
|
||||
gboolean meta_window_is_client_decorated (MetaWindow *window);
|
||||
|
||||
void meta_window_update_monitor (MetaWindow *window);
|
||||
void meta_window_update_monitor (MetaWindow *window,
|
||||
gboolean user_op);
|
||||
|
||||
void meta_window_set_urgent (MetaWindow *window,
|
||||
gboolean urgent);
|
||||
@@ -742,13 +704,13 @@ void meta_window_update_resize (MetaWindow *window,
|
||||
void meta_window_move_resize_internal (MetaWindow *window,
|
||||
MetaMoveResizeFlags flags,
|
||||
int gravity,
|
||||
int root_x_nw,
|
||||
int root_y_nw,
|
||||
int w,
|
||||
int h);
|
||||
void meta_window_save_user_window_placement (MetaWindow *window);
|
||||
MetaRectangle frame_rect);
|
||||
|
||||
void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
|
||||
void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
|
||||
|
||||
void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
|
||||
|
||||
gboolean meta_window_has_pointer (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
||||
1637
src/core/window.c
1637
src/core/window.c
File diff suppressed because it is too large
Load Diff
@@ -342,7 +342,7 @@ meta_workspace_add_window (MetaWorkspace *workspace,
|
||||
|
||||
window->workspace = workspace;
|
||||
|
||||
meta_window_set_current_workspace_hint (window);
|
||||
meta_window_current_workspace_changed (window);
|
||||
|
||||
if (window->struts)
|
||||
{
|
||||
@@ -391,7 +391,7 @@ meta_workspace_remove_window (MetaWorkspace *workspace,
|
||||
g_assert (g_list_find (workspace->mru_list, window) == NULL);
|
||||
}
|
||||
|
||||
meta_window_set_current_workspace_hint (window);
|
||||
meta_window_current_workspace_changed (window);
|
||||
|
||||
if (window->struts)
|
||||
{
|
||||
@@ -718,7 +718,7 @@ meta_workspace_update_window_hints (MetaWorkspace *workspace)
|
||||
{
|
||||
MetaWindow *win = l->data;
|
||||
|
||||
meta_window_set_current_workspace_hint (win);
|
||||
meta_window_current_workspace_changed (win);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
@@ -1040,6 +1040,45 @@ void
|
||||
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
|
||||
GSList *struts)
|
||||
{
|
||||
MetaScreen *screen = workspace->screen;
|
||||
GSList *l;
|
||||
|
||||
for (l = struts; l; l = l->next)
|
||||
{
|
||||
MetaStrut *strut = l->data;
|
||||
int idx = meta_screen_get_monitor_index_for_rect (screen, &strut->rect);
|
||||
|
||||
switch (strut->side)
|
||||
{
|
||||
case META_SIDE_TOP:
|
||||
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_UP))
|
||||
continue;
|
||||
|
||||
strut->rect.height += strut->rect.y;
|
||||
strut->rect.y = 0;
|
||||
break;
|
||||
case META_SIDE_BOTTOM:
|
||||
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_DOWN))
|
||||
continue;
|
||||
|
||||
strut->rect.height = screen->rect.height - strut->rect.y;
|
||||
break;
|
||||
case META_SIDE_LEFT:
|
||||
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_LEFT))
|
||||
continue;
|
||||
|
||||
strut->rect.width += strut->rect.x;
|
||||
strut->rect.x = 0;
|
||||
break;
|
||||
case META_SIDE_RIGHT:
|
||||
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_RIGHT))
|
||||
continue;
|
||||
|
||||
strut->rect.width = screen->rect.width - strut->rect.x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reordering doesn't actually matter, so we don't catch all
|
||||
* no-impact changes, but this is just a (possibly unnecessary
|
||||
* anyways) optimization */
|
||||
|
||||
@@ -5,14 +5,9 @@ includedir=@includedir@
|
||||
girdir=@libdir@/mutter
|
||||
typelibdir=@libdir@/mutter
|
||||
|
||||
mutter_major_version=@MUTTER_MAJOR_VERSION@
|
||||
mutter_minor_version=@MUTTER_MINOR_VERSION@
|
||||
mutter_micro_version=@MUTTER_MICRO_VERSION@
|
||||
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
|
||||
|
||||
Name: libmutter
|
||||
Description: Mutter window manager library
|
||||
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lmutter
|
||||
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
|
||||
Cflags: -I${includedir}/mutter
|
||||
|
||||
@@ -62,6 +62,7 @@ item(_GTK_WINDOW_OBJECT_PATH)
|
||||
item(_GTK_APP_MENU_OBJECT_PATH)
|
||||
item(_GTK_MENUBAR_OBJECT_PATH)
|
||||
item(_GTK_FRAME_EXTENTS)
|
||||
item(_GTK_SHOW_WINDOW_MENU)
|
||||
item(_GNOME_WM_KEYBINDINGS)
|
||||
item(_GNOME_PANEL_ACTION)
|
||||
item(_GNOME_PANEL_ACTION_MAIN_MENU)
|
||||
|
||||
@@ -43,12 +43,11 @@
|
||||
#define META_VIRTUAL_CORE_POINTER_ID 2
|
||||
#define META_VIRTUAL_CORE_KEYBOARD_ID 3
|
||||
|
||||
typedef struct _MetaResizePopup MetaResizePopup;
|
||||
|
||||
/**
|
||||
* MetaFrameFlags:
|
||||
* @META_FRAME_ALLOWS_DELETE: frame allows delete
|
||||
* @META_FRAME_ALLOWS_MENU: frame allows menu
|
||||
* @META_FRAME_ALLOWS_APPMENU: frame allows (fallback) app menu
|
||||
* @META_FRAME_ALLOWS_MINIMIZE: frame allows minimize
|
||||
* @META_FRAME_ALLOWS_MAXIMIZE: frame allows maximize
|
||||
* @META_FRAME_ALLOWS_VERTICAL_RESIZE: frame allows vertical resize
|
||||
@@ -69,78 +68,24 @@ typedef enum
|
||||
{
|
||||
META_FRAME_ALLOWS_DELETE = 1 << 0,
|
||||
META_FRAME_ALLOWS_MENU = 1 << 1,
|
||||
META_FRAME_ALLOWS_MINIMIZE = 1 << 2,
|
||||
META_FRAME_ALLOWS_MAXIMIZE = 1 << 3,
|
||||
META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 4,
|
||||
META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 5,
|
||||
META_FRAME_HAS_FOCUS = 1 << 6,
|
||||
META_FRAME_SHADED = 1 << 7,
|
||||
META_FRAME_STUCK = 1 << 8,
|
||||
META_FRAME_MAXIMIZED = 1 << 9,
|
||||
META_FRAME_ALLOWS_SHADE = 1 << 10,
|
||||
META_FRAME_ALLOWS_MOVE = 1 << 11,
|
||||
META_FRAME_FULLSCREEN = 1 << 12,
|
||||
META_FRAME_IS_FLASHING = 1 << 13,
|
||||
META_FRAME_ABOVE = 1 << 14,
|
||||
META_FRAME_TILED_LEFT = 1 << 15,
|
||||
META_FRAME_TILED_RIGHT = 1 << 16
|
||||
META_FRAME_ALLOWS_APPMENU = 1 << 2,
|
||||
META_FRAME_ALLOWS_MINIMIZE = 1 << 3,
|
||||
META_FRAME_ALLOWS_MAXIMIZE = 1 << 4,
|
||||
META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 5,
|
||||
META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 6,
|
||||
META_FRAME_HAS_FOCUS = 1 << 7,
|
||||
META_FRAME_SHADED = 1 << 8,
|
||||
META_FRAME_STUCK = 1 << 9,
|
||||
META_FRAME_MAXIMIZED = 1 << 10,
|
||||
META_FRAME_ALLOWS_SHADE = 1 << 11,
|
||||
META_FRAME_ALLOWS_MOVE = 1 << 12,
|
||||
META_FRAME_FULLSCREEN = 1 << 13,
|
||||
META_FRAME_IS_FLASHING = 1 << 14,
|
||||
META_FRAME_ABOVE = 1 << 15,
|
||||
META_FRAME_TILED_LEFT = 1 << 16,
|
||||
META_FRAME_TILED_RIGHT = 1 << 17
|
||||
} MetaFrameFlags;
|
||||
|
||||
/**
|
||||
* MetaMenuOp:
|
||||
* @META_MENU_OP_NONE: No menu operation
|
||||
* @META_MENU_OP_DELETE: Menu operation delete
|
||||
* @META_MENU_OP_MINIMIZE: Menu operation minimize
|
||||
* @META_MENU_OP_UNMAXIMIZE: Menu operation unmaximize
|
||||
* @META_MENU_OP_MAXIMIZE: Menu operation maximize
|
||||
* @META_MENU_OP_UNSHADE: Menu operation unshade
|
||||
* @META_MENU_OP_SHADE: Menu operation shade
|
||||
* @META_MENU_OP_UNSTICK: Menu operation unstick
|
||||
* @META_MENU_OP_STICK: Menu operation stick
|
||||
* @META_MENU_OP_WORKSPACES: Menu operation workspaces
|
||||
* @META_MENU_OP_MOVE: Menu operation move
|
||||
* @META_MENU_OP_RESIZE: Menu operation resize
|
||||
* @META_MENU_OP_ABOVE: Menu operation above
|
||||
* @META_MENU_OP_UNABOVE: Menu operation unabove
|
||||
* @META_MENU_OP_MOVE_LEFT: Menu operation left
|
||||
* @META_MENU_OP_MOVE_RIGHT: Menu operation right
|
||||
* @META_MENU_OP_MOVE_UP: Menu operation up
|
||||
* @META_MENU_OP_MOVE_DOWN: Menu operation down
|
||||
* @META_MENU_OP_RECOVER: Menu operation recover
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_MENU_OP_NONE = 0,
|
||||
META_MENU_OP_DELETE = 1 << 0,
|
||||
META_MENU_OP_MINIMIZE = 1 << 1,
|
||||
META_MENU_OP_UNMAXIMIZE = 1 << 2,
|
||||
META_MENU_OP_MAXIMIZE = 1 << 3,
|
||||
META_MENU_OP_UNSHADE = 1 << 4,
|
||||
META_MENU_OP_SHADE = 1 << 5,
|
||||
META_MENU_OP_UNSTICK = 1 << 6,
|
||||
META_MENU_OP_STICK = 1 << 7,
|
||||
META_MENU_OP_WORKSPACES = 1 << 8,
|
||||
META_MENU_OP_MOVE = 1 << 9,
|
||||
META_MENU_OP_RESIZE = 1 << 10,
|
||||
META_MENU_OP_ABOVE = 1 << 11,
|
||||
META_MENU_OP_UNABOVE = 1 << 12,
|
||||
META_MENU_OP_MOVE_LEFT = 1 << 13,
|
||||
META_MENU_OP_MOVE_RIGHT = 1 << 14,
|
||||
META_MENU_OP_MOVE_UP = 1 << 15,
|
||||
META_MENU_OP_MOVE_DOWN = 1 << 16,
|
||||
META_MENU_OP_RECOVER = 1 << 17
|
||||
} MetaMenuOp;
|
||||
|
||||
typedef struct _MetaWindowMenu MetaWindowMenu;
|
||||
|
||||
typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
|
||||
Display *xdisplay,
|
||||
Window client_xwindow,
|
||||
guint32 timestamp,
|
||||
MetaMenuOp op,
|
||||
int workspace,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* MetaGrabOp:
|
||||
* @META_GRAB_OP_NONE: None
|
||||
@@ -226,6 +171,7 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_CURSOR_NONE = 0,
|
||||
META_CURSOR_DEFAULT,
|
||||
META_CURSOR_NORTH_RESIZE,
|
||||
META_CURSOR_SOUTH_RESIZE,
|
||||
@@ -413,6 +359,7 @@ typedef enum
|
||||
META_BUTTON_FUNCTION_UNSHADE,
|
||||
META_BUTTON_FUNCTION_UNABOVE,
|
||||
META_BUTTON_FUNCTION_UNSTICK,
|
||||
META_BUTTON_FUNCTION_APPMENU,
|
||||
META_BUTTON_FUNCTION_LAST
|
||||
} MetaButtonFunction;
|
||||
|
||||
@@ -421,10 +368,10 @@ typedef enum
|
||||
/* Keep array size in sync with MAX_BUTTONS_PER_CORNER */
|
||||
/**
|
||||
* MetaButtonLayout:
|
||||
* @left_buttons: (array fixed-size=10):
|
||||
* @right_buttons: (array fixed-size=10):
|
||||
* @left_buttons_has_spacer: (array fixed-size=10):
|
||||
* @right_buttons_has_spacer: (array fixed-size=10):
|
||||
* @left_buttons: (array fixed-size=11):
|
||||
* @right_buttons: (array fixed-size=11):
|
||||
* @left_buttons_has_spacer: (array fixed-size=11):
|
||||
* @right_buttons_has_spacer: (array fixed-size=11):
|
||||
*/
|
||||
typedef struct _MetaButtonLayout MetaButtonLayout;
|
||||
struct _MetaButtonLayout
|
||||
@@ -438,6 +385,19 @@ struct _MetaButtonLayout
|
||||
gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER];
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaWindowMenuType:
|
||||
* @META_WINDOW_MENU_WM: the window manager menu
|
||||
* @META_WINDOW_MENU_APP: the (fallback) app menu
|
||||
*
|
||||
* Menu the compositor should display for a given window
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_WINDOW_MENU_WM,
|
||||
META_WINDOW_MENU_APP
|
||||
} MetaWindowMenuType;
|
||||
|
||||
/**
|
||||
* MetaFrameBorders:
|
||||
* @visible: inner visible portion of frame border
|
||||
|
||||
@@ -101,9 +101,8 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean did_placement);
|
||||
void meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen);
|
||||
void meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean no_delay_frame);
|
||||
@@ -122,5 +121,14 @@ void meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
void meta_compositor_hide_tile_preview (MetaCompositor *compositor);
|
||||
void meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y);
|
||||
void meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
#endif /* META_COMPOSITOR_H */
|
||||
|
||||
@@ -94,7 +94,6 @@ guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display);
|
||||
|
||||
GList* meta_display_get_tab_list (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
MetaWindow* meta_display_get_tab_next (MetaDisplay *display,
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <meta/types.h>
|
||||
#include <meta/compositor.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include <meta/meta-version.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@@ -164,6 +165,17 @@ struct _MetaPluginClass
|
||||
int tile_monitor_number);
|
||||
void (*hide_tile_preview) (MetaPlugin *plugin);
|
||||
|
||||
void (*show_window_menu) (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void (*show_window_menu_for_rect) (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::kill_window_effects:
|
||||
* @actor: a #MetaWindowActor
|
||||
@@ -288,10 +300,10 @@ struct _MetaPluginVersion
|
||||
#define META_PLUGIN_DECLARE(ObjectName, object_name) \
|
||||
G_MODULE_EXPORT MetaPluginVersion meta_plugin_version = \
|
||||
{ \
|
||||
MUTTER_MAJOR_VERSION, \
|
||||
MUTTER_MINOR_VERSION, \
|
||||
MUTTER_MICRO_VERSION, \
|
||||
MUTTER_PLUGIN_API_VERSION \
|
||||
META_MAJOR_VERSION, \
|
||||
META_MINOR_VERSION, \
|
||||
META_MICRO_VERSION, \
|
||||
META_PLUGIN_API_VERSION \
|
||||
}; \
|
||||
\
|
||||
static GType g_define_type_id = 0; \
|
||||
|
||||
28
src/meta/meta-version.h.in
Normal file
28
src/meta/meta-version.h.in
Normal file
@@ -0,0 +1,28 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Rico Tzschichholz
|
||||
*
|
||||
* 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_VERSION_H
|
||||
#define META_VERSION_H
|
||||
|
||||
#define META_MAJOR_VERSION @MUTTER_MAJOR_VERSION@
|
||||
#define META_MINOR_VERSION @MUTTER_MINOR_VERSION@
|
||||
#define META_MICRO_VERSION @MUTTER_MICRO_VERSION@
|
||||
#define META_PLUGIN_API_VERSION @MUTTER_PLUGIN_API_VERSION@
|
||||
|
||||
#endif
|
||||
@@ -141,6 +141,7 @@ gboolean meta_prefs_get_gnome_animations (void);
|
||||
gboolean meta_prefs_get_edge_tiling (void);
|
||||
gboolean meta_prefs_get_auto_maximize (void);
|
||||
gboolean meta_prefs_get_center_new_windows (void);
|
||||
gboolean meta_prefs_get_show_fallback_app_menu (void);
|
||||
|
||||
void meta_prefs_get_button_layout (MetaButtonLayout *button_layout);
|
||||
|
||||
@@ -399,10 +400,6 @@ GType meta_key_binding_get_type (void);
|
||||
|
||||
MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name);
|
||||
|
||||
void meta_prefs_get_window_binding (const char *name,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers);
|
||||
|
||||
gboolean meta_prefs_get_visual_bell (void);
|
||||
gboolean meta_prefs_bell_is_audible (void);
|
||||
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
|
||||
|
||||
@@ -108,8 +108,7 @@ gboolean meta_window_appears_focused (MetaWindow *window);
|
||||
gboolean meta_window_is_shaded (MetaWindow *window);
|
||||
gboolean meta_window_is_override_redirect (MetaWindow *window);
|
||||
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
|
||||
MetaRectangle *meta_window_get_rect (MetaWindow *window);
|
||||
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
void meta_window_get_buffer_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
|
||||
void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect) G_GNUC_DEPRECATED;
|
||||
@@ -140,6 +139,7 @@ const char * meta_window_get_wm_class (MetaWindow *window);
|
||||
const char * meta_window_get_wm_class_instance (MetaWindow *window);
|
||||
gboolean meta_window_showing_on_its_workspace (MetaWindow *window);
|
||||
|
||||
const char * meta_window_get_gtk_theme_variant (MetaWindow *window);
|
||||
const char * meta_window_get_gtk_application_id (MetaWindow *window);
|
||||
const char * meta_window_get_gtk_unique_bus_name (MetaWindow *window);
|
||||
const char * meta_window_get_gtk_application_object_path (MetaWindow *window);
|
||||
@@ -147,11 +147,9 @@ const char * meta_window_get_gtk_window_object_path (MetaWindow *window);
|
||||
const char * meta_window_get_gtk_app_menu_object_path (MetaWindow *window);
|
||||
const char * meta_window_get_gtk_menubar_object_path (MetaWindow *window);
|
||||
|
||||
void meta_window_move(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
|
||||
void meta_window_move_frame(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
|
||||
void meta_window_move_resize_frame (MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw, int w, int h);
|
||||
void meta_window_move_to_monitor (MetaWindow *window, int monitor);
|
||||
void meta_window_resize(MetaWindow *window, gboolean user_op, int w, int h);
|
||||
|
||||
void meta_window_set_demands_attention (MetaWindow *window);
|
||||
void meta_window_unset_demands_attention (MetaWindow *window);
|
||||
|
||||
44
src/org.freedesktop.login1.xml
Normal file
44
src/org.freedesktop.login1.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.freedesktop.login1.Session">
|
||||
<property name="Active" type="b" access="read" />
|
||||
|
||||
<method name="Activate">
|
||||
</method>
|
||||
<method name="TakeControl">
|
||||
<arg name="force" type="b"/>
|
||||
</method>
|
||||
<method name="TakeDevice">
|
||||
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
|
||||
<arg name="major" type="u" direction="in"/>
|
||||
<arg name="minor" type="u" direction="in"/>
|
||||
<arg name="fd" type="h" direction="out"/>
|
||||
<arg name="paused" type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="ReleaseDevice">
|
||||
<arg name="major" type="u"/>
|
||||
<arg name="minor" type="u"/>
|
||||
</method>
|
||||
<method name="PauseDeviceComplete">
|
||||
<arg name="major" type="u"/>
|
||||
<arg name="minor" type="u"/>
|
||||
</method>
|
||||
<signal name="PauseDevice">
|
||||
<arg name="major" type="u"/>
|
||||
<arg name="minor" type="u"/>
|
||||
<arg name="type" type="s"/>
|
||||
</signal>
|
||||
<signal name="ResumeDevice">
|
||||
<arg name="major" type="u"/>
|
||||
<arg name="minor" type="u"/>
|
||||
<arg name="fd" type="h"/>
|
||||
</signal>
|
||||
</interface>
|
||||
|
||||
<interface name="org.freedesktop.login1.Seat">
|
||||
<method name="SwitchTo">
|
||||
<arg name="vt" type="u"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
244
src/ui/frames.c
244
src/ui/frames.c
@@ -28,7 +28,6 @@
|
||||
#include "frames.h"
|
||||
#include <meta/util.h>
|
||||
#include "core.h"
|
||||
#include "menu.h"
|
||||
#include <meta/theme.h>
|
||||
#include <meta/prefs.h>
|
||||
#include "ui.h"
|
||||
@@ -225,8 +224,6 @@ meta_frames_init (MetaFrames *frames)
|
||||
|
||||
update_style_contexts (frames);
|
||||
|
||||
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
|
||||
|
||||
meta_prefs_add_listener (prefs_changed_callback, frames);
|
||||
}
|
||||
|
||||
@@ -1102,9 +1099,9 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
|
||||
case G_DESKTOP_TITLEBAR_ACTION_MENU:
|
||||
meta_core_show_window_menu (display,
|
||||
frame->xwindow,
|
||||
META_WINDOW_MENU_WM,
|
||||
event->x_root,
|
||||
event->y_root,
|
||||
event->button,
|
||||
event->time);
|
||||
break;
|
||||
}
|
||||
@@ -1139,6 +1136,64 @@ meta_frame_right_click_event(MetaUIFrame *frame,
|
||||
return meta_frame_titlebar_event (frame, event, action);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_try_grab_op (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
MetaGrabOp op,
|
||||
gdouble grab_x,
|
||||
gdouble grab_y,
|
||||
guint32 time)
|
||||
{
|
||||
Display *display;
|
||||
gboolean ret;
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
ret = meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
op,
|
||||
FALSE,
|
||||
TRUE,
|
||||
frame->grab_button,
|
||||
0,
|
||||
time,
|
||||
grab_x, grab_y);
|
||||
if (!ret)
|
||||
{
|
||||
frames->current_grab_op = op;
|
||||
frames->grab_frame = frame;
|
||||
frames->grab_x = grab_x;
|
||||
frames->grab_y = grab_y;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_retry_grab_op (MetaFrames *frames,
|
||||
guint time)
|
||||
{
|
||||
Display *display;
|
||||
MetaGrabOp op;
|
||||
|
||||
if (frames->current_grab_op == META_GRAB_OP_NONE)
|
||||
return TRUE;
|
||||
|
||||
op = frames->current_grab_op;
|
||||
frames->current_grab_op = META_GRAB_OP_NONE;
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
return meta_core_begin_grab_op (display,
|
||||
frames->grab_frame->xwindow,
|
||||
op,
|
||||
FALSE,
|
||||
TRUE,
|
||||
frames->grab_frame->grab_button,
|
||||
0,
|
||||
time,
|
||||
frames->grab_x,
|
||||
frames->grab_y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
@@ -1193,6 +1248,8 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
if (meta_core_get_grab_op (display) != META_GRAB_OP_NONE)
|
||||
return FALSE; /* already up to something */
|
||||
|
||||
frame->grab_button = event->button;
|
||||
|
||||
if (event->button == 1 &&
|
||||
(control == META_FRAME_CONTROL_MAXIMIZE ||
|
||||
control == META_FRAME_CONTROL_UNMAXIMIZE ||
|
||||
@@ -1204,7 +1261,8 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
control == META_FRAME_CONTROL_UNABOVE ||
|
||||
control == META_FRAME_CONTROL_STICK ||
|
||||
control == META_FRAME_CONTROL_UNSTICK ||
|
||||
control == META_FRAME_CONTROL_MENU))
|
||||
control == META_FRAME_CONTROL_MENU ||
|
||||
control == META_FRAME_CONTROL_APPMENU))
|
||||
{
|
||||
frames->grab_xwindow = frame->xwindow;
|
||||
|
||||
@@ -1213,29 +1271,40 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
frame->prelit_control = control;
|
||||
redraw_control (frames, frame, control);
|
||||
|
||||
if (control == META_FRAME_CONTROL_MENU)
|
||||
if (control == META_FRAME_CONTROL_MENU ||
|
||||
control == META_FRAME_CONTROL_APPMENU)
|
||||
{
|
||||
MetaFrameGeometry fgeom;
|
||||
GdkRectangle *rect;
|
||||
int dx, dy;
|
||||
MetaRectangle root_rect;
|
||||
MetaWindowMenuType menu;
|
||||
int win_x, win_y;
|
||||
|
||||
meta_frames_calc_geometry (frames, frame, &fgeom);
|
||||
|
||||
rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom);
|
||||
rect = control_rect (control, &fgeom);
|
||||
|
||||
/* get delta to convert to root coords */
|
||||
dx = event->x_root - event->x;
|
||||
dy = event->y_root - event->y;
|
||||
/* convert to root coords */
|
||||
win_x = event->x_root - event->x;
|
||||
win_y = event->y_root - event->y;
|
||||
|
||||
/* Align to the right end of the menu rectangle if RTL */
|
||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||
dx += rect->width;
|
||||
root_rect.x = win_x + rect->x;
|
||||
root_rect.y = win_y + rect->y;
|
||||
root_rect.width = rect->width;
|
||||
root_rect.height = rect->height;
|
||||
|
||||
meta_core_show_window_menu (display,
|
||||
menu = control == META_FRAME_CONTROL_MENU ? META_WINDOW_MENU_WM
|
||||
: META_WINDOW_MENU_APP;
|
||||
|
||||
/* if the compositor takes a grab for showing the menu, we will
|
||||
* get a LeaveNotify event we want to ignore, to keep the pressed
|
||||
* button state while the menu is open
|
||||
*/
|
||||
frame->maybe_ignore_leave_notify = TRUE;
|
||||
meta_core_show_window_menu_for_rect (display,
|
||||
frame->xwindow,
|
||||
rect->x + dx,
|
||||
rect->y + rect->height + dy,
|
||||
event->button,
|
||||
menu,
|
||||
&root_rect,
|
||||
event->time);
|
||||
}
|
||||
}
|
||||
@@ -1284,16 +1353,9 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
break;
|
||||
}
|
||||
|
||||
meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
op,
|
||||
TRUE,
|
||||
TRUE,
|
||||
event->button,
|
||||
0,
|
||||
event->time,
|
||||
event->x_root,
|
||||
event->y_root);
|
||||
meta_frames_try_grab_op (frames, frame, op,
|
||||
event->x_root, event->y_root,
|
||||
event->time);
|
||||
}
|
||||
else if (control == META_FRAME_CONTROL_TITLE &&
|
||||
event->button == 1)
|
||||
@@ -1306,16 +1368,10 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
|
||||
if (flags & META_FRAME_ALLOWS_MOVE)
|
||||
{
|
||||
meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
meta_frames_try_grab_op (frames, frame,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
TRUE,
|
||||
event->button,
|
||||
0,
|
||||
event->time,
|
||||
event->x_root,
|
||||
event->y_root);
|
||||
event->x_root, event->y_root,
|
||||
event->time);
|
||||
}
|
||||
}
|
||||
else if (event->button == 2)
|
||||
@@ -1340,6 +1396,7 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
frames->current_grab_op = META_GRAB_OP_NONE;
|
||||
|
||||
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
|
||||
if (frame == NULL)
|
||||
@@ -1428,6 +1485,8 @@ meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
break;
|
||||
case META_FRAME_CONTROL_MENU:
|
||||
break;
|
||||
case META_FRAME_CONTROL_APPMENU:
|
||||
break;
|
||||
case META_FRAME_CONTROL_MINIMIZE:
|
||||
break;
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
@@ -1480,6 +1539,7 @@ meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
switch (control)
|
||||
{
|
||||
case META_FRAME_CONTROL_MENU:
|
||||
case META_FRAME_CONTROL_APPMENU:
|
||||
case META_FRAME_CONTROL_MINIMIZE:
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
case META_FRAME_CONTROL_DELETE:
|
||||
@@ -1498,7 +1558,8 @@ meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
break;
|
||||
}
|
||||
|
||||
if (control == frame->prelit_control)
|
||||
if (control == frame->prelit_control &&
|
||||
frame->button_state == META_BUTTON_STATE_PRELIGHT)
|
||||
return;
|
||||
|
||||
/* Save the old control so we can unprelight it */
|
||||
@@ -1547,6 +1608,10 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
}
|
||||
|
||||
if ((event->state & GDK_BUTTON1_MASK) &&
|
||||
frames->current_grab_op != META_GRAB_OP_NONE)
|
||||
meta_frames_retry_grab_op (frames, event->time);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1567,47 +1632,23 @@ meta_frames_destroy_event (GtkWidget *widget,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
|
||||
{
|
||||
GdkWindow *parent = gdk_window_get_parent (window);
|
||||
cairo_pattern_t *bg_pattern;
|
||||
|
||||
bg_pattern = gdk_window_get_background_pattern (window);
|
||||
if (bg_pattern == NULL && parent)
|
||||
{
|
||||
gint window_x, window_y;
|
||||
|
||||
gdk_window_get_position (window, &window_x, &window_y);
|
||||
setup_bg_cr (cr, parent, x_offset + window_x, y_offset + window_y);
|
||||
}
|
||||
else if (bg_pattern)
|
||||
{
|
||||
cairo_translate (cr, - x_offset, - y_offset);
|
||||
cairo_set_source (cr, bg_pattern);
|
||||
cairo_translate (cr, x_offset, y_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clip_region_to_visible_frame_border (cairo_region_t *region,
|
||||
MetaUIFrame *frame)
|
||||
static cairo_region_t *
|
||||
get_visible_frame_border_region (MetaUIFrame *frame)
|
||||
{
|
||||
MetaRectangle frame_rect;
|
||||
cairo_rectangle_int_t area;
|
||||
cairo_region_t *frame_border;
|
||||
MetaFrameFlags flags;
|
||||
MetaFrameType type;
|
||||
MetaFrameBorders borders;
|
||||
Display *display;
|
||||
int frame_width, frame_height;
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
meta_core_get (display, frame->xwindow,
|
||||
META_CORE_GET_FRAME_FLAGS, &flags,
|
||||
META_CORE_GET_FRAME_TYPE, &type,
|
||||
META_CORE_GET_FRAME_WIDTH, &frame_width,
|
||||
META_CORE_GET_FRAME_HEIGHT, &frame_height,
|
||||
META_CORE_GET_FRAME_RECT, &frame_rect,
|
||||
META_CORE_GET_END);
|
||||
|
||||
meta_theme_get_frame_borders (meta_theme_get_current (),
|
||||
@@ -1617,8 +1658,8 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
|
||||
/* Visible frame rect */
|
||||
area.x = borders.invisible.left;
|
||||
area.y = borders.invisible.top;
|
||||
area.width = frame_width - borders.invisible.left - borders.invisible.right;
|
||||
area.height = frame_height - borders.invisible.top - borders.invisible.bottom;
|
||||
area.width = frame_rect.width;
|
||||
area.height = frame_rect.height;
|
||||
|
||||
frame_border = cairo_region_create_rectangle (&area);
|
||||
|
||||
@@ -1630,9 +1671,7 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
|
||||
|
||||
/* Visible frame border */
|
||||
cairo_region_subtract_rectangle (frame_border, &area);
|
||||
cairo_region_intersect (region, frame_border);
|
||||
|
||||
cairo_region_destroy (frame_border);
|
||||
return frame_border;
|
||||
}
|
||||
|
||||
#define TAU (2*M_PI)
|
||||
@@ -1731,42 +1770,42 @@ meta_frames_get_mask (MetaFrames *frames,
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
/* XXX -- this is disgusting. Find a better approach here.
|
||||
* Use multiple widgets? */
|
||||
static MetaUIFrame *
|
||||
find_frame_to_draw (MetaFrames *frames,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
MetaUIFrame *frame;
|
||||
|
||||
g_hash_table_iter_init (&iter, frames->frames);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &frame, NULL))
|
||||
if (gtk_cairo_should_draw_window (cr, frame->window))
|
||||
return frame;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
MetaFrames *frames;
|
||||
cairo_rectangle_int_t clip;
|
||||
cairo_region_t *region;
|
||||
cairo_surface_t *target;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
target = cairo_get_target (cr);
|
||||
gdk_cairo_get_clip_rectangle (cr, &clip);
|
||||
|
||||
g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
|
||||
frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
|
||||
frame = find_frame_to_draw (frames, cr);
|
||||
if (frame == NULL)
|
||||
return FALSE;
|
||||
|
||||
region = cairo_region_create_rectangle (&clip);
|
||||
clip_region_to_visible_frame_border (region, frame);
|
||||
|
||||
if (cairo_region_is_empty (region))
|
||||
goto out;
|
||||
|
||||
region = get_visible_frame_border_region (frame);
|
||||
gdk_cairo_region (cr, region);
|
||||
cairo_clip (cr);
|
||||
|
||||
cairo_save (cr);
|
||||
setup_bg_cr (cr, frame->window, 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
meta_frames_paint (frames, frame, cr);
|
||||
|
||||
out:
|
||||
cairo_region_destroy (region);
|
||||
|
||||
return TRUE;
|
||||
@@ -1799,6 +1838,9 @@ meta_frames_paint (MetaFrames *frames,
|
||||
case META_FRAME_CONTROL_MENU:
|
||||
button_type = META_BUTTON_TYPE_MENU;
|
||||
break;
|
||||
case META_FRAME_CONTROL_APPMENU:
|
||||
button_type = META_BUTTON_TYPE_APPMENU;
|
||||
break;
|
||||
case META_FRAME_CONTROL_MINIMIZE:
|
||||
button_type = META_BUTTON_TYPE_MINIMIZE;
|
||||
break;
|
||||
@@ -1922,6 +1964,8 @@ meta_frames_enter_notify_event (GtkWidget *widget,
|
||||
if (frame == NULL)
|
||||
return FALSE;
|
||||
|
||||
frame->maybe_ignore_leave_notify = FALSE;
|
||||
|
||||
control = get_control (frames, frame, event->x, event->y);
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
|
||||
@@ -1934,6 +1978,8 @@ meta_frames_leave_notify_event (GtkWidget *widget,
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
MetaFrames *frames;
|
||||
Display *display;
|
||||
MetaGrabOp grab_op;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
|
||||
@@ -1941,6 +1987,18 @@ meta_frames_leave_notify_event (GtkWidget *widget,
|
||||
if (frame == NULL)
|
||||
return FALSE;
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
grab_op = meta_core_get_grab_op (display);
|
||||
|
||||
/* ignore the first LeaveNotify event after opening a window menu
|
||||
* if it is the result of a compositor grab
|
||||
*/
|
||||
frame->maybe_ignore_leave_notify = frame->maybe_ignore_leave_notify &&
|
||||
grab_op == META_GRAB_OP_COMPOSITOR;
|
||||
|
||||
if (frame->maybe_ignore_leave_notify)
|
||||
return FALSE;
|
||||
|
||||
meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
|
||||
|
||||
return TRUE;
|
||||
@@ -1964,6 +2022,9 @@ control_rect (MetaFrameControl control,
|
||||
case META_FRAME_CONTROL_MENU:
|
||||
rect = &fgeom->menu_rect.visible;
|
||||
break;
|
||||
case META_FRAME_CONTROL_APPMENU:
|
||||
rect = &fgeom->appmenu_rect.visible;
|
||||
break;
|
||||
case META_FRAME_CONTROL_MINIMIZE:
|
||||
rect = &fgeom->min_rect.visible;
|
||||
break;
|
||||
@@ -2043,6 +2104,9 @@ get_control (MetaFrames *frames,
|
||||
if (POINT_IN_RECT (x, y, fgeom.menu_rect.clickable))
|
||||
return META_FRAME_CONTROL_MENU;
|
||||
|
||||
if (POINT_IN_RECT (x, y, fgeom.appmenu_rect.clickable))
|
||||
return META_FRAME_CONTROL_APPMENU;
|
||||
|
||||
meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow,
|
||||
META_CORE_GET_FRAME_FLAGS, &flags,
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef enum
|
||||
META_FRAME_CONTROL_TITLE,
|
||||
META_FRAME_CONTROL_DELETE,
|
||||
META_FRAME_CONTROL_MENU,
|
||||
META_FRAME_CONTROL_APPMENU,
|
||||
META_FRAME_CONTROL_MINIMIZE,
|
||||
META_FRAME_CONTROL_MAXIMIZE,
|
||||
META_FRAME_CONTROL_UNMAXIMIZE,
|
||||
@@ -79,6 +80,7 @@ struct _MetaUIFrame
|
||||
int text_height;
|
||||
char *title; /* NULL once we have a layout */
|
||||
guint shape_applied : 1;
|
||||
guint maybe_ignore_leave_notify : 1;
|
||||
|
||||
/* FIXME get rid of this, it can just be in the MetaFrames struct */
|
||||
MetaFrameControl prelit_control;
|
||||
@@ -98,6 +100,12 @@ struct _MetaFrames
|
||||
GtkStyleContext *normal_style;
|
||||
GHashTable *style_variants;
|
||||
|
||||
MetaGrabOp current_grab_op;
|
||||
MetaUIFrame *grab_frame;
|
||||
guint grab_button;
|
||||
gdouble grab_x;
|
||||
gdouble grab_y;
|
||||
|
||||
Window grab_xwindow;
|
||||
};
|
||||
|
||||
|
||||
516
src/ui/menu.c
516
src/ui/menu.c
@@ -1,516 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter window menu */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2004 Rob Adams
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "menu.h"
|
||||
#include <meta/main.h>
|
||||
#include "util-private.h"
|
||||
#include "core.h"
|
||||
#include "metaaccellabel.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct _MenuItem MenuItem;
|
||||
typedef struct _MenuData MenuData;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MENU_ITEM_SEPARATOR = 0,
|
||||
MENU_ITEM_NORMAL,
|
||||
MENU_ITEM_CHECKBOX,
|
||||
MENU_ITEM_RADIOBUTTON,
|
||||
MENU_ITEM_WORKSPACE_LIST,
|
||||
} MetaMenuItemType;
|
||||
|
||||
struct _MenuItem
|
||||
{
|
||||
MetaMenuOp op;
|
||||
MetaMenuItemType type;
|
||||
const gboolean checked;
|
||||
const char *label;
|
||||
};
|
||||
|
||||
|
||||
struct _MenuData
|
||||
{
|
||||
MetaWindowMenu *menu;
|
||||
MetaMenuOp op;
|
||||
};
|
||||
|
||||
static void activate_cb (GtkWidget *menuitem, gpointer data);
|
||||
|
||||
static MenuItem menuitems[] = {
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
|
||||
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Always on Visible Workspace") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Only on This Workspace") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Left") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace R_ight") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Up") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Down") },
|
||||
{ 0, MENU_ITEM_WORKSPACE_LIST, FALSE, NULL },
|
||||
{ 0, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
|
||||
};
|
||||
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkRequisition req;
|
||||
GdkPoint *pos;
|
||||
|
||||
pos = user_data;
|
||||
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
|
||||
|
||||
*x = pos->x;
|
||||
*y = pos->y;
|
||||
|
||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||
*x = MAX (0, *x - req.width);
|
||||
|
||||
/* Ensure onscreen */
|
||||
*x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width));
|
||||
*y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
|
||||
}
|
||||
|
||||
static void
|
||||
menu_closed (GtkMenu *widget,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWindowMenu *menu;
|
||||
|
||||
menu = data;
|
||||
|
||||
(* menu->func) (menu,
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
menu->client_xwindow,
|
||||
gtk_get_current_event_time (),
|
||||
0, 0,
|
||||
menu->data);
|
||||
|
||||
/* menu may now be freed */
|
||||
}
|
||||
|
||||
static void
|
||||
activate_cb (GtkWidget *menuitem, gpointer data)
|
||||
{
|
||||
MenuData *md;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (menuitem));
|
||||
|
||||
md = data;
|
||||
|
||||
(* md->menu->func) (md->menu,
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
md->menu->client_xwindow,
|
||||
gtk_get_current_event_time (),
|
||||
md->op,
|
||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem),
|
||||
"workspace")),
|
||||
md->menu->data);
|
||||
|
||||
/* menu may now be freed */
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a Display and an index, get the workspace name and add any
|
||||
* accelerators. At the moment this means adding a _ if the name is of
|
||||
* the form "Workspace n" where n is less than 10, and escaping any
|
||||
* other '_'s so they do not create inadvertant accelerators.
|
||||
*
|
||||
* The calling code owns the string, and is reponsible to free the
|
||||
* memory after use.
|
||||
*
|
||||
* See also http://mail.gnome.org/archives/gnome-i18n/2008-March/msg00380.html
|
||||
* which discusses possible i18n concerns.
|
||||
*/
|
||||
static char*
|
||||
get_workspace_name_with_accel (Display *display,
|
||||
Window xroot,
|
||||
int index)
|
||||
{
|
||||
const char *name;
|
||||
int number;
|
||||
int charcount=0;
|
||||
|
||||
name = meta_core_get_workspace_name_with_index (display, xroot, index);
|
||||
|
||||
g_assert (name != NULL);
|
||||
|
||||
/*
|
||||
* If the name is of the form "Workspace x" where x is an unsigned
|
||||
* integer, insert a '_' before the number if it is less than 10 and
|
||||
* return it
|
||||
*/
|
||||
number = 0;
|
||||
if (sscanf (name, _("Workspace %d%n"), &number, &charcount) != 0 &&
|
||||
*(name + charcount)=='\0')
|
||||
{
|
||||
char *new_name;
|
||||
|
||||
/*
|
||||
* Above name is a pointer into the Workspace struct. Here we make
|
||||
* a copy copy so we can have our wicked way with it.
|
||||
*/
|
||||
if (number == 10)
|
||||
new_name = g_strdup_printf (_("Workspace 1_0"));
|
||||
else
|
||||
new_name = g_strdup_printf (_("Workspace %s%d"),
|
||||
number < 10 ? "_" : "",
|
||||
number);
|
||||
return new_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Otherwise this is just a normal name. Escape any _ characters so that
|
||||
* the user's workspace names do not get mangled. If the number is less
|
||||
* than 10 we provide an accelerator.
|
||||
*/
|
||||
char *new_name;
|
||||
const char *source;
|
||||
char *dest;
|
||||
|
||||
/*
|
||||
* Assume the worst case, that every character is a _. We also
|
||||
* provide memory for " (_#)"
|
||||
*/
|
||||
new_name = g_malloc0 (strlen (name) * 2 + 6 + 1);
|
||||
|
||||
/*
|
||||
* Now iterate down the strings, adding '_' to escape as we go
|
||||
*/
|
||||
dest = new_name;
|
||||
source = name;
|
||||
while (*source != '\0')
|
||||
{
|
||||
if (*source == '_')
|
||||
*dest++ = '_';
|
||||
*dest++ = *source++;
|
||||
}
|
||||
|
||||
/* People don't start at workspace 0, but workspace 1 */
|
||||
if (index < 9)
|
||||
{
|
||||
g_snprintf (dest, 6, " (_%d)", index + 1);
|
||||
}
|
||||
else if (index == 9)
|
||||
{
|
||||
g_snprintf (dest, 6, " (_0)");
|
||||
}
|
||||
|
||||
return new_name;
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
menu_item_new (MenuItem *menuitem, int workspace_id)
|
||||
{
|
||||
unsigned int key;
|
||||
MetaVirtualModifier mods;
|
||||
const char *i18n_label;
|
||||
GtkWidget *mi;
|
||||
GtkWidget *accel_label;
|
||||
|
||||
if (menuitem->type == MENU_ITEM_NORMAL)
|
||||
{
|
||||
mi = gtk_menu_item_new ();
|
||||
}
|
||||
else if (menuitem->type == MENU_ITEM_CHECKBOX)
|
||||
{
|
||||
mi = gtk_check_menu_item_new ();
|
||||
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
|
||||
menuitem->checked);
|
||||
}
|
||||
else if (menuitem->type == MENU_ITEM_RADIOBUTTON)
|
||||
{
|
||||
mi = gtk_check_menu_item_new ();
|
||||
|
||||
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (mi),
|
||||
TRUE);
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
|
||||
menuitem->checked);
|
||||
}
|
||||
else if (menuitem->type == MENU_ITEM_WORKSPACE_LIST)
|
||||
return NULL;
|
||||
else
|
||||
return gtk_separator_menu_item_new ();
|
||||
|
||||
i18n_label = _(menuitem->label);
|
||||
meta_core_get_menu_accelerator (menuitem->op, workspace_id, &key, &mods);
|
||||
|
||||
accel_label = meta_accel_label_new_with_mnemonic (i18n_label);
|
||||
gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (mi), accel_label);
|
||||
gtk_widget_show (accel_label);
|
||||
|
||||
meta_accel_label_set_accelerator (META_ACCEL_LABEL (accel_label),
|
||||
key, mods);
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
MetaWindowMenu*
|
||||
meta_window_menu_new (MetaFrames *frames,
|
||||
MetaMenuOp ops,
|
||||
MetaMenuOp insensitive,
|
||||
Window client_xwindow,
|
||||
unsigned long active_workspace,
|
||||
int n_workspaces,
|
||||
MetaWindowMenuFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
int i;
|
||||
MetaWindowMenu *menu;
|
||||
|
||||
/* FIXME: Modifications to 'ops' should happen in meta_window_show_menu */
|
||||
if (n_workspaces < 2)
|
||||
ops &= ~(META_MENU_OP_STICK | META_MENU_OP_UNSTICK | META_MENU_OP_WORKSPACES);
|
||||
else if (n_workspaces == 2)
|
||||
/* #151183: If we only have two workspaces, disable the menu listing them. */
|
||||
ops &= ~(META_MENU_OP_WORKSPACES);
|
||||
|
||||
menu = g_new (MetaWindowMenu, 1);
|
||||
menu->frames = frames;
|
||||
menu->client_xwindow = client_xwindow;
|
||||
menu->func = func;
|
||||
menu->data = data;
|
||||
menu->ops = ops;
|
||||
menu->insensitive = insensitive;
|
||||
|
||||
menu->menu = gtk_menu_new ();
|
||||
|
||||
gtk_menu_set_screen (GTK_MENU (menu->menu),
|
||||
gtk_widget_get_screen (GTK_WIDGET (frames)));
|
||||
|
||||
for (i = 0; i < (int) G_N_ELEMENTS (menuitems); i++)
|
||||
{
|
||||
MenuItem menuitem = menuitems[i];
|
||||
if (ops & menuitem.op || menuitem.op == 0)
|
||||
{
|
||||
GtkWidget *mi;
|
||||
MenuData *md;
|
||||
unsigned int key;
|
||||
MetaVirtualModifier mods;
|
||||
|
||||
mi = menu_item_new (&menuitem, -1);
|
||||
|
||||
/* Set the activeness of radiobuttons. */
|
||||
switch (menuitem.op)
|
||||
{
|
||||
case META_MENU_OP_STICK:
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
|
||||
active_workspace == 0xFFFFFFFF);
|
||||
break;
|
||||
case META_MENU_OP_UNSTICK:
|
||||
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
|
||||
active_workspace != 0xFFFFFFFF);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (menuitem.type == MENU_ITEM_WORKSPACE_LIST)
|
||||
{
|
||||
if (ops & META_MENU_OP_WORKSPACES)
|
||||
{
|
||||
Display *display;
|
||||
Window xroot;
|
||||
GdkScreen *screen;
|
||||
GdkWindow *window;
|
||||
GtkWidget *submenu;
|
||||
int j;
|
||||
|
||||
MenuItem to_another_workspace = {
|
||||
0, MENU_ITEM_NORMAL, FALSE,
|
||||
N_("Move to Another _Workspace")
|
||||
};
|
||||
|
||||
meta_verbose ("Creating %d-workspace menu current space %lu\n",
|
||||
n_workspaces, active_workspace);
|
||||
|
||||
window = gtk_widget_get_window (GTK_WIDGET (frames));
|
||||
display = GDK_WINDOW_XDISPLAY (window);
|
||||
|
||||
screen = gdk_window_get_screen (window);
|
||||
xroot = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
|
||||
|
||||
submenu = gtk_menu_new ();
|
||||
|
||||
g_assert (mi==NULL);
|
||||
mi = menu_item_new (&to_another_workspace, -1);
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu);
|
||||
|
||||
for (j = 0; j < n_workspaces; j++)
|
||||
{
|
||||
char *label;
|
||||
MenuData *md;
|
||||
unsigned int key;
|
||||
MetaVirtualModifier mods;
|
||||
MenuItem moveitem;
|
||||
GtkWidget *submi;
|
||||
|
||||
meta_core_get_menu_accelerator (META_MENU_OP_WORKSPACES,
|
||||
j + 1,
|
||||
&key, &mods);
|
||||
|
||||
label = get_workspace_name_with_accel (display, xroot, j);
|
||||
|
||||
moveitem.type = MENU_ITEM_NORMAL;
|
||||
moveitem.op = META_MENU_OP_WORKSPACES;
|
||||
moveitem.label = label;
|
||||
submi = menu_item_new (&moveitem, j + 1);
|
||||
|
||||
g_free (label);
|
||||
|
||||
if ((active_workspace == (unsigned)j) && (ops & META_MENU_OP_UNSTICK))
|
||||
gtk_widget_set_sensitive (submi, FALSE);
|
||||
|
||||
md = g_new (MenuData, 1);
|
||||
|
||||
md->menu = menu;
|
||||
md->op = META_MENU_OP_WORKSPACES;
|
||||
|
||||
g_object_set_data (G_OBJECT (submi),
|
||||
"workspace",
|
||||
GINT_TO_POINTER (j));
|
||||
|
||||
g_signal_connect_data (G_OBJECT (submi),
|
||||
"activate",
|
||||
G_CALLBACK (activate_cb),
|
||||
md,
|
||||
(GClosureNotify) g_free, 0);
|
||||
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), submi);
|
||||
|
||||
gtk_widget_show (submi);
|
||||
}
|
||||
}
|
||||
else
|
||||
meta_verbose ("not creating workspace menu\n");
|
||||
}
|
||||
else if (menuitem.type != MENU_ITEM_SEPARATOR)
|
||||
{
|
||||
meta_core_get_menu_accelerator (menuitems[i].op, -1,
|
||||
&key, &mods);
|
||||
|
||||
if (insensitive & menuitem.op)
|
||||
gtk_widget_set_sensitive (mi, FALSE);
|
||||
|
||||
md = g_new (MenuData, 1);
|
||||
|
||||
md->menu = menu;
|
||||
md->op = menuitem.op;
|
||||
|
||||
g_signal_connect_data (G_OBJECT (mi),
|
||||
"activate",
|
||||
G_CALLBACK (activate_cb),
|
||||
md,
|
||||
(GClosureNotify) g_free, 0);
|
||||
}
|
||||
|
||||
if (mi)
|
||||
{
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), mi);
|
||||
|
||||
gtk_widget_show (mi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
g_signal_connect (menu->menu, "selection_done",
|
||||
G_CALLBACK (menu_closed), menu);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_menu_popup (MetaWindowMenu *menu,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp)
|
||||
{
|
||||
GdkPoint *pt;
|
||||
|
||||
pt = g_new (GdkPoint, 1);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (menu->menu),
|
||||
"destroy-point",
|
||||
pt,
|
||||
g_free);
|
||||
|
||||
pt->x = root_x;
|
||||
pt->y = root_y;
|
||||
|
||||
gtk_menu_popup (GTK_MENU (menu->menu),
|
||||
NULL, NULL,
|
||||
popup_position_func, pt,
|
||||
button,
|
||||
timestamp);
|
||||
|
||||
if (!gtk_widget_get_visible (menu->menu))
|
||||
meta_warning ("GtkMenu failed to grab the pointer\n");
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_menu_free (MetaWindowMenu *menu)
|
||||
{
|
||||
gtk_widget_destroy (menu->menu);
|
||||
g_free (menu);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user