Compare commits
207 Commits
wip/xtogls
...
3.13.4
Author | SHA1 | Date | |
---|---|---|---|
1d8e4bdd6d | |||
1677a068ce | |||
a02b8441b1 | |||
dfe1c106f2 | |||
e49bbe2ed8 | |||
6ee5a1437c | |||
93a3383e60 | |||
c9a2a561f8 | |||
ac0b2fdc6f | |||
46b9984414 | |||
f9743e2174 | |||
a3c55c2692 | |||
692eb4d957 | |||
826751429b | |||
5621d3c0c7 | |||
b5f46c9171 | |||
166b8c042c | |||
d34ece6f1a | |||
679844f791 | |||
9316256e10 | |||
90d7737fc1 | |||
567ca15610 | |||
558b323485 | |||
1a05da8296 | |||
5df59f75cd | |||
029673d0ee | |||
3a57f843d5 | |||
182a267f69 | |||
3de40434fa | |||
bc8328d7c2 | |||
12c1a06e60 | |||
b11405570a | |||
3b85e4b2b9 | |||
c5abf5ddbb | |||
2a3d4b62a7 | |||
8ff81bcc37 | |||
7159d3bc35 | |||
941d202938 | |||
5ea0cf8bab | |||
df9a5f867f | |||
06e4778072 | |||
92388892b3 | |||
5d124ac00a | |||
a57c3ae105 | |||
55354f5c38 | |||
379bb0a77d | |||
39357fc242 | |||
799de4f0f4 | |||
c34b5c1cf0 | |||
46361c3e28 | |||
f9d33b2efc | |||
2185904fcb | |||
eb952819c2 | |||
d7d8c92a9a | |||
88a7790d44 | |||
806dabe2d7 | |||
740e7ddd69 | |||
bee97ab6a7 | |||
59fc17c355 | |||
5f25ca0c3a | |||
41b4a079c7 | |||
e4235376d8 | |||
043a201f90 | |||
d1a588a94f | |||
01b6d9bfe2 | |||
9711d95996 | |||
b87db00fdb | |||
6190b65056 | |||
10fe91d704 | |||
36bb05b10e | |||
a7b7213017 | |||
031154a400 | |||
463b50e746 | |||
1749a85e96 | |||
1af9e92e91 | |||
12d0c98fb5 | |||
817c6986a0 | |||
7c68aaea4c | |||
6fea46e0cf | |||
59fa74fed1 | |||
581335fbea | |||
9b5d6cc008 | |||
d0f98ec1ba | |||
a977fcf3d0 | |||
664f6ef420 | |||
06a31992e3 | |||
4e2092d593 | |||
9755f308e5 | |||
09610daea1 | |||
13b7fa4eba | |||
909a46087f | |||
c10c8649f5 | |||
82dce6758a | |||
024652bfb4 | |||
789608b637 | |||
d05b750b8d | |||
704cae1de3 | |||
23b074481a | |||
5dc8fa6690 | |||
a9ba98686f | |||
59382bace2 | |||
2edf822bc6 | |||
355621b0ab | |||
a307e13a63 | |||
f807207b65 | |||
30b54aae34 | |||
79e682bcd0 | |||
a05ae8654c | |||
0db172edbf | |||
7b0930f798 | |||
0919b37c34 | |||
faf55c4627 | |||
f351c5d304 | |||
63bca17ab6 | |||
c2abe43ee7 | |||
1de2fd7122 | |||
e377e82cfd | |||
fa8174a200 | |||
d22448731c | |||
ef95133b1c | |||
c068c2122d | |||
d8c47b0abd | |||
66eb4bc34c | |||
bce812ecbc | |||
02220ed6c7 | |||
8d08851f28 | |||
af135c0b0b | |||
42c972735e | |||
110c79d10e | |||
b9d867cb86 | |||
ea3b961e43 | |||
bc510378b3 | |||
0a47d135ac | |||
ec8ed1dbb0 | |||
203e5335ab | |||
f1d8428650 | |||
8d29d22e99 | |||
9c6e527d4b | |||
077606c057 | |||
a615f93060 | |||
c562657f1e | |||
7b3922f8e9 | |||
c14382181f | |||
b2183dfda7 | |||
bb92054c86 | |||
4e4a6eb5d7 | |||
692acbd986 | |||
901901825c | |||
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 |
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
|
32
.gitignore
vendored
32
.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,10 +41,9 @@ stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-restart-helper
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
org.gnome.mutter.wayland.gschema.valid
|
||||
@ -56,19 +52,6 @@ testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
m4/*
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-attached
|
||||
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]
|
||||
@ -84,6 +67,7 @@ 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}
|
||||
|
34
NEWS
34
NEWS
@ -1,3 +1,37 @@
|
||||
3.13.4
|
||||
======
|
||||
* Fix move/resize operations for wayland clients [Marek; #731237]
|
||||
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
|
||||
* Handle keysyms without the XF86 prefix [Owen; #727993]
|
||||
* Add touch gesture support [Carlos]
|
||||
* Fix a deadlock when exiting [Owen; #733068]
|
||||
* Add framework for restarting the compositor with nice visuals
|
||||
[Owen; #733026]
|
||||
* Toggle seat capabilities on VT switch [Carlos; #733563]
|
||||
* Misc bug fixes [Florian, Owen; #732695, #732350]
|
||||
|
||||
Contributors:
|
||||
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
|
||||
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
|
||||
Enrico Nicoletto [pt_BR]
|
||||
|
||||
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]
|
||||
|
@ -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) || {
|
||||
|
56
configure.ac
56
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], [2])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
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()
|
||||
@ -70,13 +72,19 @@ CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gio-2.0 >= 2.25.10
|
||||
gio-unix-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
xcursor
|
||||
$CLUTTER_PACKAGE >= 1.19.5
|
||||
clutter-wayland-1.0
|
||||
clutter-wayland-compositor-1.0
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
libinput
|
||||
wayland-server >= 1.4.93
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
@ -107,26 +115,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)
|
||||
|
||||
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)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@ -191,15 +185,12 @@ 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 >= 1.4.93"
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
|
||||
@ -299,17 +290,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])
|
||||
@ -392,6 +372,7 @@ changequote([,])dnl
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
doc/Makefile
|
||||
doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
@ -399,6 +380,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 |
@ -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,9 +21,6 @@ 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/resizepopup.c
|
||||
src/ui/theme.c
|
||||
|
@ -1,2 +1 @@
|
||||
src/metacity.schemas.in
|
||||
src/mutter-wayland.desktop.in
|
||||
data/mutter-wayland.desktop.in
|
||||
|
1283
po/pt_BR.po
1283
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@ -5,38 +5,37 @@ 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 \
|
||||
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
|
||||
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
|
||||
$(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 \
|
||||
@ -155,6 +154,8 @@ libmutter_la_SOURCES = \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/meta-gesture-tracker.c \
|
||||
core/meta-gesture-tracker-private.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@ -166,6 +167,7 @@ libmutter_la_SOURCES = \
|
||||
core/screen-private.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/restart.c \
|
||||
core/stack.c \
|
||||
core/stack.h \
|
||||
core/stack-tracker.c \
|
||||
@ -194,6 +196,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 \
|
||||
@ -223,6 +227,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 \
|
||||
@ -256,7 +262,7 @@ 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 \
|
||||
@ -285,6 +291,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 = \
|
||||
@ -293,14 +306,21 @@ 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
|
||||
|
||||
libexec_PROGRAMS = mutter-restart-helper
|
||||
mutter_restart_helper_SOURCES = core/restart-helper.c
|
||||
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
|
||||
@ -324,7 +344,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 \
|
||||
@ -344,53 +364,19 @@ 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 \
|
||||
|
@ -103,14 +103,6 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_class_init (MetaBackendClass *klass)
|
||||
{
|
||||
@ -122,7 +114,6 @@ meta_backend_class_init (MetaBackendClass *klass)
|
||||
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
|
||||
klass->grab_device = meta_backend_real_grab_device;
|
||||
klass->ungrab_device = meta_backend_real_ungrab_device;
|
||||
klass->warp_pointer = meta_backend_real_warp_pointer;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -23,8 +23,6 @@
|
||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <wayland-server.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
@ -32,7 +30,6 @@
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
MetaCursorRenderer *renderer;
|
||||
|
||||
gboolean is_showing;
|
||||
|
@ -44,9 +44,6 @@
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
@ -60,10 +57,12 @@ static guint signals[LAST_SIGNAL];
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
@ -97,6 +96,9 @@ sync_cursor (MetaCursorTracker *tracker)
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
@ -129,47 +131,9 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
meta_cursor_tracker_new (void)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->pointer.cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self, 0, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
meta_cursor_tracker_new (MetaScreen *screen)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
return make_x11_cursor_tracker (screen);
|
||||
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *_cursor_tracker;
|
||||
@ -186,7 +150,7 @@ MetaCursorTracker *
|
||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
{
|
||||
if (!_cursor_tracker)
|
||||
_cursor_tracker = meta_cursor_tracker_new (screen);
|
||||
_cursor_tracker = meta_cursor_tracker_new ();
|
||||
|
||||
return _cursor_tracker;
|
||||
}
|
||||
@ -207,12 +171,13 @@ gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
@ -243,6 +208,7 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
|
||||
static void
|
||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorImage *cursor_image;
|
||||
CoglTexture2D *sprite;
|
||||
guint8 *cursor_data;
|
||||
@ -252,7 +218,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
if (tracker->xfixes_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
cursor_image = XFixesGetCursorImage (display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
|
@ -60,7 +60,7 @@ typedef struct {
|
||||
gboolean enabled;
|
||||
MetaRectangle rect;
|
||||
float refresh_rate;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
@ -656,20 +656,20 @@ handle_text (GMarkupParseContext *context,
|
||||
else if (strcmp (parser->output_field, "rotation") == 0)
|
||||
{
|
||||
if (strncmp (text, "normal", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
else if (strncmp (text, "left", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_90;
|
||||
else if (strncmp (text, "upside_down", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_180;
|
||||
else if (strncmp (text, "right", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_270;
|
||||
else
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"Invalid rotation type %.*s", (int)text_len, text);
|
||||
}
|
||||
else if (strcmp (parser->output_field, "reflect_x") == 0)
|
||||
parser->output.transform += read_bool (text, text_len, error) ?
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
|
||||
META_MONITOR_TRANSFORM_FLIPPED : 0;
|
||||
else if (strcmp (parser->output_field, "reflect_y") == 0)
|
||||
{
|
||||
/* FIXME (look at the rotation map in monitor.c) */
|
||||
@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].is_primary = TRUE;
|
||||
|
||||
return ret;
|
||||
@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].is_primary = FALSE;
|
||||
ret->outputs[j].is_presentation = FALSE;
|
||||
}
|
||||
@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = (output == primary);
|
||||
|
||||
/* Disable outputs that would go beyond framebuffer limits */
|
||||
@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = TRUE;
|
||||
}
|
||||
else
|
||||
@ -1512,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
output->rect.x,
|
||||
output->rect.y,
|
||||
rotation_map[output->transform & 0x3],
|
||||
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->is_primary ? "yes" : "no",
|
||||
output->is_presentation ? "yes" : "no");
|
||||
}
|
||||
@ -1621,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
enum wl_output_transform transform,
|
||||
MetaOutput *output)
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
MetaMonitorTransform transform,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "meta-monitor-manager-dummy.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
struct _MetaMonitorManagerDummy
|
||||
{
|
||||
@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
manager->crtcs[0].rect.width = manager->modes[0].width;
|
||||
manager->crtcs[0].rect.height = manager->modes[0].height;
|
||||
manager->crtcs[0].current_mode = &manager->modes[0];
|
||||
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
||||
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
|
||||
manager->crtcs[0].is_dirty = FALSE;
|
||||
manager->crtcs[0].logical_monitor = NULL;
|
||||
|
||||
@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
manager->n_outputs = 1;
|
||||
|
||||
manager->outputs[0].crtc = &manager->crtcs[0];
|
||||
manager->outputs[0].output_id = 1;
|
||||
manager->outputs[0].winsys_id = 1;
|
||||
manager->outputs[0].name = g_strdup ("LVDS");
|
||||
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
|
||||
manager->outputs[0].product = g_strdup ("unknown");
|
||||
|
@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
*/
|
||||
info.is_presentation = TRUE;
|
||||
info.in_fullscreen = -1;
|
||||
info.output_id = 0;
|
||||
info.winsys_id = 0;
|
||||
|
||||
g_array_append_val (monitor_infos, info);
|
||||
|
||||
@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
info->is_primary = info->is_primary || output->is_primary;
|
||||
info->is_presentation = info->is_presentation && output->is_presentation;
|
||||
|
||||
if (output->is_primary || info->output_id == 0)
|
||||
info->output_id = output->output_id;
|
||||
if (output->is_primary || info->winsys_id == 0)
|
||||
info->winsys_id = output->winsys_id;
|
||||
|
||||
if (info->is_primary)
|
||||
manager->primary_monitor_index = info->number;
|
||||
@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
GVariantBuilder transforms;
|
||||
|
||||
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
|
||||
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
|
||||
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
|
||||
if (crtc->all_transforms & (1 << j))
|
||||
g_variant_builder_add (&transforms, "u", j);
|
||||
|
||||
@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->output_id,
|
||||
(gint64)output->winsys_id,
|
||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||
&crtcs,
|
||||
output->name,
|
||||
@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
int new_mode, x, y;
|
||||
int new_screen_width, new_screen_height;
|
||||
guint transform;
|
||||
guint output_id;
|
||||
guint output_index;
|
||||
GPtrArray *crtc_infos, *output_infos;
|
||||
|
||||
if (serial != manager->serial)
|
||||
@ -694,7 +694,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
MetaOutput *first_output;
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
guint output_id;
|
||||
|
||||
crtc_info = g_slice_new (MetaCRTCInfo);
|
||||
crtc_info->outputs = g_ptr_array_new ();
|
||||
@ -756,8 +755,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->y = 0;
|
||||
}
|
||||
|
||||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
|
||||
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
|
||||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
|
||||
((crtc->all_transforms & (1 << transform)) == 0))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
@ -768,18 +767,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->transform = transform;
|
||||
|
||||
first_output = NULL;
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (!output_can_config (output, crtc, mode))
|
||||
{
|
||||
@ -824,12 +823,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
g_variant_iter_init (&output_iter, outputs);
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
|
||||
{
|
||||
MetaOutputInfo *output_info;
|
||||
gboolean primary, presentation;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
@ -838,7 +837,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
output_info = g_slice_new0 (MetaOutputInfo);
|
||||
output_info->output = &manager->outputs[output_id];
|
||||
output_info->output = &manager->outputs[output_index];
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary))
|
||||
output_info->is_primary = primary;
|
||||
@ -909,7 +908,7 @@ static gboolean
|
||||
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
guint serial,
|
||||
guint output_id,
|
||||
guint output_index,
|
||||
gint value)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
|
||||
@ -923,14 +922,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (value < 0 || value > 100)
|
||||
{
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-display-config-shared.h"
|
||||
#include "meta-dbus-display-config.h"
|
||||
@ -60,12 +59,23 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
typedef enum {
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
META_MONITOR_TRANSFORM_90,
|
||||
META_MONITOR_TRANSFORM_180,
|
||||
META_MONITOR_TRANSFORM_270,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270,
|
||||
} MetaMonitorTransform;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
MetaCRTC *crtc;
|
||||
/* The low-level ID of this output, used to apply back configuration */
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
char *name;
|
||||
char *vendor;
|
||||
char *product;
|
||||
@ -114,7 +124,7 @@ struct _MetaCRTC
|
||||
glong crtc_id;
|
||||
MetaRectangle rect;
|
||||
MetaMonitorMode *current_mode;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
unsigned int all_transforms;
|
||||
|
||||
/* Only used to build the logical configuration
|
||||
@ -162,14 +172,14 @@ struct _MetaMonitorInfo
|
||||
gboolean in_fullscreen;
|
||||
|
||||
/* The primary or first output for this monitor, 0 if we can't figure out.
|
||||
It can be matched to an output_id of a MetaOutput.
|
||||
It can be matched to a winsys_id of a MetaOutput.
|
||||
|
||||
This is used as an opaque token on reconfiguration when switching from
|
||||
clone to extened, to decide on what output the windows should go next
|
||||
(it's an attempt to keep windows on the same monitor, and preferably on
|
||||
the primary one).
|
||||
*/
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -185,7 +195,7 @@ struct _MetaCRTCInfo {
|
||||
MetaMonitorMode *mode;
|
||||
int x;
|
||||
int y;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
GPtrArray *outputs;
|
||||
};
|
||||
|
||||
@ -339,7 +349,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
static inline gboolean
|
||||
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
|
||||
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
|
||||
{
|
||||
return (transform % 2);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -40,8 +40,6 @@
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
@ -259,7 +257,7 @@ find_output_by_id (MetaOutput *outputs,
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
if (outputs[i].output_id == id)
|
||||
if (outputs[i].winsys_id == id)
|
||||
return &outputs[i];
|
||||
|
||||
return NULL;
|
||||
@ -363,9 +361,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
/* FIXME: implement! */
|
||||
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
if (crtc->mode_valid)
|
||||
{
|
||||
@ -408,7 +406,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
|
||||
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
|
||||
|
||||
meta_output->output_id = connector->connector_id;
|
||||
meta_output->winsys_id = connector->connector_id;
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
@ -491,7 +489,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->crtc = NULL;
|
||||
|
||||
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
||||
meta_output->output_id);
|
||||
meta_output->winsys_id);
|
||||
if (old_output)
|
||||
{
|
||||
meta_output->is_primary = old_output->is_primary;
|
||||
@ -667,7 +665,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
|
||||
if (output_kms->dpms_prop_id != 0)
|
||||
{
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
|
||||
output_kms->dpms_prop_id, state);
|
||||
|
||||
if (ok < 0)
|
||||
@ -748,7 +746,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||
|
||||
connectors[j] = output->output_id;
|
||||
connectors[j] = output->winsys_id;
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
|
@ -51,6 +51,7 @@ struct _MetaBackendX11Private
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
Time latest_evtime;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
@ -71,6 +72,7 @@ static void
|
||||
translate_device_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window stage_window = meta_backend_x11_get_xwindow (x11);
|
||||
|
||||
if (device_event->event != stage_window)
|
||||
@ -88,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
|
||||
@ -117,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:
|
||||
@ -131,10 +151,15 @@ handle_host_xevent (MetaBackend *backend,
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
gboolean bypass_clutter = FALSE;
|
||||
|
||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
bypass_clutter = TRUE;
|
||||
|
||||
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
|
||||
handle_alarm_notify (backend, event);
|
||||
|
||||
@ -142,17 +167,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;
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
|
||||
out:
|
||||
if (!bypass_clutter)
|
||||
clutter_x11_handle_event (event);
|
||||
{
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
clutter_x11_handle_event (event);
|
||||
}
|
||||
|
||||
XFreeEventData (priv->xdisplay, &event->xcookie);
|
||||
}
|
||||
@ -235,6 +257,24 @@ x_event_source_new (MetaBackend *backend)
|
||||
return source;
|
||||
}
|
||||
|
||||
static void
|
||||
take_touch_grab (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { 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 (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||
DefaultRootWindow (priv->xdisplay),
|
||||
False, &mask, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
@ -272,6 +312,8 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
take_touch_grab (backend);
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||
}
|
||||
|
||||
@ -313,6 +355,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);
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "edid.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
/* Look for DPI_FALLBACK in:
|
||||
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
||||
@ -67,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
|
||||
|
||||
static enum wl_output_transform
|
||||
wl_transform_from_xrandr (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr (Rotation rotation)
|
||||
{
|
||||
static const enum wl_output_transform y_reflected_map[4] = {
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
static const MetaMonitorTransform y_reflected_map[4] = {
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
enum wl_output_transform ret;
|
||||
MetaMonitorTransform ret;
|
||||
|
||||
switch (rotation & 0x7F)
|
||||
{
|
||||
default:
|
||||
case RR_Rotate_0:
|
||||
ret = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = META_MONITOR_TRANSFORM_NORMAL;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
ret = WL_OUTPUT_TRANSFORM_90;
|
||||
ret = META_MONITOR_TRANSFORM_90;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
ret = WL_OUTPUT_TRANSFORM_180;
|
||||
ret = META_MONITOR_TRANSFORM_180;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
ret = WL_OUTPUT_TRANSFORM_270;
|
||||
ret = META_MONITOR_TRANSFORM_270;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -105,35 +105,35 @@ wl_transform_from_xrandr (Rotation rotation)
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
|
||||
|
||||
static unsigned int
|
||||
wl_transform_from_xrandr_all (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
/* Handle the common cases first (none or all) */
|
||||
if (rotation == 0 || rotation == RR_Rotate_0)
|
||||
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
return (1 << META_MONITOR_TRANSFORM_NORMAL);
|
||||
|
||||
/* All rotations and one reflection -> all of them by composition */
|
||||
if ((rotation & ALL_ROTATIONS) &&
|
||||
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
|
||||
return ALL_WL_TRANSFORMS;
|
||||
return ALL_TRANSFORMS;
|
||||
|
||||
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
if (rotation & RR_Rotate_90)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_90;
|
||||
if (rotation & RR_Rotate_180)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_180;
|
||||
if (rotation & RR_Rotate_270)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_270;
|
||||
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
|
||||
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
|
||||
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
|
||||
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -150,7 +150,7 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||
&actual_type, &actual_format,
|
||||
@ -186,7 +186,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
@ -211,7 +211,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom);
|
||||
|
||||
if (info == NULL)
|
||||
@ -278,25 +278,25 @@ get_edid_property (Display *dpy,
|
||||
|
||||
static GBytes *
|
||||
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
XID winsys_id)
|
||||
{
|
||||
Atom edid_atom;
|
||||
guint8 *result;
|
||||
gsize len;
|
||||
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (result)
|
||||
@ -312,14 +312,14 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
XID winsys_id)
|
||||
{
|
||||
Atom atom;
|
||||
XRRPropertyInfo *info;
|
||||
gboolean result = FALSE;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, winsys_id,
|
||||
atom);
|
||||
|
||||
if (info)
|
||||
@ -434,8 +434,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
||||
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
|
||||
|
||||
for (j = 0; j < (unsigned)resources->nmode; j++)
|
||||
{
|
||||
@ -467,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
GBytes *edid;
|
||||
MonitorInfo *parsed_edid;
|
||||
|
||||
meta_output->output_id = resources->outputs[i];
|
||||
meta_output->winsys_id = resources->outputs[i];
|
||||
meta_output->name = g_strdup (output->name);
|
||||
|
||||
edid = read_output_edid (manager_xrandr, meta_output->output_id);
|
||||
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
|
||||
if (edid)
|
||||
{
|
||||
gsize len;
|
||||
@ -504,7 +504,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
meta_output->hotplug_mode_update =
|
||||
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
|
||||
output_get_hotplug_mode_update (manager_xrandr, meta_output->winsys_id);
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
@ -556,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
|
||||
}
|
||||
|
||||
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
||||
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
|
||||
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
|
||||
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
|
||||
|
||||
@ -589,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
|
||||
for (k = 0; k < manager->n_outputs; k++)
|
||||
{
|
||||
if (clone == (XID)manager->outputs[k].output_id)
|
||||
if (clone == (XID)manager->outputs[k].winsys_id)
|
||||
{
|
||||
meta_output->possible_clones[j] = &manager->outputs[k];
|
||||
break;
|
||||
@ -605,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
return read_output_edid (manager_xrandr, output->output_id);
|
||||
return read_output_edid (manager_xrandr, output->winsys_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -637,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
static Rotation
|
||||
wl_transform_to_xrandr (enum wl_output_transform transform)
|
||||
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
case META_MONITOR_TRANSFORM_NORMAL:
|
||||
return RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case META_MONITOR_TRANSFORM_90:
|
||||
return RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
case META_MONITOR_TRANSFORM_180:
|
||||
return RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case META_MONITOR_TRANSFORM_270:
|
||||
return RR_Rotate_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED:
|
||||
return RR_Reflect_X | RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
||||
return RR_Reflect_X | RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
||||
return RR_Reflect_X | RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
||||
return RR_Reflect_X | RR_Rotate_270;
|
||||
}
|
||||
|
||||
@ -672,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
@ -828,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output->crtc = crtc;
|
||||
new_controlled_mask |= 1UL << j;
|
||||
|
||||
outputs[j] = output->output_id;
|
||||
outputs[j] = output->winsys_id;
|
||||
}
|
||||
|
||||
if (crtc->current_mode == mode &&
|
||||
@ -847,7 +847,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
manager_xrandr->time,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
meta_monitor_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
|
||||
if (ok != Success)
|
||||
@ -891,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
(XID)output_info->output->winsys_id);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
@ -934,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
|
@ -148,33 +148,6 @@ process_damage (MetaCompositor *compositor,
|
||||
meta_window_actor_process_x11_damage (window_actor, event);
|
||||
}
|
||||
|
||||
static Window
|
||||
get_output_window (MetaCompositor *compositor)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
Window output;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISelectEvents (xdisplay, output, &mask, 1);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/* compat helper */
|
||||
static MetaCompositor *
|
||||
get_compositor_for_screen (MetaScreen *screen)
|
||||
@ -385,6 +358,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 +378,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;
|
||||
@ -486,12 +467,12 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
compositor->stage = meta_stage_new ();
|
||||
clutter_actor_show (compositor->stage);
|
||||
|
||||
wayland_compositor->stage = compositor->stage;
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
clutter_actor_show (compositor->stage);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -510,8 +491,6 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
@ -528,10 +507,16 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
}
|
||||
}
|
||||
|
||||
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
|
||||
after_stage_paint,
|
||||
compositor,
|
||||
NULL);
|
||||
/* We use connect_after() here to accomodate code in GNOME Shell that,
|
||||
* when benchmarking drawing performance, connects to ::after-paint
|
||||
* and calls glFinish(). The timing information from that will be
|
||||
* more accurate if we hold off until that completes before we signal
|
||||
* apps to begin drawing the next frame. If there are no other
|
||||
* connections to ::after-paint, connect() vs. connect_after() doesn't
|
||||
* matter.
|
||||
*/
|
||||
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
|
||||
G_CALLBACK (after_stage_paint), compositor);
|
||||
|
||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
|
||||
|
||||
@ -550,7 +535,8 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->output = get_output_window (compositor);
|
||||
compositor->output = screen->composite_overlay_window;
|
||||
|
||||
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
|
||||
|
||||
meta_empty_stage_input_region (screen);
|
||||
@ -691,12 +677,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
|
||||
@ -756,9 +741,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
{
|
||||
@ -1366,3 +1348,12 @@ meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -374,3 +374,20 @@ meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
|
||||
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);
|
||||
}
|
||||
|
@ -87,5 +87,10 @@ void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
|
||||
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);
|
||||
@ -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);
|
||||
|
@ -109,7 +109,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
}
|
||||
|
||||
static int
|
||||
get_output_scale (int output_id)
|
||||
get_output_scale (int winsys_id)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||
MetaOutput *outputs;
|
||||
@ -120,7 +120,7 @@ get_output_scale (int output_id)
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].output_id == output_id)
|
||||
if (outputs[i].winsys_id == winsys_id)
|
||||
{
|
||||
output_scale = outputs[i].scale;
|
||||
break;
|
||||
@ -150,7 +150,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
|
||||
|
||||
/* 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);
|
||||
output_scale = get_output_scale (window->monitor->winsys_id);
|
||||
|
||||
return (double)output_scale / (double)priv->surface->scale;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -36,6 +36,12 @@
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
typedef enum {
|
||||
INITIALLY_FROZEN,
|
||||
DRAWING_FIRST_FRAME,
|
||||
EMITTED_FIRST_FRAME
|
||||
} FirstFrameState;
|
||||
|
||||
struct _MetaWindowActorPrivate
|
||||
{
|
||||
MetaWindow *window;
|
||||
@ -104,6 +110,7 @@ struct _MetaWindowActorPrivate
|
||||
guint no_shadow : 1;
|
||||
|
||||
guint updates_frozen : 1;
|
||||
guint first_frame_state : 2; /* FirstFrameState */
|
||||
};
|
||||
|
||||
typedef struct _FrameData FrameData;
|
||||
@ -115,6 +122,14 @@ struct _FrameData
|
||||
gint64 frame_drawn_time;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FIRST_FRAME,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_META_WINDOW = 1,
|
||||
@ -181,6 +196,31 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
|
||||
actor_class->paint = meta_window_actor_paint;
|
||||
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
|
||||
|
||||
/**
|
||||
* MetaWindowActor::first-frame:
|
||||
* @actor: the #MetaWindowActor instance
|
||||
*
|
||||
* The ::first-frame signal will be emitted the first time a frame
|
||||
* of window contents has been drawn by the application and Mutter
|
||||
* has had the chance to drawn that frame to the screen. If the
|
||||
* window starts off initially hidden, obscured, or on on a
|
||||
* different workspace, the ::first-frame signal will be emitted
|
||||
* even though the user doesn't see the contents.
|
||||
*
|
||||
* MetaDisplay::window-created is a good place to connect to this
|
||||
* signal - at that point, the MetaWindowActor for the window
|
||||
* exists, but the window has reliably not yet been drawn.
|
||||
* Connecting to an existing window that has already been drawn to
|
||||
* the screen is not useful.
|
||||
*/
|
||||
signals[FIRST_FRAME] =
|
||||
g_signal_new ("first-frame",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
pspec = g_param_spec_object ("meta-window",
|
||||
"MetaWindow",
|
||||
"The displayed MetaWindow",
|
||||
@ -306,6 +346,9 @@ meta_window_actor_thaw (MetaWindowActor *self)
|
||||
if (priv->freeze_count > 0)
|
||||
return;
|
||||
|
||||
if (priv->first_frame_state == INITIALLY_FROZEN)
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
if (priv->surface)
|
||||
meta_surface_actor_set_frozen (priv->surface, FALSE);
|
||||
|
||||
@ -348,6 +391,9 @@ set_surface (MetaWindowActor *self,
|
||||
* frozen as well... */
|
||||
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
|
||||
|
||||
if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
}
|
||||
@ -746,9 +792,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;
|
||||
@ -851,7 +899,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
|
||||
if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc)
|
||||
{
|
||||
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
|
||||
break;
|
||||
@ -1150,7 +1198,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 */
|
||||
@ -1324,7 +1372,12 @@ 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 (is_frozen (self))
|
||||
priv->first_frame_state = INITIALLY_FROZEN;
|
||||
else
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
/* 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.
|
||||
@ -1908,6 +1961,12 @@ meta_window_actor_post_paint (MetaWindowActor *self)
|
||||
do_send_frame_drawn (self, priv->frames->data);
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
}
|
||||
|
||||
if (priv->first_frame_state == DRAWING_FIRST_FRAME)
|
||||
{
|
||||
priv->first_frame_state = EMITTED_FIRST_FRAME;
|
||||
g_signal_emit (self, signals[FIRST_FRAME], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2020,7 +2079,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)
|
||||
{
|
||||
@ -2037,3 +2096,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
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -404,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"
|
||||
@ -613,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,
|
||||
@ -626,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,
|
||||
@ -645,7 +620,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
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,
|
||||
|
@ -392,6 +392,22 @@ meta_core_show_window_menu (Display *xdisplay,
|
||||
meta_window_show_menu (window, menu, root_x, root_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_show_window_menu_for_rect (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
meta_window_show_menu_for_rect (window, menu, rect);
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
Window xroot,
|
||||
@ -479,46 +495,5 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
||||
void
|
||||
meta_invalidate_default_icons (void)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
GSList *windows;
|
||||
GSList *l;
|
||||
|
||||
if (display == NULL)
|
||||
return; /* We can validly be called before the display is opened. */
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
for (l = windows; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = (MetaWindow*)l->data;
|
||||
|
||||
if (window->icon_cache.origin == USING_FALLBACK_ICON)
|
||||
{
|
||||
meta_icon_cache_free (&(window->icon_cache));
|
||||
meta_window_update_icon_now (window);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
XIEventMask *mask)
|
||||
{
|
||||
XIEventMask *prev;
|
||||
gint n_masks, i, j;
|
||||
|
||||
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
|
||||
|
||||
for (i = 0; i < n_masks; i++)
|
||||
{
|
||||
if (prev[i].deviceid != XIAllMasterDevices)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MIN (mask->mask_len, prev[i].mask_len); j++)
|
||||
mask->mask[j] |= prev[i].mask[j];
|
||||
}
|
||||
|
||||
XFree (prev);
|
||||
/* XXX: Actually invalidate the icons when they're used. */
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
/* Don't include core headers here */
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -138,6 +139,12 @@ void meta_core_show_window_menu (Display *xdisplay,
|
||||
int root_y,
|
||||
guint32 timestamp);
|
||||
|
||||
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,
|
||||
MetaGrabOp op,
|
||||
@ -162,8 +169,4 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
|
||||
void meta_invalidate_default_icons (void);
|
||||
|
||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
XIEventMask *mask);
|
||||
|
||||
#endif
|
||||
|
@ -37,8 +37,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
static void
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/display.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "meta-gesture-tracker-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/barrier.h>
|
||||
#include <clutter/clutter.h>
|
||||
@ -145,8 +146,6 @@ struct _MetaDisplay
|
||||
GHashTable *xids;
|
||||
GHashTable *wayland_windows;
|
||||
|
||||
int server_grab_count;
|
||||
|
||||
/* serials of leave/unmap events that may
|
||||
* correspond to an enter event we should
|
||||
* ignore
|
||||
@ -181,7 +180,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;
|
||||
@ -254,6 +252,8 @@ struct _MetaDisplay
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
MetaGestureTracker *gesture_tracker;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
@ -312,8 +312,6 @@ struct _MetaDisplayClass
|
||||
gboolean meta_display_open (void);
|
||||
void meta_display_close (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
void meta_display_grab (MetaDisplay *display);
|
||||
void meta_display_ungrab (MetaDisplay *display);
|
||||
|
||||
void meta_display_unmanage_windows_for_screen (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@ -443,4 +441,16 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
|
||||
guint32 *timestamp);
|
||||
|
||||
void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_show_restart_message (MetaDisplay *display,
|
||||
const char *message);
|
||||
gboolean meta_display_request_restart (MetaDisplay *display);
|
||||
|
||||
void meta_restart_init (void);
|
||||
void meta_restart_finish (void);
|
||||
|
||||
#endif
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
@ -70,7 +71,6 @@
|
||||
#include "x11/xprops.h"
|
||||
|
||||
#include "wayland/meta-xwayland-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
/*
|
||||
* SECTION:pings
|
||||
@ -117,6 +117,8 @@ enum
|
||||
WINDOW_MARKED_URGENT,
|
||||
GRAB_OP_BEGIN,
|
||||
GRAB_OP_END,
|
||||
SHOW_RESTART_MESSAGE,
|
||||
RESTART,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -269,6 +271,59 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
META_TYPE_WINDOW,
|
||||
META_TYPE_GRAB_OP);
|
||||
|
||||
/**
|
||||
* MetaDisplay::show-restart-message:
|
||||
* @display: the #MetaDisplay instance
|
||||
* @message: (allow-none): The message to display, or %NULL
|
||||
* to clear a previous restart message.
|
||||
*
|
||||
* The ::show-restart-message signal will be emitted to indicate
|
||||
* that the compositor should show a message during restart. This is
|
||||
* emitted when meta_restart() is called, either by Mutter
|
||||
* internally or by the embedding compositor. The message should be
|
||||
* immediately added to the Clutter stage in its final form -
|
||||
* ::restart will be emitted to exit the application and leave the
|
||||
* stage contents frozen as soon as the the stage is painted again.
|
||||
*
|
||||
* On case of failure to restart, this signal will be emitted again
|
||||
* with %NULL for @message.
|
||||
*
|
||||
* Returns: %TRUE means the message was added to the stage; %FALSE
|
||||
* indicates that the compositor did not show the message.
|
||||
*/
|
||||
display_signals[SHOW_RESTART_MESSAGE] =
|
||||
g_signal_new ("show-restart-message",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
g_signal_accumulator_true_handled,
|
||||
NULL, NULL,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
/**
|
||||
* MetaDisplay::restart:
|
||||
* @display: the #MetaDisplay instance
|
||||
*
|
||||
* The ::restart signal is emitted to indicate that compositor
|
||||
* should reexec the process. This is
|
||||
* emitted when meta_restart() is called, either by Mutter
|
||||
* internally or by the embedding compositor. See also
|
||||
* ::show-restart-message.
|
||||
*
|
||||
* Returns: %FALSE to indicate that the compositor could not
|
||||
* be restarted. When the compositor is restarted, the signal
|
||||
* should not return.
|
||||
*/
|
||||
display_signals[RESTART] =
|
||||
g_signal_new ("restart",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
g_signal_accumulator_true_handled,
|
||||
NULL, NULL,
|
||||
G_TYPE_BOOLEAN, 0);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOCUS_WINDOW,
|
||||
g_param_spec_object ("focus-window",
|
||||
@ -295,16 +350,9 @@ ping_data_free (MetaPingData *ping_data)
|
||||
g_free (ping_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove_pending_pings_for_window:
|
||||
* @display: The display the window appears on
|
||||
* @xwindow: The X ID of the window whose pings we should remove
|
||||
*
|
||||
* Frees every pending ping structure for the given X window on the
|
||||
* given display. This means that we also destroy the timeouts.
|
||||
*/
|
||||
static void
|
||||
remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
|
||||
void
|
||||
meta_display_remove_pending_pings_for_window (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
GSList *tmp;
|
||||
GSList *dead;
|
||||
@ -317,7 +365,7 @@ remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
|
||||
{
|
||||
MetaPingData *ping_data = tmp->data;
|
||||
|
||||
if (ping_data->window->xwindow == xwindow)
|
||||
if (ping_data->window == window)
|
||||
dead = g_slist_prepend (dead, ping_data);
|
||||
}
|
||||
|
||||
@ -413,6 +461,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:
|
||||
*
|
||||
@ -426,6 +496,7 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
|
||||
gboolean
|
||||
meta_display_open (void)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Display *xdisplay;
|
||||
MetaScreen *screen;
|
||||
int i;
|
||||
@ -457,224 +528,223 @@ meta_display_open (void)
|
||||
XSynchronize (xdisplay, True);
|
||||
|
||||
g_assert (the_display == NULL);
|
||||
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
|
||||
display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
|
||||
|
||||
the_display->closing = 0;
|
||||
display->closing = 0;
|
||||
|
||||
/* here we use XDisplayName which is what the user
|
||||
* probably put in, vs. DisplayString(display) which is
|
||||
* canonicalized by XOpenDisplay()
|
||||
*/
|
||||
the_display->name = g_strdup (XDisplayName (NULL));
|
||||
the_display->xdisplay = xdisplay;
|
||||
the_display->server_grab_count = 0;
|
||||
the_display->display_opening = TRUE;
|
||||
display->name = g_strdup (XDisplayName (NULL));
|
||||
display->xdisplay = xdisplay;
|
||||
display->display_opening = TRUE;
|
||||
|
||||
the_display->pending_pings = NULL;
|
||||
the_display->autoraise_timeout_id = 0;
|
||||
the_display->autoraise_window = NULL;
|
||||
the_display->focus_window = NULL;
|
||||
the_display->focus_serial = 0;
|
||||
the_display->server_focus_window = None;
|
||||
the_display->server_focus_serial = 0;
|
||||
display->pending_pings = NULL;
|
||||
display->autoraise_timeout_id = 0;
|
||||
display->autoraise_window = NULL;
|
||||
display->focus_window = NULL;
|
||||
display->focus_serial = 0;
|
||||
display->server_focus_window = None;
|
||||
display->server_focus_serial = 0;
|
||||
|
||||
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
||||
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
|
||||
display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
||||
display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
|
||||
terminal has the focus */
|
||||
|
||||
meta_bell_init (the_display);
|
||||
meta_bell_init (display);
|
||||
|
||||
meta_display_init_keys (the_display);
|
||||
meta_display_init_keys (display);
|
||||
|
||||
update_window_grab_modifiers (the_display);
|
||||
update_window_grab_modifiers (display);
|
||||
|
||||
meta_prefs_add_listener (prefs_changed_callback, the_display);
|
||||
meta_prefs_add_listener (prefs_changed_callback, display);
|
||||
|
||||
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
|
||||
XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
||||
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
||||
False, atoms);
|
||||
{
|
||||
int i = 0;
|
||||
#define item(x) the_display->atom_##x = atoms[i++];
|
||||
#define item(x) display->atom_##x = atoms[i++];
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
}
|
||||
|
||||
the_display->prop_hooks = NULL;
|
||||
meta_display_init_window_prop_hooks (the_display);
|
||||
the_display->group_prop_hooks = NULL;
|
||||
meta_display_init_group_prop_hooks (the_display);
|
||||
display->prop_hooks = NULL;
|
||||
meta_display_init_window_prop_hooks (display);
|
||||
display->group_prop_hooks = NULL;
|
||||
meta_display_init_group_prop_hooks (display);
|
||||
|
||||
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||
* created in screen_new
|
||||
*/
|
||||
the_display->leader_window = None;
|
||||
the_display->timestamp_pinging_window = None;
|
||||
display->leader_window = None;
|
||||
display->timestamp_pinging_window = None;
|
||||
|
||||
the_display->monitor_cache_invalidated = TRUE;
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
the_display->groups_by_leader = NULL;
|
||||
display->groups_by_leader = NULL;
|
||||
|
||||
the_display->screen = NULL;
|
||||
display->screen = NULL;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
the_display->sn_display = sn_display_new (the_display->xdisplay,
|
||||
display->sn_display = sn_display_new (display->xdisplay,
|
||||
sn_error_trap_push,
|
||||
sn_error_trap_pop);
|
||||
#endif
|
||||
|
||||
/* Get events */
|
||||
meta_display_init_events (the_display);
|
||||
meta_display_init_events (display);
|
||||
|
||||
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
|
||||
display->xids = g_hash_table_new (meta_unsigned_long_hash,
|
||||
meta_unsigned_long_equal);
|
||||
the_display->wayland_windows = g_hash_table_new (NULL, NULL);
|
||||
display->wayland_windows = g_hash_table_new (NULL, NULL);
|
||||
|
||||
i = 0;
|
||||
while (i < N_IGNORED_CROSSING_SERIALS)
|
||||
{
|
||||
the_display->ignored_crossing_serials[i] = 0;
|
||||
display->ignored_crossing_serials[i] = 0;
|
||||
++i;
|
||||
}
|
||||
the_display->ungrab_should_not_cause_focus_window = None;
|
||||
display->ungrab_should_not_cause_focus_window = None;
|
||||
|
||||
the_display->current_time = CurrentTime;
|
||||
the_display->sentinel_counter = 0;
|
||||
display->current_time = CurrentTime;
|
||||
display->sentinel_counter = 0;
|
||||
|
||||
the_display->grab_resize_timeout_id = 0;
|
||||
the_display->grab_have_keyboard = FALSE;
|
||||
display->grab_resize_timeout_id = 0;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
the_display->last_bell_time = 0;
|
||||
display->last_bell_time = 0;
|
||||
#endif
|
||||
|
||||
the_display->grab_op = META_GRAB_OP_NONE;
|
||||
the_display->grab_window = NULL;
|
||||
the_display->grab_tile_mode = META_TILE_NONE;
|
||||
the_display->grab_tile_monitor_number = -1;
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
|
||||
the_display->grab_edge_resistance_data = NULL;
|
||||
display->grab_edge_resistance_data = NULL;
|
||||
|
||||
{
|
||||
int major, minor;
|
||||
|
||||
the_display->have_xsync = FALSE;
|
||||
display->have_xsync = FALSE;
|
||||
|
||||
the_display->xsync_error_base = 0;
|
||||
the_display->xsync_event_base = 0;
|
||||
display->xsync_error_base = 0;
|
||||
display->xsync_event_base = 0;
|
||||
|
||||
/* I don't think we really have to fill these in */
|
||||
major = SYNC_MAJOR_VERSION;
|
||||
minor = SYNC_MINOR_VERSION;
|
||||
|
||||
if (!XSyncQueryExtension (the_display->xdisplay,
|
||||
&the_display->xsync_event_base,
|
||||
&the_display->xsync_error_base) ||
|
||||
!XSyncInitialize (the_display->xdisplay,
|
||||
if (!XSyncQueryExtension (display->xdisplay,
|
||||
&display->xsync_event_base,
|
||||
&display->xsync_error_base) ||
|
||||
!XSyncInitialize (display->xdisplay,
|
||||
&major, &minor))
|
||||
{
|
||||
the_display->xsync_error_base = 0;
|
||||
the_display->xsync_event_base = 0;
|
||||
display->xsync_error_base = 0;
|
||||
display->xsync_event_base = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
the_display->have_xsync = TRUE;
|
||||
XSyncSetPriority (the_display->xdisplay, None, 10);
|
||||
display->have_xsync = TRUE;
|
||||
XSyncSetPriority (display->xdisplay, None, 10);
|
||||
}
|
||||
|
||||
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
|
||||
major, minor,
|
||||
the_display->xsync_error_base,
|
||||
the_display->xsync_event_base);
|
||||
display->xsync_error_base,
|
||||
display->xsync_event_base);
|
||||
}
|
||||
|
||||
{
|
||||
the_display->have_shape = FALSE;
|
||||
display->have_shape = FALSE;
|
||||
|
||||
the_display->shape_error_base = 0;
|
||||
the_display->shape_event_base = 0;
|
||||
display->shape_error_base = 0;
|
||||
display->shape_event_base = 0;
|
||||
|
||||
if (!XShapeQueryExtension (the_display->xdisplay,
|
||||
&the_display->shape_event_base,
|
||||
&the_display->shape_error_base))
|
||||
if (!XShapeQueryExtension (display->xdisplay,
|
||||
&display->shape_event_base,
|
||||
&display->shape_error_base))
|
||||
{
|
||||
the_display->shape_error_base = 0;
|
||||
the_display->shape_event_base = 0;
|
||||
display->shape_error_base = 0;
|
||||
display->shape_event_base = 0;
|
||||
}
|
||||
else
|
||||
the_display->have_shape = TRUE;
|
||||
display->have_shape = TRUE;
|
||||
|
||||
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
|
||||
the_display->shape_error_base,
|
||||
the_display->shape_event_base);
|
||||
display->shape_error_base,
|
||||
display->shape_event_base);
|
||||
}
|
||||
|
||||
{
|
||||
the_display->have_composite = FALSE;
|
||||
display->have_composite = FALSE;
|
||||
|
||||
the_display->composite_error_base = 0;
|
||||
the_display->composite_event_base = 0;
|
||||
display->composite_error_base = 0;
|
||||
display->composite_event_base = 0;
|
||||
|
||||
if (!XCompositeQueryExtension (the_display->xdisplay,
|
||||
&the_display->composite_event_base,
|
||||
&the_display->composite_error_base))
|
||||
if (!XCompositeQueryExtension (display->xdisplay,
|
||||
&display->composite_event_base,
|
||||
&display->composite_error_base))
|
||||
{
|
||||
the_display->composite_error_base = 0;
|
||||
the_display->composite_event_base = 0;
|
||||
display->composite_error_base = 0;
|
||||
display->composite_event_base = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
the_display->composite_major_version = 0;
|
||||
the_display->composite_minor_version = 0;
|
||||
if (XCompositeQueryVersion (the_display->xdisplay,
|
||||
&the_display->composite_major_version,
|
||||
&the_display->composite_minor_version))
|
||||
display->composite_major_version = 0;
|
||||
display->composite_minor_version = 0;
|
||||
if (XCompositeQueryVersion (display->xdisplay,
|
||||
&display->composite_major_version,
|
||||
&display->composite_minor_version))
|
||||
{
|
||||
the_display->have_composite = TRUE;
|
||||
display->have_composite = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
the_display->composite_major_version = 0;
|
||||
the_display->composite_minor_version = 0;
|
||||
display->composite_major_version = 0;
|
||||
display->composite_minor_version = 0;
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Attempted to init Composite, found error base %d event base %d "
|
||||
"extn ver %d %d\n",
|
||||
the_display->composite_error_base,
|
||||
the_display->composite_event_base,
|
||||
the_display->composite_major_version,
|
||||
the_display->composite_minor_version);
|
||||
display->composite_error_base,
|
||||
display->composite_event_base,
|
||||
display->composite_major_version,
|
||||
display->composite_minor_version);
|
||||
|
||||
the_display->have_damage = FALSE;
|
||||
display->have_damage = FALSE;
|
||||
|
||||
the_display->damage_error_base = 0;
|
||||
the_display->damage_event_base = 0;
|
||||
display->damage_error_base = 0;
|
||||
display->damage_event_base = 0;
|
||||
|
||||
if (!XDamageQueryExtension (the_display->xdisplay,
|
||||
&the_display->damage_event_base,
|
||||
&the_display->damage_error_base))
|
||||
if (!XDamageQueryExtension (display->xdisplay,
|
||||
&display->damage_event_base,
|
||||
&display->damage_error_base))
|
||||
{
|
||||
the_display->damage_error_base = 0;
|
||||
the_display->damage_event_base = 0;
|
||||
display->damage_error_base = 0;
|
||||
display->damage_event_base = 0;
|
||||
}
|
||||
else
|
||||
the_display->have_damage = TRUE;
|
||||
display->have_damage = TRUE;
|
||||
|
||||
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
|
||||
the_display->damage_error_base,
|
||||
the_display->damage_event_base);
|
||||
display->damage_error_base,
|
||||
display->damage_event_base);
|
||||
|
||||
the_display->xfixes_error_base = 0;
|
||||
the_display->xfixes_event_base = 0;
|
||||
display->xfixes_error_base = 0;
|
||||
display->xfixes_event_base = 0;
|
||||
|
||||
if (XFixesQueryExtension (the_display->xdisplay,
|
||||
&the_display->xfixes_event_base,
|
||||
&the_display->xfixes_error_base))
|
||||
if (XFixesQueryExtension (display->xdisplay,
|
||||
&display->xfixes_event_base,
|
||||
&display->xfixes_error_base))
|
||||
{
|
||||
int xfixes_major, xfixes_minor;
|
||||
|
||||
XFixesQueryVersion (the_display->xdisplay, &xfixes_major, &xfixes_minor);
|
||||
XFixesQueryVersion (display->xdisplay, &xfixes_major, &xfixes_minor);
|
||||
|
||||
if (xfixes_major * 100 + xfixes_minor < 500)
|
||||
meta_fatal ("Mutter requires XFixes 5.0");
|
||||
@ -685,21 +755,21 @@ meta_display_open (void)
|
||||
}
|
||||
|
||||
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
|
||||
the_display->xfixes_error_base,
|
||||
the_display->xfixes_event_base);
|
||||
display->xfixes_error_base,
|
||||
display->xfixes_event_base);
|
||||
}
|
||||
|
||||
{
|
||||
int major = 2, minor = 3;
|
||||
gboolean has_xi = FALSE;
|
||||
|
||||
if (XQueryExtension (the_display->xdisplay,
|
||||
if (XQueryExtension (display->xdisplay,
|
||||
"XInputExtension",
|
||||
&the_display->xinput_opcode,
|
||||
&the_display->xinput_error_base,
|
||||
&the_display->xinput_event_base))
|
||||
&display->xinput_opcode,
|
||||
&display->xinput_error_base,
|
||||
&display->xinput_event_base))
|
||||
{
|
||||
if (XIQueryVersion (the_display->xdisplay, &major, &minor) == Success)
|
||||
if (XIQueryVersion (display->xdisplay, &major, &minor) == Success)
|
||||
{
|
||||
int version = (major * 10) + minor;
|
||||
if (version >= 22)
|
||||
@ -707,7 +777,7 @@ meta_display_open (void)
|
||||
|
||||
#ifdef HAVE_XI23
|
||||
if (version >= 23)
|
||||
the_display->have_xinput_23 = TRUE;
|
||||
display->have_xinput_23 = TRUE;
|
||||
#endif /* HAVE_XI23 */
|
||||
}
|
||||
}
|
||||
@ -731,35 +801,35 @@ meta_display_open (void)
|
||||
* this window, so we can't rely on it still being set later. See bug
|
||||
* 354213 for details.
|
||||
*/
|
||||
the_display->leader_window =
|
||||
meta_create_offscreen_window (the_display->xdisplay,
|
||||
DefaultRootWindow (the_display->xdisplay),
|
||||
display->leader_window =
|
||||
meta_create_offscreen_window (display->xdisplay,
|
||||
DefaultRootWindow (display->xdisplay),
|
||||
PropertyChangeMask);
|
||||
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
the_display->atom__NET_WM_NAME,
|
||||
meta_prop_set_utf8_string_hint (display,
|
||||
display->leader_window,
|
||||
display->atom__NET_WM_NAME,
|
||||
net_wm_name);
|
||||
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
the_display->atom__GNOME_WM_KEYBINDINGS,
|
||||
meta_prop_set_utf8_string_hint (display,
|
||||
display->leader_window,
|
||||
display->atom__GNOME_WM_KEYBINDINGS,
|
||||
gnome_wm_keybindings);
|
||||
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
the_display->atom__MUTTER_VERSION,
|
||||
meta_prop_set_utf8_string_hint (display,
|
||||
display->leader_window,
|
||||
display->atom__MUTTER_VERSION,
|
||||
VERSION);
|
||||
|
||||
data[0] = the_display->leader_window;
|
||||
XChangeProperty (the_display->xdisplay,
|
||||
the_display->leader_window,
|
||||
the_display->atom__NET_SUPPORTING_WM_CHECK,
|
||||
data[0] = display->leader_window;
|
||||
XChangeProperty (display->xdisplay,
|
||||
display->leader_window,
|
||||
display->atom__NET_SUPPORTING_WM_CHECK,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
|
||||
XWindowEvent (the_display->xdisplay,
|
||||
the_display->leader_window,
|
||||
XWindowEvent (display->xdisplay,
|
||||
display->leader_window,
|
||||
PropertyChangeMask,
|
||||
&event);
|
||||
|
||||
@ -768,45 +838,52 @@ meta_display_open (void)
|
||||
/* Make it painfully clear that we can't rely on PropertyNotify events on
|
||||
* this window, as per bug 354213.
|
||||
*/
|
||||
XSelectInput(the_display->xdisplay,
|
||||
the_display->leader_window,
|
||||
XSelectInput(display->xdisplay,
|
||||
display->leader_window,
|
||||
NoEventMask);
|
||||
}
|
||||
|
||||
/* Make a little window used only for pinging the server for timestamps; note
|
||||
* that meta_create_offscreen_window already selects for PropertyChangeMask.
|
||||
*/
|
||||
the_display->timestamp_pinging_window =
|
||||
meta_create_offscreen_window (the_display->xdisplay,
|
||||
DefaultRootWindow (the_display->xdisplay),
|
||||
display->timestamp_pinging_window =
|
||||
meta_create_offscreen_window (display->xdisplay,
|
||||
DefaultRootWindow (display->xdisplay),
|
||||
PropertyChangeMask);
|
||||
|
||||
the_display->last_focus_time = timestamp;
|
||||
the_display->last_user_time = timestamp;
|
||||
the_display->compositor = NULL;
|
||||
display->last_focus_time = timestamp;
|
||||
display->last_user_time = timestamp;
|
||||
display->compositor = NULL;
|
||||
|
||||
/* Mutter used to manage all X screens of the display in a single process, but
|
||||
* now it always manages exactly one screen as specified by the DISPLAY
|
||||
* environment variable.
|
||||
*/
|
||||
i = meta_ui_get_screen_number ();
|
||||
screen = meta_screen_new (the_display, i, timestamp);
|
||||
screen = meta_screen_new (display, i, timestamp);
|
||||
|
||||
if (!screen)
|
||||
{
|
||||
/* This would typically happen because all the screens already
|
||||
* have window managers.
|
||||
*/
|
||||
meta_display_close (the_display, timestamp);
|
||||
meta_display_close (display, timestamp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
the_display->screen = screen;
|
||||
display->screen = screen;
|
||||
|
||||
enable_compositor (the_display);
|
||||
meta_screen_init_workspaces (screen);
|
||||
|
||||
enable_compositor (display);
|
||||
|
||||
meta_screen_create_guard_window (screen);
|
||||
|
||||
/* Set up touch support */
|
||||
display->gesture_tracker = meta_gesture_tracker_new ();
|
||||
g_signal_connect (display->gesture_tracker, "state-changed",
|
||||
G_CALLBACK (gesture_tracker_state_changed), display);
|
||||
|
||||
/* We know that if mutter is running as a Wayland compositor,
|
||||
* we start out with no windows.
|
||||
*/
|
||||
@ -818,12 +895,12 @@ meta_display_open (void)
|
||||
int ret_to;
|
||||
|
||||
/* kinda bogus because GetInputFocus has no possible errors */
|
||||
meta_error_trap_push (the_display);
|
||||
meta_error_trap_push (display);
|
||||
|
||||
/* FIXME: This is totally broken; see comment 9 of bug 88194 about this */
|
||||
focus = None;
|
||||
ret_to = RevertToPointerRoot;
|
||||
XGetInputFocus (the_display->xdisplay, &focus, &ret_to);
|
||||
XGetInputFocus (display->xdisplay, &focus, &ret_to);
|
||||
|
||||
/* Force a new FocusIn (does this work?) */
|
||||
|
||||
@ -832,29 +909,29 @@ meta_display_open (void)
|
||||
*/
|
||||
if (focus == None || focus == PointerRoot)
|
||||
/* Just focus the no_focus_window on the first screen */
|
||||
meta_display_focus_the_no_focus_window (the_display,
|
||||
the_display->screen,
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
display->screen,
|
||||
timestamp);
|
||||
else
|
||||
{
|
||||
MetaWindow * window;
|
||||
window = meta_display_lookup_x_window (the_display, focus);
|
||||
window = meta_display_lookup_x_window (display, focus);
|
||||
if (window)
|
||||
meta_display_set_input_focus_window (the_display, window, FALSE, timestamp);
|
||||
meta_display_set_input_focus_window (display, window, FALSE, timestamp);
|
||||
else
|
||||
/* Just focus the no_focus_window on the first screen */
|
||||
meta_display_focus_the_no_focus_window (the_display,
|
||||
the_display->screen,
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
display->screen,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (the_display);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
meta_idle_monitor_init_dbus ();
|
||||
|
||||
/* Done opening new display */
|
||||
the_display->display_opening = FALSE;
|
||||
display->display_opening = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -963,6 +1040,7 @@ meta_display_close (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
g_assert (display != NULL);
|
||||
g_assert (display == the_display);
|
||||
|
||||
if (display->closing != 0)
|
||||
{
|
||||
@ -976,6 +1054,8 @@ meta_display_close (MetaDisplay *display,
|
||||
|
||||
meta_display_remove_autoraise_callback (display);
|
||||
|
||||
g_clear_object (&display->gesture_tracker);
|
||||
|
||||
if (display->focus_timeout_id)
|
||||
g_source_remove (display->focus_timeout_id);
|
||||
display->focus_timeout_id = 0;
|
||||
@ -1020,50 +1100,6 @@ meta_display_close (MetaDisplay *display,
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Grab/ungrab routines taken from fvwm.
|
||||
* Calling this function will cause X to ignore all other clients until
|
||||
* you ungrab. This may not be quite as bad as it sounds, yet there is
|
||||
* agreement that avoiding server grabs except when they are clearly needed
|
||||
* is a good thing.
|
||||
*
|
||||
* If you do use such grabs, please clearly explain the necessity for their
|
||||
* usage in a comment. Try to keep their scope extremely limited. In
|
||||
* particular, try to avoid emitting any signals or notifications while
|
||||
* a grab is active (if the signal receiver tries to block on an X request
|
||||
* from another client at this point, you will have a deadlock).
|
||||
*/
|
||||
void
|
||||
meta_display_grab (MetaDisplay *display)
|
||||
{
|
||||
if (display->server_grab_count == 0)
|
||||
{
|
||||
XGrabServer (display->xdisplay);
|
||||
}
|
||||
display->server_grab_count += 1;
|
||||
meta_verbose ("Grabbing display, grab count now %d\n",
|
||||
display->server_grab_count);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_ungrab (MetaDisplay *display)
|
||||
{
|
||||
if (display->server_grab_count == 0)
|
||||
meta_bug ("Ungrabbed non-grabbed server\n");
|
||||
|
||||
display->server_grab_count -= 1;
|
||||
if (display->server_grab_count == 0)
|
||||
{
|
||||
/* FIXME we want to purge all pending "queued" stuff
|
||||
* at this point, such as window hide/show
|
||||
*/
|
||||
XUngrabServer (display->xdisplay);
|
||||
XFlush (display->xdisplay);
|
||||
}
|
||||
|
||||
meta_verbose ("Ungrabbing display, grab count now %d\n",
|
||||
display->server_grab_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_for_x_display:
|
||||
* @xdisplay: An X display
|
||||
@ -1343,23 +1379,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,
|
||||
@ -1367,7 +1387,7 @@ window_raise_with_delay_callback (void *data)
|
||||
window->desc);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1514,7 +1534,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
|
||||
* we know which is which by making two requests that the server will
|
||||
* process at the same time.
|
||||
*/
|
||||
meta_display_grab (display);
|
||||
XGrabServer (display->xdisplay);
|
||||
|
||||
serial = XNextRequest (display->xdisplay);
|
||||
|
||||
@ -1527,7 +1547,8 @@ request_xserver_input_focus_change (MetaDisplay *display,
|
||||
display->atom__MUTTER_FOCUS_SET,
|
||||
XA_STRING, 8, PropModeAppend, NULL, 0);
|
||||
|
||||
meta_display_ungrab (display);
|
||||
XUngrabServer (display->xdisplay);
|
||||
XFlush (display->xdisplay);
|
||||
|
||||
meta_display_update_focus_window (display,
|
||||
meta_window,
|
||||
@ -1567,9 +1588,6 @@ meta_display_unregister_x_window (MetaDisplay *display,
|
||||
g_return_if_fail (g_hash_table_lookup (display->xids, &xwindow) != NULL);
|
||||
|
||||
g_hash_table_remove (display->xids, &xwindow);
|
||||
|
||||
/* Remove any pending pings */
|
||||
remove_pending_pings_for_window (display, xwindow);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1696,15 +1714,15 @@ meta_display_update_cursor (MetaDisplay *display)
|
||||
}
|
||||
|
||||
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)
|
||||
return window;
|
||||
window = parent;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1752,11 +1770,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_window_is_attached_dialog (window) && meta_grab_op_is_moving (op))
|
||||
grab_window = get_toplevel_transient_for (window);
|
||||
if (meta_grab_op_is_moving (op))
|
||||
grab_window = get_first_freefloating_window (window);
|
||||
|
||||
g_assert (grab_window != NULL);
|
||||
g_assert (op != META_GRAB_OP_NONE);
|
||||
@ -1845,18 +1863,19 @@ void
|
||||
meta_display_end_grab_op (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *grab_window = display->grab_window;
|
||||
MetaGrabOp grab_op = display->grab_op;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
|
||||
"Ending grab op %u at time %u\n", grab_op, timestamp);
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return;
|
||||
|
||||
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
|
||||
display->screen, display->grab_window, display->grab_op);
|
||||
display->screen, grab_window, grab_op);
|
||||
|
||||
meta_window_grab_op_ended (display->grab_window, display->grab_op);
|
||||
|
||||
if (meta_grab_op_is_moving_or_resizing (display->grab_op))
|
||||
if (meta_grab_op_is_moving_or_resizing (grab_op))
|
||||
{
|
||||
/* Clear out the edge cache */
|
||||
meta_display_cleanup_edges (display);
|
||||
@ -1882,7 +1901,7 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ungrabbing all keys timestamp %u\n", timestamp);
|
||||
meta_window_ungrab_all_keys (display->grab_window, timestamp);
|
||||
meta_window_ungrab_all_keys (grab_window, timestamp);
|
||||
}
|
||||
|
||||
display->grab_timestamp = 0;
|
||||
@ -1899,6 +1918,8 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
display->grab_resize_timeout_id = 0;
|
||||
}
|
||||
|
||||
meta_window_grab_op_ended (grab_window, grab_op);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
}
|
||||
@ -2525,21 +2546,19 @@ mru_cmp (gconstpointer a,
|
||||
* meta_display_get_tab_list:
|
||||
* @display: a #MetaDisplay
|
||||
* @type: type of tab list
|
||||
* @screen: a #MetaScreen
|
||||
* @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;
|
||||
@ -2614,7 +2633,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;
|
||||
@ -3169,3 +3188,34 @@ 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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_show_restart_message (MetaDisplay *display,
|
||||
const char *message)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
|
||||
g_signal_emit (display,
|
||||
display_signals[SHOW_RESTART_MESSAGE], 0,
|
||||
message, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_request_restart (MetaDisplay *display)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
|
||||
g_signal_emit (display,
|
||||
display_signals[RESTART], 0,
|
||||
&result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
1800
src/core/events.c
1800
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
|
||||
|
||||
|
@ -26,14 +26,11 @@
|
||||
#include "bell.h"
|
||||
#include <meta/errors.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#define EVENT_MASK (SubstructureRedirectMask | \
|
||||
StructureNotifyMask | SubstructureNotifyMask | \
|
||||
ExposureMask | \
|
||||
ButtonPressMask | ButtonReleaseMask | \
|
||||
PointerMotionMask | PointerMotionHintMask | \
|
||||
EnterWindowMask | LeaveWindowMask | \
|
||||
FocusChangeMask)
|
||||
ExposureMask | FocusChangeMask)
|
||||
|
||||
void
|
||||
meta_window_ensure_frame (MetaWindow *window)
|
||||
@ -109,6 +106,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);
|
||||
@ -150,10 +160,16 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
|
||||
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);
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
/* 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);
|
||||
|
@ -55,8 +55,8 @@
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
|
||||
#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"
|
||||
@ -1194,9 +1194,8 @@ meta_window_change_keygrabs (MetaWindow *window,
|
||||
void
|
||||
meta_window_grab_keys (MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
/* Under Wayland, we don't need to grab at all. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
if (window->all_keys_grabbed)
|
||||
@ -1223,7 +1222,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;
|
||||
@ -1437,7 +1436,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);
|
||||
|
@ -94,26 +94,6 @@ static GMainLoop *meta_main_loop = NULL;
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* log_handler:
|
||||
* @log_domain: the domain the error occurred in (we ignore this)
|
||||
* @log_level: the log level so that we can filter out less
|
||||
* important messages
|
||||
* @message: the message to log
|
||||
* @user_data: arbitrary data (we ignore this)
|
||||
*
|
||||
* Prints log messages. If Mutter was compiled with backtrace support,
|
||||
* also prints a backtrace (see meta_print_backtrace()).
|
||||
*/
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_warning ("Log level %d: %s\n", log_level, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_print_compilation_info:
|
||||
*
|
||||
@ -387,6 +367,8 @@ meta_init (void)
|
||||
meta_clutter_init ();
|
||||
}
|
||||
|
||||
meta_restart_init ();
|
||||
|
||||
/*
|
||||
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
|
||||
* for now.
|
||||
@ -444,24 +426,10 @@ meta_register_with_session (void)
|
||||
int
|
||||
meta_run (void)
|
||||
{
|
||||
const gchar *log_domains[] = {
|
||||
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
|
||||
/* Load prefs */
|
||||
meta_prefs_init ();
|
||||
meta_prefs_add_listener (prefs_changed_callback, NULL);
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
|
||||
g_log_set_handler (log_domains[i],
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler, NULL);
|
||||
|
||||
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
|
||||
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
|
||||
/* Try to find some theme that'll work if the theme preference
|
||||
|
@ -309,9 +309,16 @@ accelerator_parse (const gchar *accelerator,
|
||||
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
|
||||
keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
g_free (with_xf86);
|
||||
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accelerator += len;
|
||||
|
76
src/core/meta-gesture-tracker-private.h
Normal file
76
src/core/meta-gesture-tracker-private.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- 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.
|
||||
*
|
||||
* 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 (void);
|
||||
|
||||
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 */
|
567
src/core/meta-gesture-tracker.c
Normal file
567
src/core/meta-gesture-tracker.c
Normal file
@ -0,0 +1,567 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gesture-tracker
|
||||
* @Title: MetaGestureTracker
|
||||
* @Short_Description: Manages gestures on windows/desktop
|
||||
*
|
||||
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
|
||||
* based on the outcome of those.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "meta-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_0,
|
||||
PROP_AUTODENY_TIMEOUT,
|
||||
LAST_PROP,
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[LAST_PROP];
|
||||
|
||||
enum {
|
||||
STATE_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
#define DEFAULT_AUTODENY_TIMEOUT 150
|
||||
|
||||
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;
|
||||
|
||||
obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
|
||||
"Auto-deny timeout",
|
||||
"Auto-deny timeout",
|
||||
0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
|
||||
|
||||
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;
|
||||
|
||||
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 (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_GESTURE_TRACKER, 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));
|
||||
}
|
@ -1234,6 +1234,7 @@ xsettings_overrides_changed (GSettings *settings,
|
||||
GVariant *value;
|
||||
GVariantDict overrides;
|
||||
int shell_shows_app_menu = 1;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (!g_settings_get_boolean (settings, "active"))
|
||||
goto out;
|
||||
@ -1247,8 +1248,13 @@ xsettings_overrides_changed (GSettings *settings,
|
||||
"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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
82
src/core/restart-helper.c
Normal file
82
src/core/restart-helper.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* SECTION:restart-helper
|
||||
* @short_description: helper program during a restart
|
||||
*
|
||||
* To smoothly restart Mutter, we want to keep the composite
|
||||
* overlay window enabled during the restart. This is done by
|
||||
* spawning this program, which keeps a reference to the the composite
|
||||
* overlay window until Mutter picks it back up.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
Display *display = XOpenDisplay (NULL);
|
||||
Window selection_window;
|
||||
XSetWindowAttributes xwa;
|
||||
unsigned long mask = 0;
|
||||
|
||||
xwa.override_redirect = True;
|
||||
mask |= CWOverrideRedirect;
|
||||
|
||||
|
||||
XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
|
||||
|
||||
selection_window = XCreateWindow (display,
|
||||
DefaultRootWindow (display),
|
||||
-100, -100, 1, 1, 0,
|
||||
0,
|
||||
InputOnly,
|
||||
DefaultVisual (display, DefaultScreen (display)),
|
||||
mask, &xwa);
|
||||
|
||||
XSetSelectionOwner (display,
|
||||
XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
|
||||
selection_window,
|
||||
CurrentTime);
|
||||
|
||||
/* Mutter looks for an (arbitrary) line printed to stdout to know that
|
||||
* we have started and have a reference to the COW. XSync() so that
|
||||
* everything is set on the X server before Mutter starts restarting.
|
||||
*/
|
||||
XSync (display, False);
|
||||
|
||||
printf ("STARTED\n");
|
||||
fflush (stdout);
|
||||
|
||||
while (True)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
XNextEvent (display, &xev);
|
||||
/* Mutter restarted and unset the selection to indicate that
|
||||
* it has a reference on the COW again */
|
||||
if (xev.xany.type == SelectionClear)
|
||||
return 0;
|
||||
}
|
||||
}
|
212
src/core/restart.c
Normal file
212
src/core/restart.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SECTION:restart
|
||||
* @short_description: Smoothly restart the compositor
|
||||
*
|
||||
* There are some cases where we need to restart Mutter in order
|
||||
* to deal with changes in state - the particular case inspiring
|
||||
* this is enabling or disabling stereo output. To make this
|
||||
* fairly smooth for the user, we need to do two things:
|
||||
*
|
||||
* - Display a message to the user and make sure that it is
|
||||
* actually painted before we exit.
|
||||
* - Use a helper program so that the Composite Overlay Window
|
||||
* isn't unmapped and mapped.
|
||||
*
|
||||
* This handles both of these.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <gio/gunixinputstream.h>
|
||||
|
||||
#include <meta/main.h>
|
||||
#include "ui.h"
|
||||
#include "util-private.h"
|
||||
#include "display-private.h"
|
||||
|
||||
static gboolean restart_helper_started = FALSE;
|
||||
static gboolean restart_message_shown = FALSE;
|
||||
static gboolean is_restart = FALSE;
|
||||
|
||||
void
|
||||
meta_restart_init (void)
|
||||
{
|
||||
Display *xdisplay = meta_ui_get_display ();
|
||||
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
|
||||
Window restart_helper_window = None;
|
||||
|
||||
restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
|
||||
if (restart_helper_window)
|
||||
is_restart = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
restart_check_ready (void)
|
||||
{
|
||||
if (restart_helper_started && restart_message_shown)
|
||||
meta_display_request_restart (meta_get_display ());
|
||||
}
|
||||
|
||||
static void
|
||||
restart_helper_read_line_callback (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gsize length;
|
||||
char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
|
||||
res,
|
||||
&length, &error);
|
||||
if (line == NULL)
|
||||
{
|
||||
meta_warning ("Failed to read output from restart helper%s%s\n",
|
||||
error ? ": " : NULL,
|
||||
error ? error->message : NULL);
|
||||
}
|
||||
else
|
||||
g_free (line); /* We don't actually care what the restart helper outputs */
|
||||
|
||||
g_object_unref (source_object);
|
||||
|
||||
restart_helper_started = TRUE;
|
||||
restart_check_ready ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
restart_message_painted (gpointer data)
|
||||
{
|
||||
restart_message_shown = TRUE;
|
||||
restart_check_ready ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_restart:
|
||||
* @message: message to display to the user.
|
||||
*
|
||||
* Starts the process of restarting the compositor. Note that Mutter's
|
||||
* involvement here is to make the restart visually smooth for the
|
||||
* user - it cannot itself safely reexec a program that embeds libmuttter.
|
||||
* So in order for this to work, the compositor must handle two
|
||||
* signals - MetaDisplay::show-restart-message, to display the
|
||||
* message passed here on the Clutter stage, and ::restart to actually
|
||||
* reexec the compositor.
|
||||
*/
|
||||
void
|
||||
meta_restart (const char *message)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display();
|
||||
GInputStream *unix_stream;
|
||||
GDataInputStream *data_stream;
|
||||
GError *error = NULL;
|
||||
int helper_out_fd;
|
||||
|
||||
static const char * const helper_argv[] = {
|
||||
MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
|
||||
};
|
||||
|
||||
if (meta_display_show_restart_message (display, message))
|
||||
{
|
||||
/* Wait until the stage was painted */
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
restart_message_painted,
|
||||
NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Can't show the message, show the message as soon as the
|
||||
* restart helper starts
|
||||
*/
|
||||
restart_message_painted (NULL);
|
||||
}
|
||||
|
||||
/* We also need to wait for the restart helper to get its
|
||||
* reference to the Composite Overlay Window.
|
||||
*/
|
||||
if (!g_spawn_async_with_pipes (NULL, /* working directory */
|
||||
(char **)helper_argv,
|
||||
NULL, /* envp */
|
||||
G_SPAWN_DEFAULT,
|
||||
NULL, NULL, /* child_setup */
|
||||
NULL, /* child_pid */
|
||||
NULL, /* standard_input */
|
||||
&helper_out_fd,
|
||||
NULL, /* standard_error */
|
||||
&error))
|
||||
{
|
||||
meta_warning ("Failed to start restart helper: %s\n", error->message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
|
||||
data_stream = g_data_input_stream_new (unix_stream);
|
||||
g_object_unref (unix_stream);
|
||||
|
||||
g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
|
||||
NULL, restart_helper_read_line_callback,
|
||||
&error);
|
||||
if (error != NULL)
|
||||
{
|
||||
meta_warning ("Failed to read from restart helper: %s\n", error->message);
|
||||
g_object_unref (data_stream);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
/* If starting the restart helper fails, then we just go ahead and restart
|
||||
* immediately. We won't get a smooth transition, since the overlay window
|
||||
* will be destroyed and recreated, but otherwise it will work fine.
|
||||
*/
|
||||
restart_helper_started = TRUE;
|
||||
restart_check_ready ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
meta_restart_finish (void)
|
||||
{
|
||||
if (is_restart)
|
||||
{
|
||||
Display *xdisplay = meta_display_get_xdisplay (meta_get_display ());
|
||||
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
|
||||
XSetSelectionOwner (xdisplay, atom_restart_helper, None, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_is_restart:
|
||||
*
|
||||
* Returns %TRUE if this instance of Mutter comes from Mutter
|
||||
* restarting itself (for example to enable/disable stereo.)
|
||||
* See meta_restart(). If this is the case, any startup visuals
|
||||
* or animations should be suppressed.
|
||||
*/
|
||||
gboolean
|
||||
meta_is_restart (void)
|
||||
{
|
||||
return is_restart;
|
||||
}
|
@ -119,6 +119,8 @@ struct _MetaScreen
|
||||
* and restack them below a guard window. When using a compositor
|
||||
* this allows us to provide live previews of unmapped windows */
|
||||
Window guard_window;
|
||||
|
||||
Window composite_overlay_window;
|
||||
};
|
||||
|
||||
struct _MetaScreenClass
|
||||
@ -135,6 +137,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,
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <locale.h>
|
||||
@ -55,6 +56,8 @@
|
||||
#include "x11/window-x11.h"
|
||||
#include "x11/xprops.h"
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
static char* get_screen_name (MetaDisplay *display,
|
||||
int number);
|
||||
|
||||
@ -469,13 +472,24 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
XStoreName (xdisplay, guard_window, "mutter guard window");
|
||||
|
||||
{
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
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);
|
||||
XISelectEvents (xdisplay, guard_window, &mask, 1);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
|
||||
/* Sync on the connection we created the window on to
|
||||
* make sure it's created before we select on it on the
|
||||
* backend connection. */
|
||||
XSync (xdisplay, False);
|
||||
|
||||
XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
|
||||
}
|
||||
}
|
||||
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
@ -492,6 +506,15 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
return guard_window;
|
||||
}
|
||||
|
||||
/* Set a black background on the root window so that we don't
|
||||
* see confusing old copies of old windows when debugging
|
||||
* and testing. */
|
||||
static void
|
||||
meta_screen_set_background (MetaScreen *screen)
|
||||
{
|
||||
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
|
||||
}
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
@ -506,7 +529,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 ();
|
||||
@ -612,24 +634,15 @@ meta_screen_new (MetaDisplay *display,
|
||||
/* select our root window events */
|
||||
meta_error_trap_push (display);
|
||||
|
||||
/* We need to or with the existing event mask since
|
||||
* gtk+ may be interested in other events.
|
||||
*/
|
||||
{
|
||||
long event_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
XWindowAttributes attr;
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, xroot, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
#ifdef HAVE_XI23
|
||||
if (META_DISPLAY_HAS_XINPUT_23 (display))
|
||||
{
|
||||
@ -641,9 +654,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
|
||||
event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
StructureNotifyMask | ColormapChangeMask | PropertyChangeMask);
|
||||
if (XGetWindowAttributes (xdisplay, xroot, &attr))
|
||||
event_mask |= attr.your_event_mask;
|
||||
|
||||
XSelectInput (xdisplay, xroot, event_mask);
|
||||
}
|
||||
|
||||
@ -657,6 +667,9 @@ meta_screen_new (MetaDisplay *display,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Select for cursor changes so the cursor tracker is up to date. */
|
||||
XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
|
||||
|
||||
screen = g_object_new (META_TYPE_SCREEN, NULL);
|
||||
screen->closing = 0;
|
||||
|
||||
@ -697,9 +710,16 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->starting_corner = META_SCREEN_TOPLEFT;
|
||||
screen->guard_window = None;
|
||||
|
||||
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
|
||||
|
||||
/* Now that we've gotten taken a reference count on the COW, we
|
||||
* can close the helper that is holding on to it */
|
||||
meta_restart_finish ();
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
meta_screen_set_background (screen);
|
||||
|
||||
/* Handle creating a no_focus_window for this screen */
|
||||
screen->no_focus_window =
|
||||
@ -721,24 +741,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);
|
||||
@ -764,23 +770,47 @@ 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");
|
||||
|
||||
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);
|
||||
else
|
||||
meta_workspace_activate (screen->workspaces->data, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_free (MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
@ -791,8 +821,6 @@ meta_screen_free (MetaScreen *screen,
|
||||
|
||||
screen->closing += 1;
|
||||
|
||||
meta_display_grab (display);
|
||||
|
||||
meta_compositor_unmanage (screen->display->compositor);
|
||||
|
||||
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
|
||||
@ -849,9 +877,6 @@ meta_screen_free (MetaScreen *screen,
|
||||
g_free (screen->screen_name);
|
||||
|
||||
g_object_unref (screen);
|
||||
|
||||
XFlush (display->xdisplay);
|
||||
meta_display_ungrab (display);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -235,31 +235,35 @@ meta_stack_op_dump (MetaStackOp *op,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_tracker_dump (MetaStackTracker *tracker)
|
||||
stack_dump (GArray *stack)
|
||||
{
|
||||
guint i;
|
||||
|
||||
meta_push_no_msg_prefix ();
|
||||
for (i = 0; i < stack->len; i++)
|
||||
{
|
||||
MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i);
|
||||
char *window_id = get_window_id (window);
|
||||
meta_topic (META_DEBUG_STACK, " %s", window_id);
|
||||
g_free (window_id);
|
||||
}
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
meta_pop_no_msg_prefix ();
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_tracker_dump (MetaStackTracker *tracker)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "MetaStackTracker state (screen=%d)\n", tracker->screen->number);
|
||||
meta_push_no_msg_prefix ();
|
||||
meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial);
|
||||
meta_topic (META_DEBUG_STACK, " xserver_stack: ");
|
||||
for (i = 0; i < tracker->xserver_stack->len; i++)
|
||||
{
|
||||
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
|
||||
char *window_id = get_window_id (window);
|
||||
meta_topic (META_DEBUG_STACK, " %s", window_id);
|
||||
g_free (window_id);
|
||||
}
|
||||
meta_topic (META_DEBUG_STACK, "\n verfied_stack: ");
|
||||
for (i = 0; i < tracker->verified_stack->len; i++)
|
||||
{
|
||||
MetaStackWindow *window = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
|
||||
char *window_id = get_window_id (window);
|
||||
meta_topic (META_DEBUG_STACK, " %s", window_id);
|
||||
g_free (window_id);
|
||||
}
|
||||
meta_topic (META_DEBUG_STACK, "\n unverified_predictions: [");
|
||||
stack_dump (tracker->xserver_stack);
|
||||
meta_topic (META_DEBUG_STACK, " verfied_stack: ");
|
||||
stack_dump (tracker->verified_stack);
|
||||
meta_topic (META_DEBUG_STACK, " unverified_predictions: [");
|
||||
for (l = tracker->unverified_predictions->head; l; l = l->next)
|
||||
{
|
||||
MetaStackOp *op = l->data;
|
||||
@ -269,15 +273,8 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
|
||||
if (tracker->predicted_stack)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK, "\n predicted_stack: ");
|
||||
for (i = 0; i < tracker->predicted_stack->len; i++)
|
||||
{
|
||||
MetaStackWindow *window = &g_array_index (tracker->predicted_stack, MetaStackWindow, i);
|
||||
char *window_id = get_window_id (window);
|
||||
meta_topic (META_DEBUG_STACK, " %s", window_id);
|
||||
g_free (window_id);
|
||||
}
|
||||
stack_dump (tracker->predicted_stack);
|
||||
}
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
meta_pop_no_msg_prefix ();
|
||||
}
|
||||
|
||||
@ -485,14 +482,12 @@ requery_xserver_stack (MetaStackTracker *tracker)
|
||||
screen->xroot,
|
||||
&ignored1, &ignored2, &children, &n_children);
|
||||
|
||||
tracker->xserver_stack =
|
||||
g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
|
||||
tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
|
||||
g_array_set_size (tracker->xserver_stack, n_children);
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
{
|
||||
MetaStackWindow *window =
|
||||
&g_array_index (tracker->xserver_stack, MetaStackWindow, i);
|
||||
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
|
||||
window->any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
window->x11.xwindow = children[i];
|
||||
}
|
||||
@ -714,14 +709,10 @@ meta_stack_tracker_record_lower (MetaStackTracker *tracker,
|
||||
*
|
||||
* Return value: %TRUE if the predicted state is consistent with
|
||||
* receiving the given @op from X, else %FALSE.
|
||||
*
|
||||
* @modified will be set to %TRUE if tracker->verified_stack is
|
||||
* changed by applying any newly validated operations, else %FALSE.
|
||||
*/
|
||||
static gboolean
|
||||
stack_tracker_verify_predictions (MetaStackTracker *tracker,
|
||||
MetaStackOp *op,
|
||||
gboolean *modified)
|
||||
MetaStackOp *op)
|
||||
{
|
||||
GArray *tmp_predicted_stack = NULL;
|
||||
GArray *predicted_stack;
|
||||
@ -731,6 +722,8 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
|
||||
* passed to this api. */
|
||||
g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Verifying predictions:\n");
|
||||
|
||||
if (tracker->unverified_predictions->length)
|
||||
{
|
||||
GList *l;
|
||||
@ -750,6 +743,9 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
|
||||
else
|
||||
predicted_stack = tracker->verified_stack;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, " predicted_stack: ");
|
||||
stack_dump (predicted_stack);
|
||||
|
||||
switch (op->any.type)
|
||||
{
|
||||
case STACK_OP_ADD:
|
||||
@ -825,7 +821,6 @@ verified:
|
||||
meta_stack_op_free (queued_op);
|
||||
}
|
||||
|
||||
*modified = modified_stack;
|
||||
if (modified_stack)
|
||||
{
|
||||
g_array_free (tracker->verified_stack, TRUE);
|
||||
@ -847,8 +842,6 @@ not_verified:
|
||||
tracker->predicted_stack = NULL;
|
||||
}
|
||||
|
||||
*modified = FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -881,17 +874,17 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
* windows and free the queue of unverified_predictions.
|
||||
*
|
||||
* - Iterate through the x windows listed in verified_stack at the
|
||||
* same time as iterating the windows in xserver_list. (Stop
|
||||
* when we reach the end of the xserver_list)
|
||||
* same time as iterating the windows in xserver_stack. (Stop
|
||||
* when we reach the end of the xserver_stack)
|
||||
* - If the window found doesn't match the window expected
|
||||
* according to the order of xserver_list then:
|
||||
* according to the order of xserver_stack then:
|
||||
* - Look ahead for the window we were expecting and restack
|
||||
* that above the previous X window. If we fail to find the
|
||||
* expected window then create a new entry for it and stack
|
||||
* that.
|
||||
*
|
||||
* - Continue to iterate through verified_stack for any remaining
|
||||
* X windows that we now know aren't in the xserver_list and
|
||||
* X windows that we now know aren't in the xserver_stack and
|
||||
* remove them.
|
||||
*
|
||||
* - Free ->predicted_stack if any.
|
||||
@ -909,15 +902,11 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
g_queue_clear (tracker->unverified_predictions);
|
||||
|
||||
j = 0;
|
||||
expected_xwindow =
|
||||
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
|
||||
for (i = 0;
|
||||
i < tracker->verified_stack->len;
|
||||
)
|
||||
for (i = 0; i < tracker->verified_stack->len; )
|
||||
{
|
||||
MetaStackWindow *current =
|
||||
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
|
||||
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
|
||||
|
||||
if (current->any.type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
@ -954,8 +943,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
|
||||
/* Technically we only need to look forward from i if we
|
||||
* wanted to optimize this a bit... */
|
||||
expected_index =
|
||||
find_window (tracker->verified_stack, expected_xwindow);
|
||||
expected_index = find_window (tracker->verified_stack, expected_xwindow);
|
||||
|
||||
if (expected_index >= 0)
|
||||
{
|
||||
@ -993,8 +981,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
i++;
|
||||
|
||||
j++;
|
||||
expected_xwindow =
|
||||
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
|
||||
if (j >= tracker->xserver_stack->len)
|
||||
break;
|
||||
@ -1004,8 +991,7 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
* xserver_stack and so we can remove them. */
|
||||
while (i < tracker->verified_stack->len)
|
||||
{
|
||||
MetaStackWindow *current =
|
||||
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
|
||||
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
|
||||
|
||||
if (current->any.type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
g_array_remove_index (tracker->verified_stack, i);
|
||||
@ -1016,11 +1002,10 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
|
||||
}
|
||||
|
||||
/* If we get to the end of verified_list and there are any remaining
|
||||
* entries in xserver_list then append them all to the end */
|
||||
* entries in xserver_stack then append them all to the end */
|
||||
for (; j < tracker->xserver_stack->len; j++)
|
||||
{
|
||||
MetaStackWindow *current =
|
||||
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
|
||||
g_array_append_val (tracker->verified_stack, *current);
|
||||
|
||||
modified_stack = TRUE;
|
||||
@ -1044,19 +1029,13 @@ static void
|
||||
stack_tracker_event_received (MetaStackTracker *tracker,
|
||||
MetaStackOp *op)
|
||||
{
|
||||
gboolean need_sync = FALSE;
|
||||
gboolean verified;
|
||||
/* If the event is older than our latest requery, then it's
|
||||
* already included in our tree. Just ignore it. */
|
||||
if (op->any.serial < tracker->xserver_serial)
|
||||
return;
|
||||
|
||||
meta_stack_op_dump (op, "Stack op event received: ", "\n");
|
||||
|
||||
if (op->any.serial < tracker->xserver_serial)
|
||||
{
|
||||
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
|
||||
resync_verified_stack_with_xserver_stack (tracker);
|
||||
meta_stack_tracker_dump (tracker);
|
||||
return;
|
||||
}
|
||||
|
||||
tracker->xserver_serial = op->any.serial;
|
||||
|
||||
/* XXX: With the design we have ended up with it looks like we've
|
||||
@ -1070,13 +1049,8 @@ stack_tracker_event_received (MetaStackTracker *tracker,
|
||||
*/
|
||||
meta_stack_op_apply (op, tracker->xserver_stack);
|
||||
|
||||
verified = stack_tracker_verify_predictions (tracker, op, &need_sync);
|
||||
if (!verified)
|
||||
{
|
||||
resync_verified_stack_with_xserver_stack (tracker);
|
||||
meta_stack_tracker_dump (tracker);
|
||||
return;
|
||||
}
|
||||
if (!stack_tracker_verify_predictions (tracker, op))
|
||||
resync_verified_stack_with_xserver_stack (tracker);
|
||||
|
||||
meta_stack_tracker_dump (tracker);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "x11/iconcache.h"
|
||||
#include "x11/group-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
@ -107,9 +106,6 @@ struct _MetaWindow
|
||||
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
MetaIconCache icon_cache;
|
||||
Pixmap wm_hints_pixmap;
|
||||
Pixmap wm_hints_mask;
|
||||
|
||||
MetaWindowType type;
|
||||
|
||||
@ -166,6 +162,7 @@ struct _MetaWindow
|
||||
* that to toggle between normal/tiled or maximized/tiled states. */
|
||||
guint saved_maximize : 1;
|
||||
int tile_monitor_number;
|
||||
int preferred_output_winsys_id;
|
||||
|
||||
/* Whether we're shaded */
|
||||
guint shaded : 1;
|
||||
@ -350,10 +347,6 @@ struct _MetaWindow
|
||||
/* whether or not the window is from a program running on another machine */
|
||||
guint is_remote : 1;
|
||||
|
||||
/* Used for Wayland -- surfaces can behave as if they were unmapped if
|
||||
* they have a NULL buffer attached... */
|
||||
guint surface_mapped;
|
||||
|
||||
/* if non-NULL, the bounds of the window frame */
|
||||
cairo_region_t *frame_bounds;
|
||||
|
||||
@ -421,6 +414,15 @@ struct _MetaWindow
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -478,6 +480,9 @@ struct _MetaWindowClass
|
||||
void (*get_default_skip_hints) (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
gboolean *skip_pager_out);
|
||||
gboolean (*update_icon) (MetaWindow *window,
|
||||
GdkPixbuf **icon,
|
||||
GdkPixbuf **mini_icon);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
@ -575,6 +580,10 @@ void meta_window_show_menu (MetaWindow *window,
|
||||
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);
|
||||
|
||||
@ -618,8 +627,6 @@ void meta_window_stack_just_below (MetaWindow *window,
|
||||
void meta_window_set_user_time (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
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);
|
||||
|
||||
@ -661,11 +668,6 @@ 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,
|
||||
@ -676,9 +678,8 @@ void meta_window_activate_full (MetaWindow *window,
|
||||
MetaClientType source_indication,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
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);
|
||||
@ -698,4 +699,6 @@ 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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -43,8 +43,6 @@
|
||||
#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
|
||||
|
@ -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);
|
||||
@ -127,5 +126,9 @@ void meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
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,
|
||||
|
@ -34,6 +34,9 @@ gboolean meta_get_replace_current_wm (void); /* Actually defined in util
|
||||
void meta_set_wm_name (const char *wm_name);
|
||||
void meta_set_gnome_wm_keybindings (const char *wm_keybindings);
|
||||
|
||||
void meta_restart (const char *message);
|
||||
gboolean meta_is_restart (void);
|
||||
|
||||
/**
|
||||
* MetaExitCode:
|
||||
* @META_EXIT_SUCCESS: Success
|
||||
|
@ -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>
|
||||
@ -170,6 +171,11 @@ struct _MetaPluginClass
|
||||
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
|
||||
@ -294,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
|
@ -108,7 +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);
|
||||
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;
|
||||
@ -256,6 +256,7 @@ gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
|
||||
gboolean meta_window_is_above (MetaWindow *window);
|
||||
gboolean meta_window_allows_move (MetaWindow *window);
|
||||
gboolean meta_window_allows_resize (MetaWindow *window);
|
||||
gboolean meta_window_is_client_decorated (MetaWindow *window);
|
||||
|
||||
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
|
||||
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
|
||||
|
217
src/ui/frames.c
217
src/ui/frames.c
@ -224,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);
|
||||
}
|
||||
|
||||
@ -1138,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)
|
||||
@ -1192,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 ||
|
||||
@ -1218,30 +1276,36 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
{
|
||||
MetaFrameGeometry fgeom;
|
||||
GdkRectangle *rect;
|
||||
MetaRectangle root_rect;
|
||||
MetaWindowMenuType menu;
|
||||
int dx, dy;
|
||||
int win_x, win_y;
|
||||
|
||||
meta_frames_calc_geometry (frames, frame, &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;
|
||||
|
||||
menu = control == META_FRAME_CONTROL_MENU ? META_WINDOW_MENU_WM
|
||||
: META_WINDOW_MENU_APP;
|
||||
|
||||
meta_core_show_window_menu (display,
|
||||
frame->xwindow,
|
||||
menu,
|
||||
rect->x + dx,
|
||||
rect->y + rect->height + dy,
|
||||
event->time);
|
||||
/* 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,
|
||||
menu,
|
||||
&root_rect,
|
||||
event->time);
|
||||
}
|
||||
}
|
||||
else if (event->button == 1 &&
|
||||
@ -1289,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)
|
||||
@ -1311,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)
|
||||
@ -1345,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)
|
||||
@ -1506,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 */
|
||||
@ -1526,7 +1579,6 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
MetaUIFrame *frame;
|
||||
MetaFrames *frames;
|
||||
MetaFrameControl control;
|
||||
int x, y;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
|
||||
@ -1535,9 +1587,7 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
|
||||
frames->last_motion_frame = frame;
|
||||
|
||||
gdk_window_get_device_position (frame->window, event->device,
|
||||
&x, &y, NULL);
|
||||
control = get_control (frames, frame, x, y);
|
||||
control = get_control (frames, frame, event->x, event->y);
|
||||
|
||||
if (frame->button_state == META_BUTTON_STATE_PRESSED)
|
||||
{
|
||||
@ -1555,6 +1605,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;
|
||||
}
|
||||
|
||||
@ -1575,31 +1629,8 @@ 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;
|
||||
@ -1637,9 +1668,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)
|
||||
@ -1738,42 +1767,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;
|
||||
@ -1932,6 +1961,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);
|
||||
|
||||
@ -1944,6 +1975,8 @@ meta_frames_leave_notify_event (GtkWidget *widget,
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
MetaFrames *frames;
|
||||
Display *display;
|
||||
MetaGrabOp grab_op;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
|
||||
@ -1951,6 +1984,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;
|
||||
|
@ -80,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;
|
||||
@ -99,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;
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,7 @@ free_buffer (guchar *pixels, gpointer data)
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
blank_pixbuf (int width, int height, gboolean no_padding)
|
||||
blank_pixbuf (int width, int height)
|
||||
{
|
||||
guchar *buf;
|
||||
int rowstride;
|
||||
@ -73,18 +73,15 @@ blank_pixbuf (int width, int height, gboolean no_padding)
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
|
||||
if (no_padding)
|
||||
rowstride = width * 3;
|
||||
else
|
||||
/* Always align rows to 32-bit boundaries */
|
||||
rowstride = 4 * ((3 * width + 3) / 4);
|
||||
/* Always align rows to 32-bit boundaries */
|
||||
rowstride = 4 * ((4 * width + 4) / 4);
|
||||
|
||||
buf = g_try_malloc (height * rowstride);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
|
||||
FALSE, 8,
|
||||
TRUE, 8,
|
||||
width, height, rowstride,
|
||||
free_buffer, NULL);
|
||||
}
|
||||
@ -196,14 +193,14 @@ meta_gradient_create_interwoven (int width,
|
||||
{
|
||||
|
||||
int i, j, k, l, ll;
|
||||
long r1, g1, b1, dr1, dg1, db1;
|
||||
long r2, g2, b2, dr2, dg2, db2;
|
||||
long r1, g1, b1, a1, dr1, dg1, db1, da1;
|
||||
long r2, g2, b2, a2, dr2, dg2, db2, da2;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int rowstride;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -213,18 +210,22 @@ meta_gradient_create_interwoven (int width,
|
||||
r1 = (long)(colors1[0].red*0xffffff);
|
||||
g1 = (long)(colors1[0].green*0xffffff);
|
||||
b1 = (long)(colors1[0].blue*0xffffff);
|
||||
a1 = (long)(colors1[0].alpha*0xffffff);
|
||||
|
||||
r2 = (long)(colors2[0].red*0xffffff);
|
||||
g2 = (long)(colors2[0].green*0xffffff);
|
||||
b2 = (long)(colors2[0].blue*0xffffff);
|
||||
a2 = (long)(colors2[0].alpha*0xffffff);
|
||||
|
||||
dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
|
||||
dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
|
||||
db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
|
||||
da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height;
|
||||
|
||||
dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
|
||||
dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
|
||||
db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
|
||||
da2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height;
|
||||
|
||||
for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
|
||||
{
|
||||
@ -235,17 +236,19 @@ meta_gradient_create_interwoven (int width,
|
||||
ptr[0] = (unsigned char) (r1>>16);
|
||||
ptr[1] = (unsigned char) (g1>>16);
|
||||
ptr[2] = (unsigned char) (b1>>16);
|
||||
ptr[3] = (unsigned char) (a1>>16);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr[0] = (unsigned char) (r2>>16);
|
||||
ptr[1] = (unsigned char) (g2>>16);
|
||||
ptr[2] = (unsigned char) (b2>>16);
|
||||
ptr[3] = (unsigned char) (a2>>16);
|
||||
}
|
||||
|
||||
for (j=1; j <= width/2; j *= 2)
|
||||
memcpy (&(ptr[j*3]), ptr, j*3);
|
||||
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
|
||||
memcpy (&(ptr[j*4]), ptr, j*4);
|
||||
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
|
||||
|
||||
if (++l == ll)
|
||||
{
|
||||
@ -264,10 +267,12 @@ meta_gradient_create_interwoven (int width,
|
||||
r1+=dr1;
|
||||
g1+=dg1;
|
||||
b1+=db1;
|
||||
a1+=da1;
|
||||
|
||||
r2+=dr2;
|
||||
g2+=dg2;
|
||||
b2+=db2;
|
||||
a2+=da2;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
@ -292,15 +297,15 @@ meta_gradient_create_horizontal (int width, int height,
|
||||
const GdkRGBA *to)
|
||||
{
|
||||
int i;
|
||||
long r, g, b, dr, dg, db;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int r0, g0, b0;
|
||||
int rf, gf, bf;
|
||||
int r0, g0, b0, a0;
|
||||
int rf, gf, bf, af;
|
||||
int rowstride;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -311,26 +316,32 @@ meta_gradient_create_horizontal (int width, int height,
|
||||
r0 = (guchar) (from->red * 0xff);
|
||||
g0 = (guchar) (from->green * 0xff);
|
||||
b0 = (guchar) (from->blue * 0xff);
|
||||
a0 = (guchar) (from->alpha * 0xff);
|
||||
rf = (guchar) (to->red * 0xff);
|
||||
gf = (guchar) (to->green * 0xff);
|
||||
bf = (guchar) (to->blue * 0xff);
|
||||
af = (guchar) (to->alpha * 0xff);
|
||||
|
||||
r = r0 << 16;
|
||||
g = g0 << 16;
|
||||
b = b0 << 16;
|
||||
a = a0 << 16;
|
||||
|
||||
dr = ((rf-r0)<<16)/(int)width;
|
||||
dg = ((gf-g0)<<16)/(int)width;
|
||||
db = ((bf-b0)<<16)/(int)width;
|
||||
da = ((af-a0)<<16)/(int)width;
|
||||
/* render the first line */
|
||||
for (i=0; i<width; i++)
|
||||
{
|
||||
*(ptr++) = (unsigned char)(r>>16);
|
||||
*(ptr++) = (unsigned char)(g>>16);
|
||||
*(ptr++) = (unsigned char)(b>>16);
|
||||
*(ptr++) = (unsigned char)(a>>16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
}
|
||||
|
||||
/* copy the first line to the other lines */
|
||||
@ -360,15 +371,15 @@ meta_gradient_create_vertical (int width, int height,
|
||||
const GdkRGBA *to)
|
||||
{
|
||||
int i, j;
|
||||
long r, g, b, dr, dg, db;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
int r0, g0, b0;
|
||||
int rf, gf, bf;
|
||||
int r0, g0, b0, a0;
|
||||
int rf, gf, bf, af;
|
||||
int rowstride;
|
||||
unsigned char *pixels;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -378,17 +389,21 @@ meta_gradient_create_vertical (int width, int height,
|
||||
r0 = (guchar) (from->red * 0xff);
|
||||
g0 = (guchar) (from->green * 0xff);
|
||||
b0 = (guchar) (from->blue * 0xff);
|
||||
a0 = (guchar) (from->alpha * 0xff);
|
||||
rf = (guchar) (to->red * 0xff);
|
||||
gf = (guchar) (to->green * 0xff);
|
||||
bf = (guchar) (to->blue * 0xff);
|
||||
af = (guchar) (to->alpha * 0xff);
|
||||
|
||||
r = r0<<16;
|
||||
g = g0<<16;
|
||||
b = b0<<16;
|
||||
a = a0<<16;
|
||||
|
||||
dr = ((rf-r0)<<16)/(int)height;
|
||||
dg = ((gf-g0)<<16)/(int)height;
|
||||
db = ((bf-b0)<<16)/(int)height;
|
||||
da = ((af-a0)<<16)/(int)height;
|
||||
|
||||
for (i=0; i<height; i++)
|
||||
{
|
||||
@ -397,14 +412,16 @@ meta_gradient_create_vertical (int width, int height,
|
||||
ptr[0] = (unsigned char)(r>>16);
|
||||
ptr[1] = (unsigned char)(g>>16);
|
||||
ptr[2] = (unsigned char)(b>>16);
|
||||
ptr[3] = (unsigned char)(a>>16);
|
||||
|
||||
for (j=1; j <= width/2; j *= 2)
|
||||
memcpy (&(ptr[j*3]), ptr, j*3);
|
||||
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
|
||||
memcpy (&(ptr[j*4]), ptr, j*4);
|
||||
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
|
||||
|
||||
r+=dr;
|
||||
g+=dg;
|
||||
b+=db;
|
||||
a+=da;
|
||||
}
|
||||
return pixbuf;
|
||||
}
|
||||
@ -442,7 +459,7 @@ meta_gradient_create_diagonal (int width, int height,
|
||||
else if (height == 1)
|
||||
return meta_gradient_create_horizontal (width, height, from, to);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -459,12 +476,12 @@ meta_gradient_create_diagonal (int width, int height,
|
||||
ptr = gdk_pixbuf_get_pixels (tmp);
|
||||
|
||||
a = ((float)(width - 1))/((float)(height - 1));
|
||||
width = width * 3;
|
||||
width = width * 4;
|
||||
|
||||
/* copy the first line to the other lines with corresponding offset */
|
||||
for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
|
||||
{
|
||||
memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
|
||||
memcpy (&(pixels[j]), &ptr[4*(int)offset], width);
|
||||
offset += a;
|
||||
}
|
||||
|
||||
@ -479,7 +496,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
|
||||
int count)
|
||||
{
|
||||
int i, j, k;
|
||||
long r, g, b, dr, dg, db;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
@ -488,7 +505,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
|
||||
|
||||
g_return_val_if_fail (count > 2, NULL);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -509,6 +526,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
|
||||
r = (long)(colors[0].red * 0xffffff);
|
||||
g = (long)(colors[0].green * 0xffffff);
|
||||
b = (long)(colors[0].blue * 0xffffff);
|
||||
a = (long)(colors[0].alpha * 0xffffff);
|
||||
|
||||
/* render the first line */
|
||||
for (i=1; i<count; i++)
|
||||
@ -516,25 +534,30 @@ meta_gradient_create_multi_horizontal (int width, int height,
|
||||
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
|
||||
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
|
||||
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
|
||||
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)width2;
|
||||
for (j=0; j<width2; j++)
|
||||
{
|
||||
*ptr++ = (unsigned char)(r>>16);
|
||||
*ptr++ = (unsigned char)(g>>16);
|
||||
*ptr++ = (unsigned char)(b>>16);
|
||||
*ptr++ = (unsigned char)(a>>16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
k++;
|
||||
}
|
||||
r = (long)(colors[i].red * 0xffffff);
|
||||
g = (long)(colors[i].green * 0xffffff);
|
||||
b = (long)(colors[i].blue * 0xffffff);
|
||||
a = (long)(colors[i].alpha * 0xffffff);
|
||||
}
|
||||
for (j=k; j<width; j++)
|
||||
{
|
||||
*ptr++ = (unsigned char)(r>>16);
|
||||
*ptr++ = (unsigned char)(g>>16);
|
||||
*ptr++ = (unsigned char)(b>>16);
|
||||
*ptr++ = (unsigned char)(a>>16);
|
||||
}
|
||||
|
||||
/* copy the first line to the other lines */
|
||||
@ -551,7 +574,7 @@ meta_gradient_create_multi_vertical (int width, int height,
|
||||
int count)
|
||||
{
|
||||
int i, j, k;
|
||||
long r, g, b, dr, dg, db;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr, *tmp, *pixels;
|
||||
int height2;
|
||||
@ -560,7 +583,7 @@ meta_gradient_create_multi_vertical (int width, int height,
|
||||
|
||||
g_return_val_if_fail (count > 2, NULL);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height, FALSE);
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -581,33 +604,38 @@ meta_gradient_create_multi_vertical (int width, int height,
|
||||
r = (long)(colors[0].red * 0xffffff);
|
||||
g = (long)(colors[0].green * 0xffffff);
|
||||
b = (long)(colors[0].blue * 0xffffff);
|
||||
a = (long)(colors[0].alpha * 0xffffff);
|
||||
|
||||
for (i=1; i<count; i++)
|
||||
{
|
||||
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
|
||||
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
|
||||
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
|
||||
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)height2;
|
||||
|
||||
for (j=0; j<height2; j++)
|
||||
{
|
||||
ptr[0] = (unsigned char)(r>>16);
|
||||
ptr[1] = (unsigned char)(g>>16);
|
||||
ptr[2] = (unsigned char)(b>>16);
|
||||
ptr[3] = (unsigned char)(a>>16);
|
||||
|
||||
for (x=1; x <= width/2; x *= 2)
|
||||
memcpy (&(ptr[x*3]), ptr, x*3);
|
||||
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
|
||||
memcpy (&(ptr[x*4]), ptr, x*4);
|
||||
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
|
||||
|
||||
ptr += rowstride;
|
||||
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
k++;
|
||||
}
|
||||
r = (long)(colors[i].red * 0xffffff);
|
||||
g = (long)(colors[i].green * 0xffffff);
|
||||
b = (long)(colors[i].blue * 0xffffff);
|
||||
a = (long)(colors[i].alpha * 0xffffff);
|
||||
}
|
||||
|
||||
if (k<height)
|
||||
@ -617,10 +645,11 @@ meta_gradient_create_multi_vertical (int width, int height,
|
||||
ptr[0] = (unsigned char) (r>>16);
|
||||
ptr[1] = (unsigned char) (g>>16);
|
||||
ptr[2] = (unsigned char) (b>>16);
|
||||
ptr[3] = (unsigned char) (a>>16);
|
||||
|
||||
for (x=1; x <= width/2; x *= 2)
|
||||
memcpy (&(ptr[x*3]), ptr, x*3);
|
||||
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
|
||||
memcpy (&(ptr[x*4]), ptr, x*4);
|
||||
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
|
||||
|
||||
ptr += rowstride;
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaResizePopup MetaResizePopup;
|
||||
|
||||
MetaResizePopup* meta_ui_resize_popup_new (Display *display,
|
||||
int screen_number);
|
||||
void meta_ui_resize_popup_free (MetaResizePopup *popup);
|
||||
|
341
src/ui/theme.c
341
src/ui/theme.c
@ -56,8 +56,6 @@
|
||||
((int)((color).green * 255) << 8) | \
|
||||
((int)((color).blue * 255))))
|
||||
|
||||
#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255))
|
||||
|
||||
#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
|
||||
#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
|
||||
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
|
||||
@ -94,8 +92,8 @@ colorize_pixbuf (GdkPixbuf *orig,
|
||||
guchar *dest_pixels;
|
||||
|
||||
pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig),
|
||||
gdk_pixbuf_get_bits_per_sample (orig),
|
||||
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
|
||||
gdk_pixbuf_get_bits_per_sample (orig),
|
||||
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
|
||||
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
@ -165,6 +163,7 @@ color_composite (const GdkRGBA *bg,
|
||||
color->red = color->red + (fg->red - color->red) * alpha;
|
||||
color->green = color->green + (fg->green - color->green) * alpha;
|
||||
color->blue = color->blue + (fg->blue - color->blue) * alpha;
|
||||
color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -795,19 +794,19 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
|
||||
&n_right, &fgeom->above_rect))
|
||||
continue;
|
||||
else if (strip_button (left_func_rects, left_bg_rects,
|
||||
&n_left, &fgeom->stick_rect))
|
||||
&n_left, &fgeom->stick_rect))
|
||||
continue;
|
||||
else if (strip_button (right_func_rects, right_bg_rects,
|
||||
&n_right, &fgeom->stick_rect))
|
||||
continue;
|
||||
else if (strip_button (left_func_rects, left_bg_rects,
|
||||
&n_left, &fgeom->shade_rect))
|
||||
&n_left, &fgeom->shade_rect))
|
||||
continue;
|
||||
else if (strip_button (right_func_rects, right_bg_rects,
|
||||
&n_right, &fgeom->shade_rect))
|
||||
continue;
|
||||
else if (strip_button (left_func_rects, left_bg_rects,
|
||||
&n_left, &fgeom->min_rect))
|
||||
&n_left, &fgeom->min_rect))
|
||||
continue;
|
||||
else if (strip_button (right_func_rects, right_bg_rects,
|
||||
&n_right, &fgeom->min_rect))
|
||||
@ -926,12 +925,11 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
|
||||
rect->clickable.width = button_width;
|
||||
}
|
||||
|
||||
rect->clickable.y = 0;
|
||||
rect->clickable.height = button_height + button_y;
|
||||
}
|
||||
else
|
||||
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
|
||||
|
||||
rect->clickable.y = 0;
|
||||
rect->clickable.height = button_height + button_y;
|
||||
}
|
||||
else
|
||||
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
|
||||
|
||||
x = rect->visible.x + rect->visible.width + layout->button_border.right;
|
||||
if (left_buttons_has_spacer[i])
|
||||
@ -1192,10 +1190,8 @@ meta_color_spec_new_from_string (const char *str,
|
||||
MetaColorSpec *spec;
|
||||
|
||||
spec = NULL;
|
||||
|
||||
if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' &&
|
||||
str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' &&
|
||||
str[8] == 'o' && str[9] == 'm')
|
||||
|
||||
if (strncmp (str, "gtk:custom", 10) == 0)
|
||||
{
|
||||
const char *color_name_start, *fallback_str_start, *end;
|
||||
char *color_name;
|
||||
@ -1270,7 +1266,7 @@ meta_color_spec_new_from_string (const char *str,
|
||||
spec->data.gtkcustom.color_name = color_name;
|
||||
spec->data.gtkcustom.fallback = fallback;
|
||||
}
|
||||
else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':')
|
||||
else if (strncmp (str, "gtk:", 4) == 0)
|
||||
{
|
||||
/* GTK color */
|
||||
const char *bracket;
|
||||
@ -1337,8 +1333,7 @@ meta_color_spec_new_from_string (const char *str,
|
||||
spec->data.gtk.component = component;
|
||||
g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
|
||||
}
|
||||
else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' &&
|
||||
str[4] == 'd' && str[5] == '/')
|
||||
else if (strncmp (str, "blend/", 6) == 0)
|
||||
{
|
||||
/* blend */
|
||||
char **split;
|
||||
@ -1406,8 +1401,7 @@ meta_color_spec_new_from_string (const char *str,
|
||||
spec->data.blend.background = bg;
|
||||
spec->data.blend.foreground = fg;
|
||||
}
|
||||
else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
|
||||
str[4] == 'e' && str[5] == '/')
|
||||
else if (strncmp (str, "shade/", 6) == 0)
|
||||
{
|
||||
/* shade */
|
||||
char **split;
|
||||
@ -1704,20 +1698,12 @@ op_from_string (const char *p,
|
||||
return POS_OP_MOD;
|
||||
|
||||
case '`':
|
||||
if (p[0] == '`' &&
|
||||
p[1] == 'm' &&
|
||||
p[2] == 'a' &&
|
||||
p[3] == 'x' &&
|
||||
p[4] == '`')
|
||||
if (strncmp (p, "`max`", 5) == 0)
|
||||
{
|
||||
*len = 5;
|
||||
return POS_OP_MAX;
|
||||
}
|
||||
else if (p[0] == '`' &&
|
||||
p[1] == 'm' &&
|
||||
p[2] == 'i' &&
|
||||
p[3] == 'n' &&
|
||||
p[4] == '`')
|
||||
else if (strncmp (p, "`min`", 5) == 0)
|
||||
{
|
||||
*len = 5;
|
||||
return POS_OP_MIN;
|
||||
@ -3067,7 +3053,7 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
g_object_unref (G_OBJECT (op->data.image.pixbuf));
|
||||
|
||||
if (op->data.image.colorize_spec)
|
||||
meta_color_spec_free (op->data.image.colorize_spec);
|
||||
meta_color_spec_free (op->data.image.colorize_spec);
|
||||
|
||||
if (op->data.image.colorize_cache_pixbuf)
|
||||
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
|
||||
@ -3418,32 +3404,6 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
|
||||
switch (op->type)
|
||||
{
|
||||
case META_DRAW_LINE:
|
||||
break;
|
||||
|
||||
case META_DRAW_RECTANGLE:
|
||||
if (op->data.rectangle.filled)
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_color_spec_render (op->data.rectangle.color_spec,
|
||||
context,
|
||||
&color);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
FALSE,
|
||||
8, width, height);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color));
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_ARC:
|
||||
break;
|
||||
|
||||
case META_DRAW_CLIP:
|
||||
break;
|
||||
|
||||
case META_DRAW_TINT:
|
||||
{
|
||||
GdkRGBA color;
|
||||
@ -3502,12 +3462,11 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case META_DRAW_IMAGE:
|
||||
{
|
||||
if (op->data.image.colorize_spec)
|
||||
{
|
||||
GdkRGBA color;
|
||||
if (op->data.image.colorize_spec)
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_color_spec_render (op->data.image.colorize_spec,
|
||||
context, &color);
|
||||
@ -3535,24 +3494,18 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
op->data.image.vertical_stripes,
|
||||
op->data.image.horizontal_stripes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
|
||||
op->data.image.alpha_spec,
|
||||
op->data.image.fill_type,
|
||||
width, height,
|
||||
op->data.image.vertical_stripes,
|
||||
op->data.image.horizontal_stripes);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case META_DRAW_GTK_ARROW:
|
||||
case META_DRAW_GTK_BOX:
|
||||
case META_DRAW_GTK_VLINE:
|
||||
break;
|
||||
|
||||
case META_DRAW_ICON:
|
||||
if (info->mini_icon &&
|
||||
width <= gdk_pixbuf_get_width (info->mini_icon) &&
|
||||
@ -3570,12 +3523,15 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
FALSE, FALSE);
|
||||
break;
|
||||
|
||||
case META_DRAW_LINE:
|
||||
case META_DRAW_RECTANGLE:
|
||||
case META_DRAW_ARC:
|
||||
case META_DRAW_CLIP:
|
||||
case META_DRAW_GTK_ARROW:
|
||||
case META_DRAW_GTK_BOX:
|
||||
case META_DRAW_GTK_VLINE:
|
||||
case META_DRAW_TITLE:
|
||||
break;
|
||||
|
||||
case META_DRAW_OP_LIST:
|
||||
break;
|
||||
|
||||
case META_DRAW_TILE:
|
||||
break;
|
||||
}
|
||||
@ -4046,8 +4002,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
|
||||
|
||||
meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
|
||||
style_gtk, cr, info,
|
||||
d_rect);
|
||||
style_gtk, cr, info, d_rect);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -4084,8 +4039,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
while (tile.y < (ry + rheight))
|
||||
{
|
||||
meta_draw_op_list_draw_with_style (op->data.tile.op_list,
|
||||
style_gtk, cr, info,
|
||||
tile);
|
||||
style_gtk, cr, info, tile);
|
||||
|
||||
tile.y += tile.height;
|
||||
}
|
||||
@ -4185,18 +4139,6 @@ meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list,
|
||||
|
||||
fill_env (&env, info, rect);
|
||||
|
||||
/* FIXME this can be optimized, potentially a lot, by
|
||||
* compressing multiple ops when possible. For example,
|
||||
* anything convertible to a pixbuf can be composited
|
||||
* client-side, and putting a color tint over a pixbuf
|
||||
* can be done without creating the solid-color pixbuf.
|
||||
*
|
||||
* To implement this my plan is to have the idea of a
|
||||
* compiled draw op (with the string expressions already
|
||||
* evaluated), we make an array of those, and then fold
|
||||
* adjacent items when possible.
|
||||
*/
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
for (i = 0; i < op_list->n_ops; i++)
|
||||
@ -6401,6 +6343,7 @@ gtk_style_shade (GdkRGBA *a,
|
||||
b->red = red;
|
||||
b->green = green;
|
||||
b->blue = blue;
|
||||
b->alpha = a->alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6569,216 +6512,6 @@ hls_to_rgb (gdouble *h,
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* These are some functions I'm saving to use in optimizing
|
||||
* MetaDrawOpList, namely to pre-composite pixbufs on client side
|
||||
* prior to rendering to the server
|
||||
*/
|
||||
static void
|
||||
draw_bg_solid_composite (const MetaTextureSpec *bg,
|
||||
const MetaTextureSpec *fg,
|
||||
double alpha,
|
||||
GtkWidget *widget,
|
||||
GdkDrawable *drawable,
|
||||
const GdkRectangle *clip,
|
||||
MetaTextureDrawMode mode,
|
||||
double xalign,
|
||||
double yalign,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkRGBA bg_color;
|
||||
|
||||
g_assert (bg->type == META_TEXTURE_SOLID);
|
||||
g_assert (fg->type != META_TEXTURE_COMPOSITE);
|
||||
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
|
||||
|
||||
meta_color_spec_render (bg->data.solid.color_spec,
|
||||
widget,
|
||||
&bg_color);
|
||||
|
||||
switch (fg->type)
|
||||
{
|
||||
case META_TEXTURE_SOLID:
|
||||
{
|
||||
GdkRGBA fg_color;
|
||||
|
||||
meta_color_spec_render (fg->data.solid.color_spec,
|
||||
widget,
|
||||
&fg_color);
|
||||
|
||||
color_composite (&bg_color, &fg_color,
|
||||
alpha, &fg_color);
|
||||
|
||||
draw_color_rectangle (widget, drawable, &fg_color, clip,
|
||||
x, y, width, height);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_TEXTURE_GRADIENT:
|
||||
/* FIXME I think we could just composite all the colors in
|
||||
* the gradient prior to generating the gradient?
|
||||
*/
|
||||
/* FALL THRU */
|
||||
case META_TEXTURE_IMAGE:
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *composited;
|
||||
|
||||
pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
|
||||
width, height);
|
||||
|
||||
if (pixbuf == NULL)
|
||||
return;
|
||||
|
||||
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
gdk_pixbuf_get_has_alpha (pixbuf), 8,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf));
|
||||
|
||||
if (composited == NULL)
|
||||
{
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_pixbuf_composite_color (pixbuf,
|
||||
composited,
|
||||
0, 0,
|
||||
gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
0.0, 0.0, /* offsets */
|
||||
1.0, 1.0, /* scale */
|
||||
GDK_INTERP_BILINEAR,
|
||||
255 * alpha,
|
||||
0, 0, /* check offsets */
|
||||
0, /* check size */
|
||||
GDK_COLOR_RGB (bg_color),
|
||||
GDK_COLOR_RGB (bg_color));
|
||||
|
||||
/* Need to draw background since pixbuf is not
|
||||
* necessarily covering the whole thing
|
||||
*/
|
||||
draw_color_rectangle (widget, drawable, &bg_color, clip,
|
||||
x, y, width, height);
|
||||
|
||||
render_pixbuf_aligned (drawable, clip, composited,
|
||||
xalign, yalign,
|
||||
x, y, width, height);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
g_object_unref (G_OBJECT (composited));
|
||||
}
|
||||
break;
|
||||
|
||||
case META_TEXTURE_BLANK:
|
||||
case META_TEXTURE_COMPOSITE:
|
||||
case META_TEXTURE_SHAPE_LIST:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_bg_gradient_composite (const MetaTextureSpec *bg,
|
||||
const MetaTextureSpec *fg,
|
||||
double alpha,
|
||||
GtkWidget *widget,
|
||||
GdkDrawable *drawable,
|
||||
const GdkRectangle *clip,
|
||||
MetaTextureDrawMode mode,
|
||||
double xalign,
|
||||
double yalign,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_assert (bg->type == META_TEXTURE_GRADIENT);
|
||||
g_assert (fg->type != META_TEXTURE_COMPOSITE);
|
||||
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
|
||||
|
||||
switch (fg->type)
|
||||
{
|
||||
case META_TEXTURE_SOLID:
|
||||
case META_TEXTURE_GRADIENT:
|
||||
case META_TEXTURE_IMAGE:
|
||||
{
|
||||
GdkPixbuf *bg_pixbuf;
|
||||
GdkPixbuf *fg_pixbuf;
|
||||
GdkPixbuf *composited;
|
||||
int fg_width, fg_height;
|
||||
|
||||
bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255,
|
||||
width, height);
|
||||
|
||||
if (bg_pixbuf == NULL)
|
||||
return;
|
||||
|
||||
fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
|
||||
width, height);
|
||||
|
||||
if (fg_pixbuf == NULL)
|
||||
{
|
||||
g_object_unref (G_OBJECT (bg_pixbuf));
|
||||
return;
|
||||
}
|
||||
|
||||
/* gradients always fill the entire target area */
|
||||
g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width);
|
||||
g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height);
|
||||
|
||||
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
gdk_pixbuf_get_has_alpha (bg_pixbuf), 8,
|
||||
gdk_pixbuf_get_width (bg_pixbuf),
|
||||
gdk_pixbuf_get_height (bg_pixbuf));
|
||||
|
||||
if (composited == NULL)
|
||||
{
|
||||
g_object_unref (G_OBJECT (bg_pixbuf));
|
||||
g_object_unref (G_OBJECT (fg_pixbuf));
|
||||
return;
|
||||
}
|
||||
|
||||
fg_width = gdk_pixbuf_get_width (fg_pixbuf);
|
||||
fg_height = gdk_pixbuf_get_height (fg_pixbuf);
|
||||
|
||||
/* If we wanted to be all cool we could deal with the
|
||||
* offsets and try to composite only in the clip rectangle,
|
||||
* but I just don't care enough to figure it out.
|
||||
*/
|
||||
|
||||
gdk_pixbuf_composite (fg_pixbuf,
|
||||
composited,
|
||||
x + (width - fg_width) * xalign,
|
||||
y + (height - fg_height) * yalign,
|
||||
gdk_pixbuf_get_width (fg_pixbuf),
|
||||
gdk_pixbuf_get_height (fg_pixbuf),
|
||||
0.0, 0.0, /* offsets */
|
||||
1.0, 1.0, /* scale */
|
||||
GDK_INTERP_BILINEAR,
|
||||
255 * alpha);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, composited, x, y);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (bg_pixbuf));
|
||||
g_object_unref (G_OBJECT (fg_pixbuf));
|
||||
g_object_unref (G_OBJECT (composited));
|
||||
}
|
||||
break;
|
||||
|
||||
case META_TEXTURE_BLANK:
|
||||
case META_TEXTURE_SHAPE_LIST:
|
||||
case META_TEXTURE_COMPOSITE:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* meta_theme_earliest_version_with_button:
|
||||
* @type: the button type
|
||||
|
143
src/ui/ui.c
143
src/ui/ui.c
@ -83,6 +83,31 @@ is_input_event (XEvent *event)
|
||||
event->xcookie.extension == display->xinput_opcode);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_interesting_input_event (XEvent *event)
|
||||
{
|
||||
XIEvent *input_event;
|
||||
|
||||
if (!is_input_event (event))
|
||||
return FALSE;
|
||||
|
||||
input_event = (XIEvent *) event->xcookie.data;
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_Motion:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
case XI_TouchBegin:
|
||||
case XI_TouchUpdate:
|
||||
case XI_TouchEnd:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* We do some of our event handling in frames.c, which expects
|
||||
* GDK events delivered by GTK+. However, since the transition to
|
||||
* client side windows, we can't let GDK see button events, since the
|
||||
@ -98,7 +123,7 @@ is_input_event (XEvent *event)
|
||||
* use more fields, more fields need to be filled out below.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
maybe_redirect_mouse_event (XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *gdisplay;
|
||||
@ -112,14 +137,10 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
XIDeviceEvent *xev_d = NULL;
|
||||
XIEnterEvent *xev_e = NULL;
|
||||
|
||||
if (!is_input_event (xevent))
|
||||
return FALSE;
|
||||
|
||||
xev = (XIEvent *) xevent->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_TouchBegin:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_Motion:
|
||||
@ -132,34 +153,27 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
window = xev_e->event;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
/* Not interested in this event. */
|
||||
return;
|
||||
}
|
||||
|
||||
gdisplay = gdk_x11_lookup_xdisplay (xev->display);
|
||||
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
|
||||
if (!ui)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
|
||||
if (gdk_window == NULL)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdisplay);
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
|
||||
/* If GDK already thinks it has a grab, we better let it see events; this
|
||||
* is the menu-navigation case and events need to get sent to the appropriate
|
||||
* (client-side) subwindow for individual menu items.
|
||||
*/
|
||||
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
|
||||
return FALSE;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_TouchBegin:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
if (xev_d->evtype == XI_ButtonPress || xev_d->evtype == XI_TouchBegin)
|
||||
if (xev_d->evtype == XI_ButtonPress)
|
||||
{
|
||||
GtkSettings *settings = gtk_settings_get_default ();
|
||||
int double_click_time;
|
||||
@ -171,10 +185,7 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
"gtk-double-click-distance", &double_click_distance,
|
||||
NULL);
|
||||
|
||||
if (xev->evtype == XI_TouchBegin)
|
||||
button = 1;
|
||||
else
|
||||
button = xev_d->detail;
|
||||
button = xev_d->detail;
|
||||
|
||||
if (button == ui->button_click_number &&
|
||||
xev_d->event == ui->button_click_window &&
|
||||
@ -210,17 +221,24 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
gevent->button.y = xev_d->event_y;
|
||||
gevent->button.x_root = xev_d->root_x;
|
||||
gevent->button.y_root = xev_d->root_y;
|
||||
|
||||
break;
|
||||
case XI_Motion:
|
||||
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
|
||||
gevent->motion.type = GDK_MOTION_NOTIFY;
|
||||
gevent->motion.window = g_object_ref (gdk_window);
|
||||
gevent->motion.time = xev_d->time;
|
||||
gevent->motion.x = xev_d->event_x;
|
||||
gevent->motion.y = xev_d->event_y;
|
||||
gevent->motion.x_root = xev_d->root_x;
|
||||
gevent->motion.y_root = xev_d->root_y;
|
||||
|
||||
if (XIMaskIsSet (xev_d->buttons.mask, 1))
|
||||
gevent->motion.state |= GDK_BUTTON1_MASK;
|
||||
break;
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
|
||||
gevent->crossing.window = g_object_ref (gdk_window);
|
||||
gevent->crossing.time = xev_e->time;
|
||||
gevent->crossing.x = xev_e->event_x;
|
||||
gevent->crossing.y = xev_e->event_y;
|
||||
break;
|
||||
@ -233,8 +251,6 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
gdk_event_set_device (gevent, gdevice);
|
||||
gtk_main_do_event (gevent);
|
||||
gdk_event_free (gevent);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkFilterReturn
|
||||
@ -242,8 +258,11 @@ ui_filter_func (GdkXEvent *xevent,
|
||||
GdkEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (maybe_redirect_mouse_event (xevent))
|
||||
return GDK_FILTER_REMOVE;
|
||||
if (is_interesting_input_event (xevent))
|
||||
{
|
||||
maybe_redirect_mouse_event (xevent);
|
||||
return GDK_FILTER_REMOVE;
|
||||
}
|
||||
else
|
||||
return GDK_FILTER_CONTINUE;
|
||||
}
|
||||
@ -536,76 +555,6 @@ meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
return retval;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_window_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"image-missing",
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_mini_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"image-missing",
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow)
|
||||
|
@ -121,9 +121,6 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
|
||||
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
|
||||
|
||||
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow);
|
||||
|
||||
|
@ -35,6 +35,25 @@
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_listener source_destroy_listener;
|
||||
} MetaWaylandDataOffer;
|
||||
|
||||
struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
};
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_accept (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -179,7 +198,8 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
struct wl_resource *resource, *offer = NULL;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *data_device_resource, *offer = NULL;
|
||||
struct wl_display *display;
|
||||
guint32 serial;
|
||||
wl_fixed_t sx, sy;
|
||||
@ -202,28 +222,28 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
wl_resource_get_client (surface->resource) != drag_grab->drag_client)
|
||||
return;
|
||||
|
||||
resource =
|
||||
wl_resource_find_for_client (&seat->data_device_resource_list,
|
||||
wl_resource_get_client (surface->resource));
|
||||
if (!resource)
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
||||
if (!data_device_resource)
|
||||
return;
|
||||
|
||||
display = wl_client_get_display (wl_resource_get_client (resource));
|
||||
display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
|
||||
resource);
|
||||
data_device_resource);
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
|
||||
wl_data_device_send_enter (resource, serial, surface->resource,
|
||||
wl_data_device_send_enter (data_device_resource, serial, surface->resource,
|
||||
sx, sy, offer);
|
||||
|
||||
drag_grab->drag_focus = surface;
|
||||
|
||||
drag_grab->drag_focus_data_device = resource;
|
||||
drag_grab->drag_focus_data_device = data_device_resource;
|
||||
drag_grab->drag_focus_listener.notify = destroy_drag_focus;
|
||||
wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener);
|
||||
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -312,7 +332,8 @@ data_device_start_drag (struct wl_client *client,
|
||||
struct wl_resource *origin_resource,
|
||||
struct wl_resource *icon_resource, guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
|
||||
if ((seat->pointer.button_count == 0 ||
|
||||
@ -357,68 +378,67 @@ data_device_start_drag (struct wl_client *client,
|
||||
static void
|
||||
destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandSeat *seat =
|
||||
wl_container_of (listener, seat, selection_data_source_listener);
|
||||
struct wl_resource *data_device;
|
||||
MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client = NULL;
|
||||
|
||||
seat->selection_data_source = NULL;
|
||||
data_device->selection_data_source = NULL;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
|
||||
if (data_device)
|
||||
wl_data_device_send_selection (data_device, NULL);
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
wl_data_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
{
|
||||
struct wl_resource *data_device, *offer;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource, *offer;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
if (seat->selection_data_source &&
|
||||
seat->selection_serial - serial < UINT32_MAX / 2)
|
||||
if (data_device->selection_data_source &&
|
||||
data_device->selection_serial - serial < UINT32_MAX / 2)
|
||||
return;
|
||||
|
||||
if (seat->selection_data_source)
|
||||
if (data_device->selection_data_source)
|
||||
{
|
||||
wl_data_source_send_cancelled (seat->selection_data_source->resource);
|
||||
wl_list_remove (&seat->selection_data_source_listener.link);
|
||||
seat->selection_data_source = NULL;
|
||||
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
|
||||
wl_list_remove (&data_device->selection_data_source_listener.link);
|
||||
data_device->selection_data_source = NULL;
|
||||
}
|
||||
|
||||
seat->selection_data_source = source;
|
||||
seat->selection_serial = serial;
|
||||
data_device->selection_data_source = source;
|
||||
data_device->selection_serial = serial;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
|
||||
if (data_device)
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
{
|
||||
if (seat->selection_data_source)
|
||||
if (data_device->selection_data_source)
|
||||
{
|
||||
offer = meta_wayland_data_source_send_offer (seat->selection_data_source, data_device);
|
||||
wl_data_device_send_selection (data_device, offer);
|
||||
offer = meta_wayland_data_source_send_offer (data_device->selection_data_source, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_data_device_send_selection (data_device, NULL);
|
||||
wl_data_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source)
|
||||
{
|
||||
seat->selection_data_source_listener.notify =
|
||||
destroy_selection_data_source;
|
||||
wl_resource_add_destroy_listener (source->resource,
|
||||
&seat->selection_data_source_listener);
|
||||
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
|
||||
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,13 +448,16 @@ data_device_set_selection (struct wl_client *client,
|
||||
struct wl_resource *source_resource,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
if (!source_resource)
|
||||
return;
|
||||
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
/* FIXME: Store serial and check against incoming serial here. */
|
||||
meta_wayland_seat_set_selection (wl_resource_get_user_data (resource),
|
||||
wl_resource_get_user_data (source_resource),
|
||||
serial);
|
||||
meta_wayland_data_device_set_selection (data_device, source, serial);
|
||||
}
|
||||
|
||||
static const struct wl_data_device_interface data_device_interface = {
|
||||
@ -470,25 +493,18 @@ create_data_source (struct wl_client *client,
|
||||
wl_array_init (&source->mime_types);
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_data_device (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
get_data_device (struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
guint32 id, struct wl_resource *seat_resource)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
struct wl_resource *resource;
|
||||
struct wl_resource *cr;
|
||||
|
||||
resource = wl_resource_create (client, &wl_data_device_interface,
|
||||
MIN (META_WL_DATA_DEVICE_VERSION,
|
||||
wl_resource_get_version (manager_resource)), id);
|
||||
wl_resource_set_implementation (resource, &data_device_interface, seat, unbind_data_device);
|
||||
wl_list_insert (&seat->data_device_resource_list, wl_resource_get_link (resource));
|
||||
cr = wl_resource_create (client, &wl_data_device_interface,
|
||||
MIN (META_WL_DATA_DEVICE_VERSION, wl_resource_get_version (manager_resource)), id);
|
||||
wl_resource_set_implementation (cr, &data_device_interface, &seat->data_device, unbind_resource);
|
||||
wl_list_insert (&seat->data_device.resource_list, wl_resource_get_link (cr));
|
||||
}
|
||||
|
||||
static const struct wl_data_device_manager_interface manager_interface = {
|
||||
@ -518,24 +534,31 @@ meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat)
|
||||
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_client *focus_client;
|
||||
struct wl_resource *data_device, *offer;
|
||||
struct wl_resource *data_device_resource, *offer;
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
|
||||
if (!data_device)
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (!data_device_resource)
|
||||
return;
|
||||
|
||||
source = seat->selection_data_source;
|
||||
source = data_device->selection_data_source;
|
||||
if (source)
|
||||
{
|
||||
offer = meta_wayland_data_source_send_offer (source, data_device);
|
||||
wl_data_device_send_selection (data_device, offer);
|
||||
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,20 @@
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandDataDevice
|
||||
{
|
||||
uint32_t selection_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
};
|
||||
|
||||
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
|
||||
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
|
||||
|
||||
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_H */
|
||||
|
@ -301,6 +301,7 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
void
|
||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
xkb_context_unref (keyboard->xkb_context);
|
||||
|
||||
@ -549,7 +550,7 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
||||
|
||||
cr = wl_resource_create (client, &wl_keyboard_interface,
|
||||
MIN (META_WL_KEYBOARD_VERSION, wl_resource_get_version (seat_resource)), id);
|
||||
wl_resource_set_implementation (cr, NULL, keyboard, unbind_resource);
|
||||
wl_resource_set_implementation (cr, &keyboard_interface, keyboard, unbind_resource);
|
||||
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
|
||||
|
||||
wl_keyboard_send_keymap (cr,
|
||||
|
@ -168,12 +168,20 @@ wayland_output_destroy_notify (gpointer data)
|
||||
g_slice_free (MetaWaylandOutput, wayland_output);
|
||||
}
|
||||
|
||||
static inline enum wl_output_transform
|
||||
wl_output_transform_from_meta_monitor_transform (MetaMonitorTransform transform)
|
||||
{
|
||||
/* The enums are the same. */
|
||||
return (enum wl_output_transform) transform;
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
MetaOutput *output)
|
||||
{
|
||||
GList *iter;
|
||||
guint mode_flags;
|
||||
enum wl_output_transform wl_transform = wl_output_transform_from_meta_monitor_transform (output->crtc->transform);
|
||||
|
||||
g_assert (output->crtc->current_mode != NULL);
|
||||
|
||||
@ -187,7 +195,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
|
||||
if (wayland_output->x != output->crtc->rect.x ||
|
||||
wayland_output->y != output->crtc->rect.y ||
|
||||
wayland_output->transform != output->crtc->transform)
|
||||
wayland_output->transform != wl_transform)
|
||||
{
|
||||
wl_resource_post_event (resource,
|
||||
WL_OUTPUT_GEOMETRY,
|
||||
@ -198,7 +206,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
output->subpixel_order,
|
||||
output->vendor,
|
||||
output->product,
|
||||
output->crtc->transform);
|
||||
wl_transform);
|
||||
}
|
||||
|
||||
wl_resource_post_event (resource,
|
||||
@ -214,7 +222,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||
wayland_output->output = output;
|
||||
wayland_output->x = output->crtc->rect.x;
|
||||
wayland_output->y = output->crtc->rect.y;
|
||||
wayland_output->transform = output->crtc->transform;
|
||||
wayland_output->transform = wl_transform;
|
||||
}
|
||||
|
||||
static GHashTable *
|
||||
@ -236,15 +244,15 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||
/* wayland does not expose disabled outputs */
|
||||
if (output->crtc == NULL)
|
||||
{
|
||||
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
continue;
|
||||
}
|
||||
|
||||
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
|
||||
if (wayland_output)
|
||||
{
|
||||
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -256,7 +264,7 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
|
||||
wayland_output_update_for_output (wayland_output, output);
|
||||
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
|
||||
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->winsys_id), wayland_output);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (compositor->outputs);
|
||||
|
@ -200,8 +200,6 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
|
||||
pointer->cursor_surface = NULL;
|
||||
pointer->cursor_surface_destroy_listener.notify = pointer_handle_cursor_surface_destroy;
|
||||
pointer->hotspot_x = 16;
|
||||
pointer->hotspot_y = 16;
|
||||
|
||||
pointer->default_grab.interface = &default_pointer_grab_interface;
|
||||
pointer->default_grab.pointer = pointer;
|
||||
@ -209,11 +207,14 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
pointer->device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
pointer->cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
set_cursor_surface (pointer, NULL);
|
||||
}
|
||||
|
||||
@ -815,7 +816,7 @@ meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
return (pointer->button_count == 0 &&
|
||||
return (pointer->button_count > 0 &&
|
||||
pointer->grab_serial == serial &&
|
||||
pointer->focus_surface == surface);
|
||||
}
|
||||
|
@ -50,10 +50,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
struct wl_list link;
|
||||
|
||||
/* Pointer back to the compositor */
|
||||
MetaWaylandCompositor *compositor;
|
||||
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandFrameCallback;
|
||||
|
||||
@ -75,10 +71,8 @@ struct _MetaWaylandCompositor
|
||||
{
|
||||
struct wl_display *wayland_display;
|
||||
char *display_name;
|
||||
struct wl_event_loop *wayland_loop;
|
||||
ClutterActor *stage;
|
||||
GHashTable *outputs;
|
||||
GSource *wayland_event_source;
|
||||
struct wl_list frame_callbacks;
|
||||
|
||||
MetaXWaylandManager xwayland_manager;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@ -59,7 +60,10 @@ seat_get_touch (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t id)
|
||||
{
|
||||
/* Touch not supported */
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandTouch *touch = &seat->touch;
|
||||
|
||||
meta_wayland_touch_create_new_resource (touch, client, resource, id);
|
||||
}
|
||||
|
||||
static const struct wl_seat_interface seat_interface = {
|
||||
@ -84,7 +88,8 @@ bind_seat (struct wl_client *client,
|
||||
|
||||
wl_seat_send_capabilities (resource,
|
||||
WL_SEAT_CAPABILITY_POINTER |
|
||||
WL_SEAT_CAPABILITY_KEYBOARD);
|
||||
WL_SEAT_CAPABILITY_KEYBOARD |
|
||||
WL_SEAT_CAPABILITY_TOUCH);
|
||||
|
||||
if (version >= WL_SEAT_NAME_SINCE_VERSION)
|
||||
wl_seat_send_name (resource, "seat0");
|
||||
@ -95,14 +100,12 @@ meta_wayland_seat_new (struct wl_display *display)
|
||||
{
|
||||
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
|
||||
|
||||
seat->selection_data_source = NULL;
|
||||
wl_list_init (&seat->base_resource_list);
|
||||
wl_list_init (&seat->data_device_resource_list);
|
||||
|
||||
meta_wayland_pointer_init (&seat->pointer, display);
|
||||
meta_wayland_keyboard_init (&seat->keyboard, display);
|
||||
|
||||
seat->display = display;
|
||||
meta_wayland_touch_init (&seat->touch, display);
|
||||
meta_wayland_data_device_init (&seat->data_device);
|
||||
|
||||
wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
|
||||
|
||||
@ -120,6 +123,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
|
||||
{
|
||||
meta_wayland_pointer_release (&seat->pointer);
|
||||
meta_wayland_keyboard_release (&seat->keyboard);
|
||||
meta_wayland_touch_release (&seat->touch);
|
||||
|
||||
g_slice_free (MetaWaylandSeat, seat);
|
||||
}
|
||||
@ -142,6 +146,12 @@ meta_wayland_seat_update (MetaWaylandSeat *seat,
|
||||
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
case CLUTTER_TOUCH_END:
|
||||
meta_wayland_touch_update (&seat->touch, event);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -163,6 +173,10 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
return meta_wayland_keyboard_handle_event (&seat->keyboard,
|
||||
(const ClutterKeyEvent *) event);
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
case CLUTTER_TOUCH_END:
|
||||
return meta_wayland_touch_handle_event (&seat->touch, event);
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -177,6 +191,14 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat)
|
||||
meta_wayland_pointer_repick (&seat->pointer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
|
||||
{
|
||||
|
@ -26,35 +26,19 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
|
||||
struct _MetaWaylandDataOffer
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_listener source_destroy_listener;
|
||||
};
|
||||
|
||||
struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
};
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-touch.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
|
||||
struct _MetaWaylandSeat
|
||||
{
|
||||
struct wl_list base_resource_list;
|
||||
|
||||
uint32_t selection_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
|
||||
struct wl_list data_device_resource_list;
|
||||
MetaWaylandPointer pointer;
|
||||
MetaWaylandKeyboard keyboard;
|
||||
|
||||
struct wl_display *display;
|
||||
MetaWaylandTouch touch;
|
||||
MetaWaylandDataDevice data_device;
|
||||
};
|
||||
|
||||
void meta_wayland_seat_init (MetaWaylandCompositor *compositor);
|
||||
@ -67,6 +51,9 @@ void meta_wayland_seat_update (MetaWaylandSeat *seat,
|
||||
gboolean meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_seat_repick (MetaWaylandSeat *seat);
|
||||
void meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat);
|
||||
|
||||
|
@ -163,33 +163,88 @@ cursor_surface_commit (MetaWaylandSurface *surface,
|
||||
}
|
||||
|
||||
static void
|
||||
toplevel_surface_commit (MetaWaylandSurface *surface,
|
||||
calculate_surface_window_geometry (MetaWaylandSurface *surface,
|
||||
MetaRectangle *total_geometry,
|
||||
float parent_x,
|
||||
float parent_y)
|
||||
{
|
||||
ClutterActor *surface_actor = CLUTTER_ACTOR (surface->surface_actor);
|
||||
MetaRectangle geom;
|
||||
float x, y;
|
||||
GList *l;
|
||||
|
||||
/* Unmapped surfaces don't count. */
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (surface_actor))
|
||||
return;
|
||||
|
||||
/* XXX: Is there a better way to do this using Clutter APIs? */
|
||||
clutter_actor_get_position (surface_actor, &x, &y);
|
||||
|
||||
geom.x = parent_x + x;
|
||||
geom.y = parent_x + y;
|
||||
geom.width = cogl_texture_get_width (surface->buffer->texture);
|
||||
geom.height = cogl_texture_get_height (surface->buffer->texture);
|
||||
|
||||
meta_rectangle_union (total_geometry, &geom, total_geometry);
|
||||
|
||||
for (l = surface->subsurfaces; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = l->data;
|
||||
calculate_surface_window_geometry (subsurface, total_geometry, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
toplevel_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
if (pending->newly_attached)
|
||||
MetaWindow *window = surface->window;
|
||||
|
||||
/* Sanity check. */
|
||||
if (surface->buffer == NULL)
|
||||
{
|
||||
MetaWindow *window = surface->window;
|
||||
MetaWaylandBuffer *buffer = pending->buffer;
|
||||
|
||||
meta_window_set_surface_mapped (window, buffer != NULL);
|
||||
/* We resize X based surfaces according to X events */
|
||||
if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
int new_width, new_height;
|
||||
|
||||
new_width = cogl_texture_get_width (buffer->texture);
|
||||
new_height = cogl_texture_get_height (buffer->texture);
|
||||
|
||||
if (new_width != window->rect.width ||
|
||||
new_height != window->rect.height ||
|
||||
pending->dx != 0 ||
|
||||
pending->dy != 0)
|
||||
meta_window_wayland_move_resize (window, new_width, new_height, pending->dx, pending->dy);
|
||||
}
|
||||
wl_resource_post_error (surface->resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"Cannot commit a NULL buffer to an xdg_surface");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pending->frame_extents_changed)
|
||||
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
|
||||
/* We resize X based surfaces according to X events */
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
MetaRectangle geom;
|
||||
|
||||
if (pending->has_new_geometry)
|
||||
{
|
||||
/* If we have new geometry, use it. */
|
||||
geom = pending->new_geometry;
|
||||
surface->has_set_geometry = TRUE;
|
||||
}
|
||||
else if (!surface->has_set_geometry)
|
||||
{
|
||||
/* If the surface has never set any geometry, calculate
|
||||
* a default one unioning the surface and all subsurfaces together. */
|
||||
calculate_surface_window_geometry (surface, &geom, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, keep the geometry the same. */
|
||||
|
||||
/* XXX: We don't store the geometry in any consistent place
|
||||
* right now, so we can't re-fetch it. We should change
|
||||
* meta_window_wayland_move_resize. */
|
||||
|
||||
/* XXX: This is the common case. Recognize it to prevent
|
||||
* a warning. */
|
||||
if (pending->dx == 0 && pending->dy == 0)
|
||||
return;
|
||||
|
||||
g_warning ("XXX: Attach-initiated move without a new geometry. This is unimplemented right now.");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_window_wayland_move_resize (window, geom, pending->dx, pending->dy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -216,7 +271,7 @@ pending_state_init (MetaWaylandPendingState *state)
|
||||
state->buffer_destroy_listener.notify = surface_handle_pending_buffer_destroy;
|
||||
wl_list_init (&state->frame_callback_list);
|
||||
|
||||
state->frame_extents_changed = FALSE;
|
||||
state->has_new_geometry = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -262,22 +317,18 @@ static void
|
||||
subsurface_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
if (pending->newly_attached)
|
||||
{
|
||||
MetaSurfaceActor *surface_actor = surface->surface_actor;
|
||||
MetaWaylandBuffer *buffer = pending->buffer;
|
||||
float x, y;
|
||||
MetaSurfaceActor *surface_actor = surface->surface_actor;
|
||||
float x, y;
|
||||
|
||||
if (buffer != NULL)
|
||||
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
|
||||
else
|
||||
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
|
||||
if (surface->buffer != NULL)
|
||||
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
|
||||
else
|
||||
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
|
||||
|
||||
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
||||
x += pending->dx;
|
||||
y += pending->dy;
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
|
||||
}
|
||||
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
||||
x += pending->dx;
|
||||
y += pending->dy;
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -416,16 +467,13 @@ wl_surface_attach (struct wl_client *client,
|
||||
else
|
||||
buffer = NULL;
|
||||
|
||||
if (surface->buffer == buffer)
|
||||
return;
|
||||
|
||||
if (surface->pending.buffer)
|
||||
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
|
||||
|
||||
surface->pending.newly_attached = TRUE;
|
||||
surface->pending.buffer = buffer;
|
||||
surface->pending.dx = dx;
|
||||
surface->pending.dy = dy;
|
||||
surface->pending.buffer = buffer;
|
||||
surface->pending.newly_attached = TRUE;
|
||||
|
||||
if (buffer)
|
||||
wl_signal_add (&buffer->destroy_signal,
|
||||
@ -473,7 +521,6 @@ wl_surface_frame (struct wl_client *client,
|
||||
return;
|
||||
|
||||
callback = g_slice_new0 (MetaWaylandFrameCallback);
|
||||
callback->compositor = surface->compositor;
|
||||
callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
|
||||
wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
|
||||
|
||||
@ -733,23 +780,6 @@ xdg_surface_set_parent (struct wl_client *client,
|
||||
meta_window_set_transient_for (surface->window, transient_for);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_margin (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
int32_t left_margin,
|
||||
int32_t right_margin,
|
||||
int32_t top_margin,
|
||||
int32_t bottom_margin)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->pending.frame_extents_changed = TRUE;
|
||||
surface->pending.frame_extents.left = left_margin;
|
||||
surface->pending.frame_extents.right = right_margin;
|
||||
surface->pending.frame_extents.top = top_margin;
|
||||
surface->pending.frame_extents.bottom = bottom_margin;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_title (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -775,8 +805,8 @@ xdg_surface_show_window_menu (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t serial,
|
||||
uint32_t x,
|
||||
uint32_t y)
|
||||
int32_t x,
|
||||
int32_t y)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
@ -880,6 +910,20 @@ xdg_surface_ack_configure (struct wl_client *client,
|
||||
* client gets the new state. */
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_window_geometry (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
surface->pending.has_new_geometry = TRUE;
|
||||
surface->pending.new_geometry.x = x;
|
||||
surface->pending.new_geometry.y = y;
|
||||
surface->pending.new_geometry.width = width;
|
||||
surface->pending.new_geometry.height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
@ -924,13 +968,13 @@ xdg_surface_set_minimized (struct wl_client *client,
|
||||
static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
|
||||
xdg_surface_destroy,
|
||||
xdg_surface_set_parent,
|
||||
xdg_surface_set_margin,
|
||||
xdg_surface_set_title,
|
||||
xdg_surface_set_app_id,
|
||||
xdg_surface_show_window_menu,
|
||||
xdg_surface_move,
|
||||
xdg_surface_resize,
|
||||
xdg_surface_ack_configure,
|
||||
xdg_surface_set_window_geometry,
|
||||
xdg_surface_set_maximized,
|
||||
xdg_surface_unset_maximized,
|
||||
xdg_surface_set_fullscreen,
|
||||
@ -1072,20 +1116,17 @@ bind_xdg_shell (struct wl_client *client,
|
||||
guint32 version,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
XdgShell *xdg_shell;
|
||||
|
||||
if (version != 1)
|
||||
if (version != META_XDG_SHELL_VERSION)
|
||||
{
|
||||
g_warning ("using xdg-shell without stable version 1\n");
|
||||
g_warning ("using xdg-shell without stable version %d\n", META_XDG_SHELL_VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
xdg_shell = g_slice_new (XdgShell);
|
||||
|
||||
resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_xdg_shell_interface, data, NULL);
|
||||
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
|
||||
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, META_XDG_SHELL_VERSION, id);
|
||||
wl_resource_set_implementation (xdg_shell->resource, &meta_wayland_xdg_shell_interface, data, NULL);
|
||||
|
||||
xdg_shell->client_destroy_listener.notify = xdg_shell_handle_client_destroy;
|
||||
@ -1351,13 +1392,13 @@ gtk_surface_destructor (struct wl_resource *resource)
|
||||
|
||||
static void
|
||||
set_dbus_properties (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *application_id,
|
||||
const char *app_menu_path,
|
||||
const char *menubar_path,
|
||||
const char *window_object_path,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name)
|
||||
struct wl_resource *resource,
|
||||
const char *application_id,
|
||||
const char *app_menu_path,
|
||||
const char *menubar_path,
|
||||
const char *window_object_path,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
@ -1383,9 +1424,9 @@ static const struct gtk_surface_interface meta_wayland_gtk_surface_interface = {
|
||||
|
||||
static void
|
||||
get_gtk_surface (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
guint32 id,
|
||||
struct wl_resource *surface_resource)
|
||||
struct wl_resource *resource,
|
||||
guint32 id,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
@ -1409,14 +1450,14 @@ static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = {
|
||||
|
||||
static void
|
||||
bind_gtk_shell (struct wl_client *client,
|
||||
void *data,
|
||||
guint32 version,
|
||||
guint32 id)
|
||||
void *data,
|
||||
guint32 version,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, >k_shell_interface,
|
||||
MIN (META_GTK_SHELL_VERSION, version), id);
|
||||
MIN (META_GTK_SHELL_VERSION, version), id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
|
||||
|
||||
/* FIXME: ask the plugin */
|
||||
@ -1677,11 +1718,10 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
}
|
||||
|
||||
pending_state_init (&surface->sub.pending);
|
||||
surface->sub.synchronous = TRUE;
|
||||
surface->sub.parent = parent;
|
||||
surface->sub.parent_destroy_listener.notify =
|
||||
surface_handle_parent_surface_destroyed;
|
||||
wl_resource_add_destroy_listener (parent->resource,
|
||||
&surface->sub.parent_destroy_listener);
|
||||
surface->sub.parent_destroy_listener.notify = surface_handle_parent_surface_destroyed;
|
||||
wl_resource_add_destroy_listener (parent->resource, &surface->sub.parent_destroy_listener);
|
||||
parent->subsurfaces = g_list_append (parent->subsurfaces, surface);
|
||||
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (parent->surface_actor),
|
||||
@ -1704,7 +1744,7 @@ bind_subcompositor (struct wl_client *client,
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &wl_subcompositor_interface,
|
||||
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
|
||||
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, data, NULL);
|
||||
}
|
||||
|
||||
@ -1712,19 +1752,21 @@ void
|
||||
meta_wayland_shell_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&xdg_shell_interface, 1,
|
||||
compositor, bind_xdg_shell) == NULL)
|
||||
&xdg_shell_interface,
|
||||
META_XDG_SHELL_VERSION,
|
||||
compositor, bind_xdg_shell) == NULL)
|
||||
g_error ("Failed to register a global xdg-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&wl_shell_interface, 1,
|
||||
compositor, bind_wl_shell) == NULL)
|
||||
&wl_shell_interface,
|
||||
META_WL_SHELL_VERSION,
|
||||
compositor, bind_wl_shell) == NULL)
|
||||
g_error ("Failed to register a global wl-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
>k_shell_interface,
|
||||
META_GTK_SHELL_VERSION,
|
||||
compositor, bind_gtk_shell) == NULL)
|
||||
>k_shell_interface,
|
||||
META_GTK_SHELL_VERSION,
|
||||
compositor, bind_gtk_shell) == NULL)
|
||||
g_error ("Failed to register a global gtk-shell object");
|
||||
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
@ -1763,8 +1805,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
|
||||
|
||||
void
|
||||
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int new_width,
|
||||
int new_height)
|
||||
int new_width,
|
||||
int new_height)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
|
@ -61,8 +61,8 @@ typedef struct
|
||||
/* wl_surface.frame */
|
||||
struct wl_list frame_callback_list;
|
||||
|
||||
gboolean frame_extents_changed;
|
||||
GtkBorder frame_extents;
|
||||
MetaRectangle new_geometry;
|
||||
gboolean has_new_geometry;
|
||||
} MetaWaylandPendingState;
|
||||
|
||||
typedef struct
|
||||
@ -109,6 +109,8 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
gboolean has_set_geometry;
|
||||
|
||||
/* All the pending state that wl_surface.commit will apply. */
|
||||
MetaWaylandPendingState pending;
|
||||
};
|
||||
|
548
src/wayland/meta-wayland-touch.c
Normal file
548
src/wayland/meta-wayland-touch.c
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
struct _MetaWaylandTouchSurface
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWaylandTouch *touch;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
struct wl_list resource_list;
|
||||
gint touch_count;
|
||||
};
|
||||
|
||||
struct _MetaWaylandTouchInfo
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface;
|
||||
guint32 slot_serial;
|
||||
gint32 slot;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
guint updated : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination, struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
touch_surface_free (gpointer data)
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface = data;
|
||||
MetaWaylandTouch *touch = touch_surface->touch;
|
||||
|
||||
move_resources (&touch->resource_list,
|
||||
&touch_surface->resource_list);
|
||||
wl_list_remove (&touch_surface->surface_destroy_listener.link);
|
||||
g_free (touch_surface);
|
||||
}
|
||||
|
||||
static MetaWaylandTouchSurface *
|
||||
touch_surface_increment_touch (MetaWaylandTouchSurface *surface)
|
||||
{
|
||||
surface->touch_count++;
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
touch_surface_decrement_touch (MetaWaylandTouchSurface *touch_surface)
|
||||
{
|
||||
touch_surface->touch_count--;
|
||||
|
||||
if (touch_surface->touch_count == 0)
|
||||
{
|
||||
/* Now that there are no touches on the surface, free the
|
||||
* MetaWaylandTouchSurface, the memory is actually owned by
|
||||
* the touch_surface->touch_surfaces hashtable, so remove the
|
||||
* item from there.
|
||||
*/
|
||||
MetaWaylandTouch *touch = touch_surface->touch;
|
||||
g_hash_table_remove (touch->touch_surfaces, touch_surface->surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface = wl_container_of (listener, touch_surface, surface_destroy_listener);
|
||||
MetaWaylandSurface *surface = touch_surface->surface;
|
||||
MetaWaylandTouch *touch = touch_surface->touch;
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, touch->touches);
|
||||
|
||||
/* Destroy all touches on the surface, this indirectly drops touch_count
|
||||
* on the touch_surface to 0, also freeing touch_surface and removing
|
||||
* from the touch_surfaces hashtable.
|
||||
*/
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
|
||||
{
|
||||
if (touch_info->touch_surface == touch_surface)
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
|
||||
/* Ensure the surface no longer exists */
|
||||
g_assert (g_hash_table_remove (touch->touch_surfaces, surface) == FALSE);
|
||||
}
|
||||
|
||||
static MetaWaylandTouchSurface *
|
||||
touch_surface_get (MetaWaylandTouch *touch,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface;
|
||||
|
||||
touch_surface = g_hash_table_lookup (touch->touch_surfaces, surface);
|
||||
|
||||
if (touch_surface)
|
||||
return touch_surface_increment_touch (touch_surface);
|
||||
|
||||
/* Create a new one for this surface */
|
||||
touch_surface = g_new0 (MetaWaylandTouchSurface, 1);
|
||||
touch_surface->touch = touch;
|
||||
touch_surface->surface = surface;
|
||||
touch_surface->touch_count = 1;
|
||||
touch_surface->surface_destroy_listener.notify = touch_handle_surface_destroy;
|
||||
wl_resource_add_destroy_listener (touch_surface->surface->resource,
|
||||
&touch_surface->surface_destroy_listener);
|
||||
|
||||
wl_list_init (&touch_surface->resource_list);
|
||||
move_resources_for_client (&touch_surface->resource_list,
|
||||
&touch->resource_list,
|
||||
wl_resource_get_client (touch_surface->surface->resource));
|
||||
|
||||
g_hash_table_insert (touch->touch_surfaces, surface, touch_surface);
|
||||
|
||||
return touch_surface;
|
||||
}
|
||||
|
||||
static MetaWaylandTouchInfo *
|
||||
touch_get_info (MetaWaylandTouch *touch,
|
||||
ClutterEventSequence *sequence,
|
||||
gboolean create)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
|
||||
touch_info = g_hash_table_lookup (touch->touches, sequence);
|
||||
|
||||
if (!touch_info && create)
|
||||
{
|
||||
touch_info = g_new0 (MetaWaylandTouchInfo, 1);
|
||||
touch_info->slot = clutter_evdev_event_sequence_get_slot (sequence);
|
||||
g_hash_table_insert (touch->touches, sequence, touch_info);
|
||||
}
|
||||
|
||||
return touch_info;
|
||||
}
|
||||
|
||||
static void
|
||||
touch_get_relative_coordinates (MetaWaylandTouch *touch,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event,
|
||||
gfloat *x,
|
||||
gfloat *y)
|
||||
{
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
|
||||
if (surface->surface_actor)
|
||||
{
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface->surface_actor),
|
||||
event_x, event_y,
|
||||
&event_x, &event_y);
|
||||
}
|
||||
|
||||
*x = event_x;
|
||||
*y = event_y;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
meta_wayland_touch_update (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
ClutterEventSequence *sequence;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN)
|
||||
{
|
||||
MetaWaylandSurface *surface = NULL;
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_event_get_source (event);
|
||||
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
||||
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
touch_info = touch_get_info (touch, sequence, TRUE);
|
||||
touch_info->touch_surface = touch_surface_get (touch, surface);
|
||||
}
|
||||
else
|
||||
touch_info = touch_get_info (touch, sequence, FALSE);
|
||||
|
||||
if (!touch_info)
|
||||
return;
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN ||
|
||||
event->type == CLUTTER_TOUCH_END)
|
||||
{
|
||||
MetaWaylandSurface *surface = touch_info->touch_surface->surface;
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
|
||||
touch_info->slot_serial = wl_display_next_serial (display);
|
||||
}
|
||||
|
||||
touch_get_relative_coordinates (touch, touch_info->touch_surface->surface,
|
||||
event, &touch_info->x, &touch_info->y);
|
||||
touch_info->updated = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_begin (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
ClutterEventSequence *sequence;
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
touch_info = touch_get_info (touch, sequence, FALSE);
|
||||
|
||||
if (!touch_info)
|
||||
return;
|
||||
|
||||
l = &touch_info->touch_surface->resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
{
|
||||
wl_touch_send_down (resource, touch_info->slot_serial,
|
||||
clutter_event_get_time (event),
|
||||
touch_info->touch_surface->surface->resource,
|
||||
touch_info->slot,
|
||||
wl_fixed_from_double (touch_info->x),
|
||||
wl_fixed_from_double (touch_info->y));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_update (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
ClutterEventSequence *sequence;
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
touch_info = touch_get_info (touch, sequence, FALSE);
|
||||
|
||||
if (!touch_info)
|
||||
return;
|
||||
|
||||
l = &touch_info->touch_surface->resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
{
|
||||
wl_touch_send_motion (resource,
|
||||
clutter_event_get_time (event),
|
||||
touch_info->slot,
|
||||
wl_fixed_from_double (touch_info->x),
|
||||
wl_fixed_from_double (touch_info->y));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_end (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
ClutterEventSequence *sequence;
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
touch_info = touch_get_info (touch, sequence, FALSE);
|
||||
|
||||
if (!touch_info)
|
||||
return;
|
||||
|
||||
l = &touch_info->touch_surface->resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
{
|
||||
wl_touch_send_up (resource, touch_info->slot_serial,
|
||||
clutter_event_get_time (event),
|
||||
touch_info->slot);
|
||||
}
|
||||
|
||||
g_hash_table_remove (touch->touches, sequence);
|
||||
}
|
||||
|
||||
static GList *
|
||||
touch_get_surfaces (MetaWaylandTouch *touch,
|
||||
gboolean only_updated)
|
||||
{
|
||||
MetaWaylandTouchInfo *touch_info;
|
||||
GList *surfaces = NULL;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, touch->touches);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
|
||||
{
|
||||
if (only_updated && !touch_info->updated)
|
||||
continue;
|
||||
if (g_list_find (surfaces, touch_info->touch_surface))
|
||||
continue;
|
||||
|
||||
surfaces = g_list_prepend (surfaces, touch_info->touch_surface);
|
||||
touch_info->updated = FALSE;
|
||||
}
|
||||
|
||||
return g_list_reverse (surfaces);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_send_frame_event (MetaWaylandTouch *touch)
|
||||
{
|
||||
GList *surfaces, *s;
|
||||
|
||||
surfaces = s = touch_get_surfaces (touch, TRUE);
|
||||
|
||||
for (s = surfaces; s; s = s->next)
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface = s->data;
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
l = &touch_surface->resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
{
|
||||
wl_touch_send_frame (resource);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (surfaces);
|
||||
}
|
||||
|
||||
static void
|
||||
check_send_frame_event (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
gint32 slot;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
slot = clutter_evdev_event_sequence_get_slot (sequence);
|
||||
touch->frame_slots &= ~(1 << slot);
|
||||
|
||||
if (touch->frame_slots == 0)
|
||||
touch_send_frame_event (touch);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
handle_touch_begin (touch, event);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
handle_touch_update (touch, event);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_END:
|
||||
handle_touch_end (touch, event);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
check_send_frame_event (touch, event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
touch_release (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct wl_touch_interface touch_interface = {
|
||||
touch_release,
|
||||
};
|
||||
|
||||
static void
|
||||
touch_info_free (MetaWaylandTouchInfo *touch_info)
|
||||
{
|
||||
touch_surface_decrement_touch (touch_info->touch_surface);
|
||||
g_free (touch_info);
|
||||
}
|
||||
|
||||
static void
|
||||
touch_handle_cancel_event (MetaWaylandTouch *touch,
|
||||
struct libinput_event *event)
|
||||
{
|
||||
GList *surfaces, *s;
|
||||
|
||||
surfaces = s = touch_get_surfaces (touch, FALSE);
|
||||
|
||||
while (s)
|
||||
{
|
||||
MetaWaylandTouchSurface *touch_surface = s->data;
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
l = &touch_surface->resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
wl_touch_send_cancel (resource);
|
||||
}
|
||||
|
||||
g_hash_table_remove_all (touch->touches);
|
||||
g_list_free (surfaces);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
evdev_filter_func (struct libinput_event *event,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWaylandTouch *touch = data;
|
||||
|
||||
switch (libinput_event_get_type (event))
|
||||
{
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION: {
|
||||
struct libinput_event_touch *touch_event;
|
||||
int32_t slot;
|
||||
|
||||
touch_event = libinput_event_get_touch_event (event);
|
||||
slot = libinput_event_touch_get_slot (touch_event);
|
||||
|
||||
/* XXX: Could theoretically overflow, 64 slots should be
|
||||
* enough for most hw/usecases though.
|
||||
*/
|
||||
touch->frame_slots |= (1 << slot);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
/* Clutter translates this into individual CLUTTER_TOUCH_CANCEL events,
|
||||
* which are not so useful when sending a global signal as the protocol
|
||||
* requires.
|
||||
*/
|
||||
touch_handle_cancel_event (touch, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_touch_init (MetaWaylandTouch *touch,
|
||||
struct wl_display *display)
|
||||
{
|
||||
ClutterDeviceManager *manager;
|
||||
|
||||
memset (touch, 0, sizeof *touch);
|
||||
|
||||
touch->display = display;
|
||||
touch->touch_surfaces = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) touch_surface_free);
|
||||
touch->touches = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) touch_info_free);
|
||||
|
||||
wl_list_init (&touch->resource_list);
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
touch->device = clutter_device_manager_get_core_device (manager, CLUTTER_TOUCHSCREEN_DEVICE);
|
||||
clutter_evdev_add_filter (evdev_filter_func, touch, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_touch_release (MetaWaylandTouch *touch)
|
||||
{
|
||||
clutter_evdev_remove_filter (evdev_filter_func, touch);
|
||||
g_hash_table_unref (touch->touch_surfaces);
|
||||
g_hash_table_unref (touch->touches);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *cr;
|
||||
|
||||
cr = wl_resource_create (client, &wl_touch_interface,
|
||||
MIN (META_WL_TOUCH_VERSION, wl_resource_get_version (seat_resource)), id);
|
||||
wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource);
|
||||
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
|
||||
}
|
62
src/wayland/meta-wayland-touch.h
Normal file
62
src/wayland/meta-wayland-touch.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Wayland Support
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_TOUCH_H
|
||||
#define META_WAYLAND_TOUCH_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWaylandTouchSurface MetaWaylandTouchSurface;
|
||||
typedef struct _MetaWaylandTouchInfo MetaWaylandTouchInfo;
|
||||
|
||||
struct _MetaWaylandTouch
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct wl_list resource_list;
|
||||
|
||||
GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */
|
||||
GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */
|
||||
|
||||
ClutterInputDevice *device;
|
||||
guint64 frame_slots;
|
||||
};
|
||||
|
||||
void meta_wayland_touch_init (MetaWaylandTouch *touch,
|
||||
struct wl_display *display);
|
||||
|
||||
void meta_wayland_touch_release (MetaWaylandTouch *touch);
|
||||
|
||||
void meta_wayland_touch_update (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event);
|
||||
|
||||
gboolean meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id);
|
||||
|
||||
#endif /* META_WAYLAND_TOUCH_H */
|
@ -27,8 +27,9 @@ typedef struct _MetaWaylandPointer MetaWaylandPointer;
|
||||
typedef struct _MetaWaylandPointerGrab MetaWaylandPointerGrab;
|
||||
typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
|
||||
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
|
||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||
typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
||||
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
|
||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||
|
||||
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
|
||||
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
|
||||
|
@ -37,6 +37,7 @@
|
||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||
#define META_WL_COMPOSITOR_VERSION 3
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
|
||||
#define META_XDG_SHELL_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 3
|
||||
#define META_WL_OUTPUT_VERSION 2
|
||||
@ -51,7 +52,7 @@
|
||||
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
|
||||
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
|
||||
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
|
||||
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
|
||||
#define META_WL_TOUCH_VERSION 3 /* from wl_seat */
|
||||
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
|
||||
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
|
||||
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user