Compare commits
19 Commits
configurab
...
override-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a0de6dfd3 | ||
|
|
2bf0b2b6de | ||
|
|
eed2a2d324 | ||
|
|
9828007a02 | ||
|
|
1f890672bb | ||
|
|
ef966854d5 | ||
|
|
7309b6cfe3 | ||
|
|
3705a224f0 | ||
|
|
2ebedb822d | ||
|
|
d6576d9b70 | ||
|
|
6516c19ec5 | ||
|
|
5518fee61c | ||
|
|
ace0521cba | ||
|
|
0091a3aab5 | ||
|
|
268b92a4ec | ||
|
|
29bb4c27e3 | ||
|
|
bd3bdc51b9 | ||
|
|
0123dab87a | ||
|
|
413acc9574 |
31
.gitignore
vendored
31
.gitignore
vendored
@@ -13,22 +13,17 @@ config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/mutter-wm.desktop
|
||||
src/mutter.desktop
|
||||
src/metacity-wm.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
@@ -43,18 +38,19 @@ POTFILES
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmutter-private.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
mutter.desktop
|
||||
mutter.schemas
|
||||
libmetacity-private.pc
|
||||
metacity
|
||||
metacity-dialog
|
||||
metacity-theme-viewer
|
||||
metacity.desktop
|
||||
metacity.schemas
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
metacity-grayscale
|
||||
metacity-mag
|
||||
metacity-message
|
||||
metacity-window-demo
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
@@ -62,8 +58,3 @@ test-size-hints
|
||||
wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
||||
src/mutter-enum-types.[ch]
|
||||
src/stamp-mutter-enum-types.h
|
||||
src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/mutter-plugins.pc
|
||||
|
||||
2
README
2
README
@@ -20,7 +20,7 @@ libstartup-notification at
|
||||
http://www.freedesktop.org/software/startup-notification/ or on the
|
||||
GNOME ftp site. You also need GConf 1.2 (unless building a funky
|
||||
extra-small embedded metacity with --disable-gconf, see below).
|
||||
You need Clutter 1.0. You need gobject-introspection 0.6.3.
|
||||
You need Clutter 0.9.3. You need gobject-introspection 0.6.3.
|
||||
|
||||
REPORTING BUGS AND SUBMITTING PATCHES
|
||||
===
|
||||
|
||||
275
configure.in
275
configure.in
@@ -1,13 +1,15 @@
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_version], [2])
|
||||
m4_define([mutter_minor_version], [91])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
m4_define([mutter_minor_version], [27])
|
||||
# Fibonacci sequence for micro version numbering:
|
||||
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
|
||||
m4_define([mutter_plugin_api_version], [3])
|
||||
m4_define([mutter_plugin_api_version], [2])
|
||||
|
||||
AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
@@ -15,8 +17,7 @@ AC_INIT([mutter], [mutter_version],
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
MUTTER_MAJOR_VERSION=mutter_major_version
|
||||
@@ -45,9 +46,6 @@ AC_HEADER_STDC
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||
AM_PATH_GLIB_2_0()
|
||||
|
||||
#### Integer sizes
|
||||
|
||||
AC_CHECK_SIZEOF(char)
|
||||
@@ -63,75 +61,68 @@ AC_C_BIGENDIAN
|
||||
|
||||
#### Warnings
|
||||
|
||||
# Stay command-line compatible with the gnome-common configure option. Here
|
||||
# minimum/yes/maximum are the same, however.
|
||||
AC_ARG_ENABLE(compile_warnings,
|
||||
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
|
||||
enable_compile_warnings=error)
|
||||
|
||||
changequote(,)dnl
|
||||
if test "$enable_compile_warnings" != no ; then
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
# case " $CFLAGS " in
|
||||
# *[\ \ ]-Wshadow[\ \ ]*) ;;
|
||||
# *) CFLAGS="$CFLAGS -Wshadow" ;;
|
||||
# esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
|
||||
*[\ \ ]-ansi[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -ansi" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
|
||||
*[\ \ ]-pedantic[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -pedantic" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wcast-align[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wcast-align" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
|
||||
esac
|
||||
|
||||
if test "$enable_compile_warnings" = error; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Werror[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Werror" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
GTK_MIN_VERSION=2.90.7
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
MUTTER_PC_MODULES="gtk+-3.0 >= $GTK_MIN_VERSION pango >= 1.2.0 cairo >= 1.10.0"
|
||||
MUTTER_PC_MODULES='gtk+-2.0 >= 2.10.0 pango >= 1.2.0'
|
||||
|
||||
AC_ARG_ENABLE(gconf,
|
||||
AC_HELP_STRING([--disable-gconf],
|
||||
@@ -162,21 +153,31 @@ AC_ARG_ENABLE(startup-notification,
|
||||
[disable mutter's startup notification support, for embedded/size-sensitive custom non-GNOME builds]),,
|
||||
enable_startup_notification=auto)
|
||||
|
||||
AC_ARG_WITH(introspection,
|
||||
AC_ARG_ENABLE(compositor,
|
||||
AC_HELP_STRING([--disable-compositor],
|
||||
[disable mutter's compositing manager]),,
|
||||
enable_compositor=auto)
|
||||
|
||||
AC_ARG_ENABLE(clutter,
|
||||
AC_HELP_STRING([--without-clutter],
|
||||
[disable the use of clutter for compositing]),,
|
||||
with_clutter=auto)
|
||||
|
||||
AC_ARG_ENABLE(introspection,
|
||||
AC_HELP_STRING([--without-introspection],
|
||||
[disable the use of GObject introspection]),,
|
||||
with_introspection=auto)
|
||||
|
||||
AC_ARG_WITH(libcanberra,
|
||||
AC_HELP_STRING([--without-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(render,
|
||||
AC_HELP_STRING([--disable-render],
|
||||
[disable mutter's use of the RENDER extension]),,
|
||||
enable_render=auto)
|
||||
|
||||
AC_ARG_ENABLE(shape,
|
||||
AC_HELP_STRING([--disable-shape],
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
@@ -188,11 +189,17 @@ AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
|
||||
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)
|
||||
# gtk_window_set_icon_name requires gtk2+-2.6.0
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0 >= $GTK_MIN_VERSION)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0 >= $GTK_MIN_VERSION)
|
||||
# GOptionEntry requires glib-2.6.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.6.0)
|
||||
# gtk_window_set_icon_name requires gtk2+-2.60
|
||||
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-2.0 >= 2.6.0)
|
||||
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-2.0 >= 2.6.0)
|
||||
|
||||
if $PKG_CONFIG --atleast-version 1.2.0 pangoxft; then
|
||||
echo "pangoxft found"
|
||||
else
|
||||
AC_MSG_ERROR("Pango 1.2.0 or greater based on Xft2 is required")
|
||||
fi
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -224,28 +231,43 @@ else
|
||||
echo "Building without libstartup-notification"
|
||||
fi
|
||||
|
||||
have_libcanberra=no
|
||||
AC_MSG_CHECKING([libcanberra-gtk])
|
||||
if test x$with_libcanberra = xno ; then
|
||||
AC_MSG_RESULT([disabled])
|
||||
else
|
||||
if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then
|
||||
have_libcanberra=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK"
|
||||
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test x$with_libcanberra = xyes ; then
|
||||
AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
## init this, it gets set either in the compositor check below
|
||||
## or the render-specific check later
|
||||
have_xrender=no
|
||||
|
||||
XCOMPOSITE_VERSION=0.2
|
||||
if test x$enable_compositor = xyes; then
|
||||
have_xcomposite=yes
|
||||
elif test x$enable_compositor = xauto; then
|
||||
echo "Building compositing manager by default now."
|
||||
have_xcomposite=yes
|
||||
else
|
||||
have_xcomposite=no
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
|
||||
if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then
|
||||
if test x$with_clutter = xyes; then
|
||||
have_xcomposite=yes
|
||||
have_clutter=yes
|
||||
elif test x$with_clutter = xauto; then
|
||||
echo "Building clutter compositing manager by default now."
|
||||
have_xcomposite=yes
|
||||
have_clutter=yes
|
||||
else
|
||||
have_clutter=no
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(WITH_CLUTTER, test "$have_clutter" = "yes")
|
||||
|
||||
if test x$have_xcomposite = xyes; then
|
||||
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
|
||||
if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_ERROR([no. Use --disable-compositor to disable.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$have_xcomposite = xyes; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcomposite >= $XCOMPOSITE_VERSION xfixes xrender xdamage"
|
||||
AC_DEFINE(HAVE_COMPOSITE_EXTENSIONS, 1, [Building with compositing manager support])
|
||||
echo "Building with compositing manager"
|
||||
@@ -253,13 +275,42 @@ if $PKG_CONFIG --atleast-version $XCOMPOSITE_VERSION xcomposite; then
|
||||
## force on render also
|
||||
have_xrender=yes
|
||||
else
|
||||
AC_MSG_ERROR([no. Mutter requires the Xcomposite extension to build.])
|
||||
echo "Building without compositing manager"
|
||||
fi
|
||||
|
||||
CLUTTER_VERSION=1.2.0
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
## if no compositor, still possibly enable render
|
||||
if test x$have_xcomposite = xno; then
|
||||
XRENDER_VERSION=0.0
|
||||
AC_MSG_CHECKING([xrender >= $XRENDER_VERSION])
|
||||
if $PKG_CONFIG --atleast-version $XRENDER_VERSION xrender; then
|
||||
have_xrender=yes
|
||||
else
|
||||
have_xrender=no
|
||||
fi
|
||||
AC_MSG_RESULT($have_xrender)
|
||||
|
||||
if test x$enable_render = xyes; then
|
||||
have_xrender=yes
|
||||
echo "Render support forced on"
|
||||
elif test x$enable_render = xauto; then
|
||||
true
|
||||
else
|
||||
have_xrender=no
|
||||
fi
|
||||
|
||||
if test x$have_xrender = xyes; then
|
||||
echo "Building with Render"
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xrender >= $XRENDER_VERSION"
|
||||
fi
|
||||
fi ## have_composite
|
||||
|
||||
if test x$have_xrender = xyes; then
|
||||
AC_DEFINE(HAVE_RENDER, , [Building with Render extension support])
|
||||
fi
|
||||
|
||||
CLUTTER_PACKAGE=clutter-0.9
|
||||
AC_SUBST(CLUTTER_PACKAGE)
|
||||
if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
|
||||
if test x$have_clutter = xyes; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CLUTTER_PACKAGE "
|
||||
PKG_CHECK_MODULES(CLUTTER, $CLUTTER_PACKAGE)
|
||||
AC_DEFINE(WITH_CLUTTER, , [Building with Clutter compositor])
|
||||
@@ -276,12 +327,10 @@ if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
|
||||
AC_DEFINE(HAVE_GLX_TEXTURE_PIXMAP, ,
|
||||
[Is ClutterGLXTexturePixmap available?])
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR([no. Mutter requires Clutter version $CLUTTER_VERSION.])
|
||||
fi
|
||||
|
||||
if test x$with_introspection != xno; then
|
||||
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0 >= 0.9.5, have_introspection=yes, have_introspection=no)
|
||||
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0, have_introspection=yes, have_introspection=no)
|
||||
if test x$have_introspection=xyes; then
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
|
||||
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
|
||||
@@ -444,7 +493,7 @@ fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
found_sm=no
|
||||
@@ -512,8 +561,10 @@ if test "x$enable_debug" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -g -O"
|
||||
fi
|
||||
|
||||
# For fix-meta-rectangle.py
|
||||
AM_PATH_PYTHON([2.5])
|
||||
# Warnings are there for a reason
|
||||
if test "x$GCC" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall -Werror -ansi"
|
||||
fi
|
||||
|
||||
# Use gnome-doc-utils:
|
||||
GNOME_DOC_INIT([0.8.0])
|
||||
@@ -527,7 +578,7 @@ src/wm-tester/Makefile
|
||||
src/libmutter-private.pc
|
||||
src/mutter-plugins.pc
|
||||
src/tools/Makefile
|
||||
src/compositor/plugins/Makefile
|
||||
src/compositor/mutter/plugins/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
@@ -550,7 +601,7 @@ fi
|
||||
|
||||
dnl ==========================================================================
|
||||
echo "
|
||||
mutter-$VERSION
|
||||
mutter-$VERSION:
|
||||
|
||||
prefix: ${prefix}
|
||||
source code location: ${srcdir}
|
||||
@@ -560,18 +611,20 @@ mutter-$VERSION
|
||||
XFree86 Xinerama: ${use_xfree_xinerama}
|
||||
Solaris Xinerama: ${use_solaris_xinerama}
|
||||
Startup notification: ${have_startup_notification}
|
||||
libcanberra: ${have_libcanberra}
|
||||
Compositing manager: ${have_xcomposite}
|
||||
Introspection: ${have_introspection}
|
||||
Session management: ${found_sm}
|
||||
Shape extension: ${found_shape}
|
||||
Resize-and-rotate: ${found_randr}
|
||||
Xsync: ${found_xsync}
|
||||
Render: ${have_xrender}
|
||||
Xcursor: ${have_xcursor}
|
||||
Clutter: ${have_clutter}
|
||||
"
|
||||
|
||||
|
||||
MUTTER_MINOR_VERSION=mutter_minor_version
|
||||
if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then
|
||||
stable_version=`expr $MUTTER_MINOR_VERSION - 1`
|
||||
if test $(( $(echo $MUTTER_MINOR_VERSION) %2)) == "1"; then
|
||||
stable_version=$(( ($MUTTER_MINOR_VERSION / 2) * 2))
|
||||
echo "This is the UNSTABLE branch of mutter"
|
||||
echo -n "Use 2.$stable_version.x for stable "
|
||||
echo "(gnome-2-$stable_version branch in Subversion)"
|
||||
|
||||
@@ -4,7 +4,6 @@ of the theme format, and a given theme can support more than one format.
|
||||
Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml
|
||||
(original metacity format)
|
||||
Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml
|
||||
Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml
|
||||
|
||||
The subdirectory name is "metacity-1" in all versions.
|
||||
|
||||
@@ -22,41 +21,6 @@ This document has separate sections for each format version. You may
|
||||
want to read the document in reverse order, since the base features
|
||||
are discussed under version 1.
|
||||
|
||||
New Features in Theme Format Version 3.1
|
||||
========================================
|
||||
|
||||
Additional predefined variables are added for positioning expressions:
|
||||
|
||||
frame_x_center: the X center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
frame_y_center: the Y center of the entire frame, with respect to the
|
||||
piece currently being drawn.
|
||||
|
||||
The <title/> element now supports an "ellipsize_width" attribute. When
|
||||
specified, this gives a width at which to ellipsize the title. If not
|
||||
specified, the title will simply be clipped to the title area.
|
||||
|
||||
New Features in Theme Format Version 3
|
||||
======================================
|
||||
|
||||
Format version 3 has exactly one new feature; any element in the file
|
||||
can now have a version attribute:
|
||||
|
||||
version="[<|<=|=>|>] MAJOR.MINOR"
|
||||
|
||||
(< and > should be to be entity escaped as < and >). If this
|
||||
version check is not met, then the element and its children will be
|
||||
ignored. This allows having alternate sections of the theme file for
|
||||
older and newer version of the Metacity theme format.
|
||||
|
||||
When placed on the toplevel <metacity_theme> element, an unsatisfied
|
||||
version check will not just cause the contents of the file to be
|
||||
ignored, it will also cause the lookup of a theme file to proceed on
|
||||
and look for an older format 2 or format 1 file. This allows making a
|
||||
metacity-theme-3.xml file that is only used the format version 3.2 or
|
||||
newer is supported, and using metacity-theme-1.xml for older window
|
||||
managers.
|
||||
|
||||
New Features in Theme Format Version 2
|
||||
======================================
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ be@latin
|
||||
bg
|
||||
bn
|
||||
bn_IN
|
||||
br
|
||||
bs
|
||||
ca
|
||||
ca@valencia
|
||||
@@ -57,7 +56,6 @@ mn
|
||||
mr
|
||||
ms
|
||||
nb
|
||||
nds
|
||||
ne
|
||||
nl
|
||||
nn
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/core/bell.c
|
||||
src/core/core.c
|
||||
src/core/delete.c
|
||||
src/core/display.c
|
||||
|
||||
1998
po/en_GB.po
1998
po/en_GB.po
File diff suppressed because it is too large
Load Diff
2004
po/pt_BR.po
2004
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1984
po/sr@latin.po
1984
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
2028
po/zh_CN.po
2028
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1692
po/zh_HK.po
1692
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
1785
po/zh_TW.po
1785
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
186
src/Makefile.am
186
src/Makefile.am
@@ -1,52 +1,29 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter-private.la
|
||||
|
||||
SUBDIRS=wm-tester tools compositor/plugins
|
||||
SUBDIRS=wm-tester tools
|
||||
|
||||
if WITH_CLUTTER
|
||||
SUBDIRS += compositor/mutter/plugins
|
||||
endif
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@ -I $(srcdir)/include -I$(srcdir)/compositor -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_PKGLIBDIR=\"$(pkglibdir)\" -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
|
||||
|
||||
mutter_built_sources = \
|
||||
mutter-marshal.h \
|
||||
mutter-marshal.c \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
|
||||
mutter_SOURCES= \
|
||||
core/async-getprop.c \
|
||||
core/async-getprop.h \
|
||||
core/alttabhandler.c \
|
||||
include/alttabhandler.h \
|
||||
core/alttabhandlerdefault.c \
|
||||
include/alttabhandlerdefault.h \
|
||||
core/bell.c \
|
||||
core/bell.h \
|
||||
core/boxes.c \
|
||||
core/boxes-private.h \
|
||||
include/boxes.h \
|
||||
compositor/compositor.c \
|
||||
compositor/compositor-private.h \
|
||||
compositor/meta-module.c \
|
||||
compositor/meta-module.h \
|
||||
compositor/meta-plugin.c \
|
||||
compositor/meta-plugin-manager.c \
|
||||
compositor/meta-plugin-manager.h \
|
||||
compositor/meta-shadow-factory.c \
|
||||
compositor/meta-shadow-factory-private.h \
|
||||
compositor/meta-shaped-texture.c \
|
||||
compositor/meta-shaped-texture.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
compositor/meta-texture-tower.h \
|
||||
compositor/meta-window-actor.c \
|
||||
compositor/meta-window-actor-private.h \
|
||||
compositor/meta-window-group.c \
|
||||
compositor/meta-window-group.h \
|
||||
compositor/meta-window-shape.c \
|
||||
compositor/meta-window-shape.h \
|
||||
compositor/region-utils.c \
|
||||
compositor/region-utils.h \
|
||||
compositor/compositor-xrender.c \
|
||||
compositor/compositor-xrender.h \
|
||||
include/compositor.h \
|
||||
include/meta-plugin.h \
|
||||
include/meta-shadow-factory.h \
|
||||
include/meta-window-actor.h \
|
||||
include/compositor-mutter.h \
|
||||
core/constraints.c \
|
||||
core/constraints.h \
|
||||
core/core.c \
|
||||
@@ -58,6 +35,8 @@ mutter_SOURCES= \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/effects.c \
|
||||
core/effects.h \
|
||||
core/errors.c \
|
||||
include/errors.h \
|
||||
core/eventqueue.c \
|
||||
@@ -77,7 +56,8 @@ mutter_SOURCES= \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
core/mutter-Xatomtype.h \
|
||||
include/main.h \
|
||||
core/mutter-Xatomtype.h \
|
||||
core/place.c \
|
||||
core/place.h \
|
||||
core/prefs.c \
|
||||
@@ -119,15 +99,30 @@ mutter_SOURCES= \
|
||||
include/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
include/tabpopup.h \
|
||||
ui/tile-preview.c \
|
||||
include/tile-preview.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/themewidget.c \
|
||||
ui/themewidget.h \
|
||||
ui/ui.c \
|
||||
include/all-keybindings.h \
|
||||
$(mutter_built_sources)
|
||||
include/all-keybindings.h
|
||||
|
||||
if WITH_CLUTTER
|
||||
mutter_SOURCES += \
|
||||
compositor/mutter/compositor-mutter.c \
|
||||
compositor/mutter/mutter-shaped-texture.c \
|
||||
compositor/mutter/mutter-shaped-texture.h \
|
||||
compositor/mutter/mutter-plugin-manager.c \
|
||||
compositor/mutter/mutter-plugin-manager.h \
|
||||
compositor/mutter/tidy/tidy-texture-frame.c \
|
||||
compositor/mutter/tidy/tidy-texture-frame.h \
|
||||
compositor/mutter/mutter-module.c \
|
||||
compositor/mutter/mutter-module.h \
|
||||
compositor/mutter/mutter-plugin.c \
|
||||
include/mutter-plugin.h \
|
||||
include/compositor-mutter.h
|
||||
endif
|
||||
|
||||
# by setting libmutter_private_la_CFLAGS, the files shared with
|
||||
# mutter proper will be compiled with different names.
|
||||
@@ -143,20 +138,23 @@ libmutter_private_la_SOURCES= \
|
||||
ui/preview-widget.c \
|
||||
ui/preview-widget.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.c \
|
||||
ui/theme.h
|
||||
|
||||
libmutter_private_la_LDFLAGS = -no-undefined
|
||||
libmutter_private_la_LIBADD = @MUTTER_LIBS@
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
|
||||
libmutterinclude_base_headers = \
|
||||
include/alttabhandler.h \
|
||||
include/boxes.h \
|
||||
ui/gradient.h \
|
||||
include/main.h \
|
||||
include/util.h \
|
||||
include/common.h \
|
||||
ui/preview-widget.h \
|
||||
ui/theme-parser.h \
|
||||
ui/theme.h \
|
||||
include/prefs.h \
|
||||
include/window.h \
|
||||
@@ -164,24 +162,16 @@ libmutterinclude_base_headers = \
|
||||
include/compositor.h \
|
||||
include/compositor-mutter.h \
|
||||
include/types.h \
|
||||
include/errors.h \
|
||||
include/screen.h \
|
||||
include/display.h \
|
||||
include/group.h \
|
||||
include/keybindings.h \
|
||||
include/meta-plugin.h \
|
||||
include/meta-shadow-factory.h \
|
||||
include/meta-window-actor.h
|
||||
include/mutter-plugin.h
|
||||
|
||||
# Excluded from scanning for introspection but installed
|
||||
# preview-widget.h: only part of libmutter-private
|
||||
# atomnames.h: macros cause problems for scanning process
|
||||
libmutterinclude_extra_headers = \
|
||||
ui/preview-widget.h \
|
||||
include/atomnames.h
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
@@ -205,35 +195,29 @@ typelib_DATA = Meta-$(api_version).typelib
|
||||
|
||||
# We need to strip out the attribute that would point back to libmutter-introspect
|
||||
# so that libgirepository looks for symbols in the executable instead
|
||||
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES) Makefile
|
||||
$(AM_V_GEN) pwd=`pwd` ; \
|
||||
cd $(srcdir) && \
|
||||
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES)
|
||||
$(G_IR_SCANNER) \
|
||||
--namespace=Meta \
|
||||
--nsversion=$(api_version) \
|
||||
--warn-all \
|
||||
--warn-error \
|
||||
--include=GObject-2.0 \
|
||||
--include=Gdk-3.0 \
|
||||
--include=Gtk-3.0 \
|
||||
--include=Clutter-1.0 \
|
||||
--pkg=clutter-1.0 \
|
||||
--pkg=gtk+-3.0 \
|
||||
--include=xlib-2.0 \
|
||||
--include=Gdk-2.0 \
|
||||
--include=Gtk-2.0 \
|
||||
--include=Clutter-0.9 \
|
||||
--pkg=clutter-0.9 \
|
||||
--pkg=gtk+-2.0 \
|
||||
--include=xfixes-4.0 \
|
||||
--program=$$pwd/mutter \
|
||||
mutter-enum-types.h \
|
||||
$(filter %.c,$(mutter_SOURCES)) \
|
||||
--program=./mutter \
|
||||
$(filter %.c,$(mutter_SOURCES)) \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(INCLUDES) \
|
||||
-o $$pwd/$@
|
||||
-o $@
|
||||
|
||||
Meta-$(api_version).typelib: $(G_IR_COMPILER) Meta-$(api_version).gir
|
||||
$(AM_V_GEN) LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. $(G_IR_COMPILER) Meta-$(api_version).gir -o $@
|
||||
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. $(G_IR_COMPILER) Meta-$(api_version).gir -o $@
|
||||
endif
|
||||
|
||||
EFENCE=
|
||||
mutter_LDADD=@MUTTER_LIBS@ $(EFENCE)
|
||||
mutter_LDADD=@MUTTER_LIBS@ libmutter-private.la $(EFENCE)
|
||||
mutter_LDFLAGS=-export-dynamic
|
||||
|
||||
mutter_theme_viewer_LDADD= @MUTTER_LIBS@ libmutter-private.la
|
||||
@@ -244,9 +228,9 @@ testasyncgetprop_SOURCES=core/async-getprop.h core/async-getprop.c core/testasyn
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD= @MUTTER_LIBS@
|
||||
testgradient_LDADD= @MUTTER_LIBS@
|
||||
testasyncgetprop_LDADD= @MUTTER_LIBS@
|
||||
testboxes_LDADD= @MUTTER_LIBS@ libmutter-private.la
|
||||
testgradient_LDADD= @MUTTER_LIBS@ libmutter-private.la
|
||||
testasyncgetprop_LDADD= @MUTTER_LIBS@ libmutter-private.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
@@ -281,14 +265,7 @@ VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
|
||||
stock_delete_data $(srcdir)/stock_delete.png
|
||||
|
||||
BUILT_SOURCES = inlinepixbufs.h
|
||||
CLEANFILES = \
|
||||
inlinepixbufs.h \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
mutter.schemas \
|
||||
$(mutter_built_sources) \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
CLEANFILES = inlinepixbufs.h mutter.desktop mutter-wm.desktop mutter.schemas
|
||||
|
||||
inlinepixbufs.h: $(IMAGES)
|
||||
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
|
||||
@@ -299,55 +276,10 @@ pkgconfig_DATA = libmutter-private.pc mutter-plugins.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
$(IMAGES) \
|
||||
$(IMAGES) $(schema_DATA) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(schema_in_files) \
|
||||
libmutter-private.pc.in \
|
||||
mutter-plugins.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
mutter-marshal.list
|
||||
mutter-plugins.pc.in
|
||||
|
||||
BUILT_SOURCES += $(mutter_built_sources)
|
||||
MUTTER_STAMP_FILES = stamp-mutter-marshal.h stamp-mutter-enum-types.h
|
||||
CLEANFILES += $(MUTTER_STAMP_FILES)
|
||||
|
||||
mutter-marshal.h: stamp-mutter-marshal.h
|
||||
@true
|
||||
stamp-mutter-marshal.h: Makefile mutter-marshal.list
|
||||
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
|
||||
--prefix=_mutter_marshal \
|
||||
--header \
|
||||
$(srcdir)/mutter-marshal.list > xgen-tmh && \
|
||||
(cmp -s xgen-tmh mutter-marshal.h || cp -f xgen-tmh mutter-marshal.h) && \
|
||||
rm -f xgen-tmh && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
mutter-marshal.c: Makefile mutter-marshal.list
|
||||
$(AM_V_GEN) (echo "#include \"mutter-marshal.h\"" ; \
|
||||
$(GLIB_GENMARSHAL) \
|
||||
--prefix=_mutter_marshal \
|
||||
--body \
|
||||
$(srcdir)/mutter-marshal.list ) > xgen-tmc && \
|
||||
cp -f xgen-tmc mutter-marshal.c && \
|
||||
rm -f xgen-tmc
|
||||
|
||||
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
|
||||
@true
|
||||
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/mutter-enum-types.h.in \
|
||||
$(libmutterinclude_base_headers) ) >> xgen-teth && \
|
||||
(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
|
||||
rm -f xgen-teth && \
|
||||
echo timestamp > $(@F)
|
||||
|
||||
mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
|
||||
$(AM_V_GEN) ( cd $(srcdir) && \
|
||||
$(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/mutter-enum-types.c.in \
|
||||
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
|
||||
cp xgen-tetc mutter-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
|
||||
@@ -1,68 +1,90 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008 Iain Holmes
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_COMPOSITOR_PRIVATE_H
|
||||
#define META_COMPOSITOR_PRIVATE_H
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "compositor.h"
|
||||
#include "display.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _MetaCompScreen MetaCompScreen;
|
||||
|
||||
struct _MetaCompositor
|
||||
{
|
||||
MetaDisplay *display;
|
||||
void (* destroy) (MetaCompositor *compositor);
|
||||
|
||||
Atom atom_x_root_pixmap;
|
||||
Atom atom_x_set_root;
|
||||
Atom atom_net_wm_window_opacity;
|
||||
guint repaint_func_id;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
MetaPlugin *modal_plugin;
|
||||
|
||||
gboolean show_redraw : 1;
|
||||
gboolean debug : 1;
|
||||
gboolean no_mipmaps : 1;
|
||||
void (*manage_screen) (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
void (*unmanage_screen) (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
void (*add_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*remove_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*set_updates) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean update);
|
||||
gboolean (*process_event) (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window);
|
||||
Pixmap (*get_window_pixmap) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*set_active_window) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window);
|
||||
void (*map_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*unmap_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*minimize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect);
|
||||
void (*unminimize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect);
|
||||
void (*maximize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect);
|
||||
void (*unmaximize_window) (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *window_rect);
|
||||
void (*update_workspace_geometry) (MetaCompositor *compositor,
|
||||
MetaWorkspace *workspace);
|
||||
void (*switch_workspace) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *from,
|
||||
MetaWorkspace *to,
|
||||
MetaMotionDirection direction);
|
||||
void (*sync_stack) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
GList *stack);
|
||||
void (*set_window_hidden) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
gboolean hidden);
|
||||
void (*sync_window_geometry) (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void (*sync_screen_size) (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
guint width,
|
||||
guint height);
|
||||
};
|
||||
|
||||
struct _MetaCompScreen
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *stage, *window_group, *overlay_group;
|
||||
ClutterActor *hidden_group;
|
||||
GList *windows;
|
||||
GHashTable *windows_by_xid;
|
||||
Window output;
|
||||
|
||||
/* Before we create the output window */
|
||||
XserverRegion pending_input_region;
|
||||
|
||||
gint switch_workspace_in_progress;
|
||||
|
||||
MetaPluginManager *plugin_mgr;
|
||||
};
|
||||
|
||||
void meta_switch_workspace_completed (MetaScreen *screen);
|
||||
void meta_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region);
|
||||
void meta_empty_stage_input_region (MetaScreen *screen);
|
||||
|
||||
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_check_end_modal (MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||
#endif
|
||||
|
||||
3067
src/compositor/compositor-xrender.c
Normal file
3067
src/compositor/compositor-xrender.c
Normal file
File diff suppressed because it is too large
Load Diff
31
src/compositor/compositor-xrender.h
Normal file
31
src/compositor/compositor-xrender.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007 Iain Holmes
|
||||
* Based on xcompmgr - (c) 2003 Keith Packard
|
||||
* xfwm4 - (c) 2005-2007 Olivier Fourdan
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_COMPOSITOR_XRENDER_H_
|
||||
#define META_COMPOSITOR_XRENDER_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
MetaCompositor *meta_compositor_xrender_new (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,78 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_PLUGIN_MANAGER_H_
|
||||
#define META_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define META_PLUGIN_FROM_MANAGER_
|
||||
#include "meta-plugin.h"
|
||||
#undef META_PLUGIN_FROM_MANAGER_
|
||||
|
||||
#define META_PLUGIN_MINIMIZE (1<<0)
|
||||
#define META_PLUGIN_MAXIMIZE (1<<1)
|
||||
#define META_PLUGIN_UNMAXIMIZE (1<<2)
|
||||
#define META_PLUGIN_MAP (1<<3)
|
||||
#define META_PLUGIN_DESTROY (1<<4)
|
||||
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
|
||||
|
||||
#define META_PLUGIN_ALL_EFFECTS (~0)
|
||||
|
||||
/**
|
||||
* MetaPluginManager: (skip)
|
||||
*
|
||||
*/
|
||||
typedef struct MetaPluginManager MetaPluginManager;
|
||||
|
||||
MetaPluginManager * meta_plugin_manager_get (MetaScreen *screen);
|
||||
MetaPluginManager * meta_plugin_manager_get_default (void);
|
||||
|
||||
gboolean meta_plugin_manager_load (MetaPluginManager *mgr);
|
||||
gboolean meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr);
|
||||
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
void meta_plugin_manager_update_workspaces (MetaPluginManager *mgr);
|
||||
|
||||
void meta_plugin_manager_update_workspace (MetaPluginManager *mgr,
|
||||
MetaWorkspace *w);
|
||||
|
||||
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
||||
@@ -1,607 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "meta-plugin.h"
|
||||
#include "screen.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
#define META_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCREEN,
|
||||
PROP_PARAMS,
|
||||
PROP_FEATURES,
|
||||
PROP_DISABLED,
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MetaPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
gchar *params;
|
||||
gulong features;
|
||||
|
||||
gint running;
|
||||
|
||||
gboolean disabled : 1;
|
||||
gboolean debug : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_plugin_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_finalize (GObject *object)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
g_free (priv->params);
|
||||
priv->params = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_parse_params (MetaPlugin *plugin)
|
||||
{
|
||||
char *p;
|
||||
gulong features = 0;
|
||||
MetaPluginPrivate *priv = plugin->priv;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
/*
|
||||
* Feature flags: identify events that the plugin can handle; a plugin can
|
||||
* handle one or more events.
|
||||
*/
|
||||
if (klass->minimize)
|
||||
features |= META_PLUGIN_MINIMIZE;
|
||||
|
||||
if (klass->maximize)
|
||||
features |= META_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (klass->unmaximize)
|
||||
features |= META_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (klass->map)
|
||||
features |= META_PLUGIN_MAP;
|
||||
|
||||
if (klass->destroy)
|
||||
features |= META_PLUGIN_DESTROY;
|
||||
|
||||
if (klass->switch_workspace)
|
||||
features |= META_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
if (priv->params)
|
||||
{
|
||||
gboolean debug = FALSE;
|
||||
|
||||
if ((p = strstr (priv->params, "disable:")))
|
||||
{
|
||||
gchar *d = g_strdup (p+8);
|
||||
|
||||
p = strchr (d, ';');
|
||||
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
if (strstr (d, "minimize"))
|
||||
features &= ~ META_PLUGIN_MINIMIZE;
|
||||
|
||||
if (strstr (d, "maximize"))
|
||||
features &= ~ META_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (strstr (d, "unmaximize"))
|
||||
features &= ~ META_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (strstr (d, "map"))
|
||||
features &= ~ META_PLUGIN_MAP;
|
||||
|
||||
if (strstr (d, "destroy"))
|
||||
features &= ~ META_PLUGIN_DESTROY;
|
||||
|
||||
if (strstr (d, "switch-workspace"))
|
||||
features &= ~META_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
g_free (d);
|
||||
}
|
||||
|
||||
if (strstr (priv->params, "debug"))
|
||||
debug = TRUE;
|
||||
|
||||
if (debug != priv->debug)
|
||||
{
|
||||
priv->debug = debug;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "debug-mode");
|
||||
}
|
||||
}
|
||||
|
||||
if (features != priv->features)
|
||||
{
|
||||
priv->features = features;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "features");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
priv->params = g_value_dup_string (value);
|
||||
meta_plugin_parse_params (META_PLUGIN (object));
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
priv->disabled = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
priv->debug = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
g_value_set_string (value, priv->params);
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
g_value_set_boolean (value, priv->disabled);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
g_value_set_boolean (value, priv->debug);
|
||||
break;
|
||||
case PROP_FEATURES:
|
||||
g_value_set_ulong (value, priv->features);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
meta_plugin_class_init (MetaPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = meta_plugin_finalize;
|
||||
gobject_class->dispose = meta_plugin_dispose;
|
||||
gobject_class->set_property = meta_plugin_set_property;
|
||||
gobject_class->get_property = meta_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SCREEN,
|
||||
g_param_spec_object ("screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PARAMS,
|
||||
g_param_spec_string ("params",
|
||||
"Parameters",
|
||||
"Plugin Parameters",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FEATURES,
|
||||
g_param_spec_ulong ("features",
|
||||
"Features",
|
||||
"Plugin Features",
|
||||
0 , G_MAXULONG, 0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DISABLED,
|
||||
g_param_spec_boolean ("disabled",
|
||||
"Plugin disabled",
|
||||
"Plugin disabled",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEBUG_MODE,
|
||||
g_param_spec_boolean ("debug-mode",
|
||||
"Debug Mode",
|
||||
"Debug Mode",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_init (MetaPlugin *self)
|
||||
{
|
||||
MetaPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gulong
|
||||
meta_plugin_features (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->features;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_disabled (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->disabled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_running (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_debug_mode (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MetaPluginInfo *
|
||||
meta_plugin_get_info (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass && klass->plugin_info)
|
||||
return klass->plugin_info (plugin);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_plugin_get_overlay_group (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_get_overlay_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_plugin_get_stage (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_get_stage_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_plugin_get_window_group (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_get_window_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* _meta_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MetaPluginManager.
|
||||
*/
|
||||
void
|
||||
_meta_plugin_effect_started (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
meta_switch_workspace_completed (screen);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_window_effect_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MetaPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = meta_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
meta_window_actor_effect_completed (actor, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_minimize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_maximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_map_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_query_screen_size (MetaPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_screen_get_size (priv->screen, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_set_stage_reactive (MetaPlugin *plugin,
|
||||
gboolean reactive)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (reactive)
|
||||
meta_set_stage_input_region (screen, None);
|
||||
else
|
||||
meta_empty_stage_input_region (screen);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_set_stage_input_area (MetaPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
XRectangle rect;
|
||||
XserverRegion region;
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
region = XFixesCreateRegion (xdpy, &rect, 1);
|
||||
meta_set_stage_input_region (screen, region);
|
||||
XFixesDestroyRegion (xdpy, region);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_set_stage_input_region (MetaPlugin *plugin,
|
||||
XserverRegion region)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
meta_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_get_window_actors:
|
||||
* @plugin: A #MetaPlugin
|
||||
*
|
||||
* This function returns all of the #MetaWindowActor objects referenced by Mutter, including
|
||||
* override-redirect windows. The returned list is a snapshot of Mutter's current
|
||||
* stacking order, with the topmost window last.
|
||||
*
|
||||
* The 'restacked' signal of #MetaScreen signals when this value has changed.
|
||||
*
|
||||
* Returns: (transfer none) (element-type MetaWindowActor): Windows in stacking order, topmost last
|
||||
*/
|
||||
GList *
|
||||
meta_plugin_get_window_actors (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_get_window_actors (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_begin_modal:
|
||||
* @plugin: a #MetaPlugin
|
||||
* @grab_window: the X window to grab the keyboard and mouse on
|
||||
* @cursor: the cursor to use for the pointer grab, or None,
|
||||
* to use the normal cursor for the grab window and
|
||||
* its descendants.
|
||||
* @options: flags that modify the behavior of the modal grab
|
||||
* @timestamp: the timestamp used for establishing grabs
|
||||
*
|
||||
* This function is used to grab the keyboard and mouse for the exclusive
|
||||
* use of the plugin. Correct operation requires that both the keyboard
|
||||
* and mouse are grabbed, or thing will break. (In particular, other
|
||||
* passive X grabs in Meta can trigger but not be handled by the normal
|
||||
* keybinding handling code.) However, the plugin can establish the keyboard
|
||||
* and/or mouse grabs ahead of time and pass in the
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED
|
||||
* options. This facility is provided for two reasons: first to allow using
|
||||
* this function to establish modality after a passive grab, and second to
|
||||
* allow using obscure features of XGrabPointer() and XGrabKeyboard() without
|
||||
* having to add them to this API.
|
||||
*
|
||||
* Return value: whether we successfully grabbed the keyboard and
|
||||
* mouse and made the plugin modal.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_begin_modal (MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_end_modal
|
||||
* @plugin: a #MetaPlugin
|
||||
* @timestamp: the time used for releasing grabs
|
||||
*
|
||||
* Ends the modal operation begun with meta_plugin_begin_modal(). This
|
||||
* ungrabs both the mouse and keyboard even when
|
||||
* %META_MODAL_POINTER_ALREADY_GRABBED or
|
||||
* %META_MODAL_KEYBOARD_ALREADY_GRABBED were provided as options
|
||||
* when beginnning the modal operation.
|
||||
*/
|
||||
void
|
||||
meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||
}
|
||||
|
||||
Display *
|
||||
meta_plugin_get_xdisplay (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
return xdpy;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_plugin_get_screen:
|
||||
* @plugin: a #MetaPlugin
|
||||
*
|
||||
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||
* is associated with exactly one screen; if Metacity is managing
|
||||
* multiple screens, multiple plugin instances will be created.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
MetaScreen *
|
||||
meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaShadowFactory:
|
||||
*
|
||||
* Create and cache shadow textures for arbitrary window shapes
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
#define __META_SHADOW_FACTORY_PRIVATE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-window-shape.h"
|
||||
#include "meta-shadow-factory.h"
|
||||
|
||||
/**
|
||||
* MetaShadow:
|
||||
* #MetaShadow holds a shadow texture along with information about how to
|
||||
* apply that texture to draw a window texture. (E.g., it knows how big the
|
||||
* unscaled borders are on each side of the shadow texture.)
|
||||
*/
|
||||
typedef struct _MetaShadow MetaShadow;
|
||||
|
||||
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
|
||||
void meta_shadow_unref (MetaShadow *shadow);
|
||||
CoglHandle meta_shadow_get_texture (MetaShadow *shadow);
|
||||
void meta_shadow_paint (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
guint8 opacity,
|
||||
cairo_region_t *clip);
|
||||
void meta_shadow_get_bounds (MetaShadow *shadow,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
cairo_rectangle_int_t *bounds);
|
||||
|
||||
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
|
||||
MetaWindowShape *shape,
|
||||
int width,
|
||||
int height,
|
||||
const char *class_name,
|
||||
gboolean focused);
|
||||
|
||||
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,635 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-shaped-texture.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
static void meta_shaped_texture_finalize (GObject *object);
|
||||
static void meta_shaped_texture_notify (GObject *object,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
static void meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||
#else /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
|
||||
MetaShapedTexturePrivate))
|
||||
|
||||
struct _MetaShapedTexturePrivate
|
||||
{
|
||||
MetaTextureTower *paint_tower;
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
guint mask_width, mask_height;
|
||||
|
||||
GArray *rectangles;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
|
||||
|
||||
gobject_class->dispose = meta_shaped_texture_dispose;
|
||||
gobject_class->finalize = meta_shaped_texture_finalize;
|
||||
gobject_class->notify = meta_shaped_texture_notify;
|
||||
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->pick = meta_shaped_texture_pick;
|
||||
|
||||
x11_texture_class->update_area = meta_shaped_texture_update_area;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->paint_tower = meta_texture_tower_new ();
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
priv->create_mipmaps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
|
||||
meta_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (priv->material_unshaped);
|
||||
priv->material_unshaped = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_finalize (GObject *object)
|
||||
{
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_array_free (priv->rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_notify (GObject *object,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
if (G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify)
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify (object, pspec);
|
||||
|
||||
/* It seems like we could just do this out of update_area(), but unfortunately,
|
||||
* clutter_glx_texture_pixmap() doesn't call through the vtable on the
|
||||
* initial update_area, so we need to look for changes to the texture
|
||||
* explicitly.
|
||||
*/
|
||||
if (strcmp (pspec->name, "cogl-texture") == 0)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
meta_shaped_texture_clear (stex);
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower,
|
||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
GLuint mask_gl_tex;
|
||||
GLenum mask_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_handle_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material, 1, COGL_INVALID_HANDLE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
/* If the mask texture we have was created for a different size then
|
||||
recreate it */
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE
|
||||
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
|
||||
/* If we don't have a mask texture yet then create one */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
guchar *mask_data;
|
||||
const XRectangle *rect;
|
||||
GLenum paint_gl_target;
|
||||
|
||||
/* Create data for an empty image */
|
||||
mask_data = g_malloc0 (tex_width * tex_height);
|
||||
|
||||
/* Cut out a hole for each rectangle */
|
||||
for (rect = (XRectangle *) priv->rectangles->data
|
||||
+ priv->rectangles->len;
|
||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
||||
{
|
||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
||||
guchar *p;
|
||||
|
||||
/* Clip the rectangle to the size of the texture */
|
||||
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
|
||||
x2 = CLAMP (x2, x1, (gint) tex_width);
|
||||
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
|
||||
y2 = CLAMP (y2, y1, (gint) tex_height);
|
||||
|
||||
/* Fill the rectangle */
|
||||
for (p = mask_data + y1 * tex_width + x1;
|
||||
y1 < y2;
|
||||
y1++, p += tex_width)
|
||||
memset (p, 255, x2 - x1);
|
||||
}
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_ALPHA, tex_width, tex_height,
|
||||
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
|
||||
|
||||
priv->mask_texture
|
||||
= cogl_texture_new_from_foreign (tex,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
}
|
||||
else
|
||||
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
tex_width,
|
||||
mask_data);
|
||||
|
||||
g_free (mask_data);
|
||||
|
||||
priv->mask_width = tex_width;
|
||||
priv->mask_height = tex_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
|
||||
static CoglHandle material_template = COGL_INVALID_HANDLE;
|
||||
static CoglHandle material_unshaped_template = COGL_INVALID_HANDLE;
|
||||
|
||||
CoglHandle material;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* rarely supported. Also, even when it is supported there
|
||||
* are distinct performance implications from:
|
||||
*
|
||||
* - Updating mipmaps that we don't need
|
||||
* - Having to reallocate pixmaps on the server into larger buffers
|
||||
*
|
||||
* So, we just unconditionally use our mipmap emulation code. If we
|
||||
* wanted to use SGIS_generate_mipmap, we'd have to query COGL to
|
||||
* see if it was supported (no API currently), and then if and only
|
||||
* if that was the case, set the clutter texture quality to HIGH.
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
/* If there are no rectangles use a single-layer texture */
|
||||
|
||||
if (priv->material_unshaped == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_unshaped_template == COGL_INVALID_HANDLE))
|
||||
material_unshaped_template = cogl_material_new ();
|
||||
|
||||
priv->material_unshaped = cogl_material_copy (material_unshaped_template);
|
||||
}
|
||||
material = priv->material_unshaped;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_shaped_texture_ensure_mask (stex);
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
|
||||
{
|
||||
material_template = cogl_material_new ();
|
||||
cogl_material_set_layer_combine (material_template, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
priv->material = cogl_material_copy (material_template);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->clip_region);
|
||||
if (n_rects <= MAX_RECTS)
|
||||
{
|
||||
float coords[8];
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (priv->clip_region, i, &rect);
|
||||
|
||||
x1 = rect.x;
|
||||
y1 = rect.y;
|
||||
x2 = rect.x + rect.width;
|
||||
y2 = rect.y + rect.height;
|
||||
|
||||
coords[0] = rect.x / (alloc.x2 - alloc.x1);
|
||||
coords[1] = rect.y / (alloc.y2 - alloc.y1);
|
||||
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
|
||||
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
|
||||
|
||||
coords[4] = coords[0];
|
||||
coords[5] = coords[1];
|
||||
coords[6] = coords[2];
|
||||
coords[7] = coords[3];
|
||||
|
||||
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
|
||||
&coords[0], 8);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there are no rectangles then use the regular pick */
|
||||
if (priv->rectangles->len < 1)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
meta_shaped_texture_ensure_mask (stex);
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) texture;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (meta_shaped_texture_parent_class)->update_area (texture,
|
||||
x, y, width, height);
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
create_mipmaps = create_mipmaps != FALSE;
|
||||
|
||||
if (create_mipmaps != priv->create_mipmaps)
|
||||
{
|
||||
CoglHandle base_texture;
|
||||
|
||||
priv->create_mipmaps = create_mipmaps;
|
||||
|
||||
base_texture = create_mipmaps ?
|
||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)) : COGL_INVALID_HANDLE;
|
||||
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a workaround for deficiencies in the hack tower:
|
||||
*
|
||||
* When we call clutter_x11_texture_pixmap_set_pixmap(tp, None),
|
||||
* ClutterX11TexturePixmap knows that it has to get rid of the old texture, but
|
||||
* clutter_texture_set_cogl_texture(texture, COGL_INVALID_HANDLE) isn't allowed, so
|
||||
* it grabs the material for the texture and manually sets the texture in it. This means
|
||||
* that the "cogl-texture" property isn't notified, so we don't find out about it.
|
||||
*
|
||||
* And if we keep the CoglX11TexturePixmap around after the X pixmap is freed, then
|
||||
* we'll trigger X errors when we actually try to free it.
|
||||
*
|
||||
* The only correct thing to do here is to change our code to derive
|
||||
* from ClutterActor and get rid of the inheritance hack tower. Once
|
||||
* we want to depend on Clutter-1.4 (which has CoglTexturePixmapX11),
|
||||
* that will be very easy to do.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_clear (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE);
|
||||
|
||||
if (priv->material_unshaped != COGL_INVALID_HANDLE)
|
||||
cogl_material_set_layer (priv->material_unshaped, 0, COGL_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_set_size (priv->rectangles, 0);
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
|
||||
const XRectangle *rect)
|
||||
{
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
meta_shaped_texture_add_rectangles (stex, 1, rect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_append_vals (priv->rectangles, rects, num_rects);
|
||||
|
||||
meta_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_clip_region:
|
||||
* @frame: a #TidyTextureframe
|
||||
* @clip_region: (transfer full): the region of the texture that
|
||||
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
|
||||
* THE FUNCTION (for efficiency to avoid a copy.)
|
||||
*
|
||||
* Provides a hint to the texture about what areas of the texture
|
||||
* are not completely obscured and thus need to be painted. This
|
||||
* is an optimization and is not supposed to have any effect on
|
||||
* the output.
|
||||
*
|
||||
* Typically a parent container will set the clip region before
|
||||
* painting its children, and then unset it afterwards.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->clip_region)
|
||||
{
|
||||
cairo_region_destroy (priv->clip_region);
|
||||
priv->clip_region = NULL;
|
||||
}
|
||||
|
||||
priv->clip_region = clip_region;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_SHAPED_TEXTURE_H__
|
||||
#define __META_SHAPED_TEXTURE_H__
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type())
|
||||
#define META_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),META_TYPE_SHAPED_TEXTURE, MetaShapedTexture))
|
||||
#define META_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
|
||||
#define META_IS_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHAPED_TEXTURE))
|
||||
#define META_IS_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SHAPED_TEXTURE))
|
||||
#define META_SHAPED_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
|
||||
|
||||
typedef struct _MetaShapedTexture MetaShapedTexture;
|
||||
typedef struct _MetaShapedTextureClass MetaShapedTextureClass;
|
||||
typedef struct _MetaShapedTexturePrivate MetaShapedTexturePrivate;
|
||||
|
||||
struct _MetaShapedTextureClass
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmapClass parent_class;
|
||||
#else
|
||||
ClutterX11TexturePixmapClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MetaShapedTexture
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmap parent;
|
||||
#else
|
||||
ClutterX11TexturePixmap parent;
|
||||
#endif
|
||||
|
||||
MetaShapedTexturePrivate *priv;
|
||||
};
|
||||
|
||||
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
|
||||
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps);
|
||||
|
||||
void meta_shaped_texture_clear (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
|
||||
const XRectangle *rect);
|
||||
void meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects);
|
||||
|
||||
/* Assumes ownership of clip_region */
|
||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SHAPED_TEXTURE_H__ */
|
||||
@@ -1,654 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
|
||||
#define MAX_TEXTURE_LEVELS 12
|
||||
|
||||
/* If the texture format in memory doesn't match this, then Mesa
|
||||
* will do the conversion, so things will still work, but it might
|
||||
* be slow depending on how efficient Mesa is. These should be the
|
||||
* native formats unless the display is 16bpp. If conversions
|
||||
* here are a bottleneck, investigate whether we are converting when
|
||||
* storing window data *into* the texture before adding extra code
|
||||
* to handle multiple texture formats.
|
||||
*/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
#else
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint16 x1;
|
||||
guint16 y1;
|
||||
guint16 x2;
|
||||
guint16 y2;
|
||||
} Box;
|
||||
|
||||
struct _MetaTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglHandle textures[MAX_TEXTURE_LEVELS];
|
||||
CoglHandle fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_texture_tower_new:
|
||||
*
|
||||
* Creates a new texture tower. The base texture has to be set with
|
||||
* meta_texture_tower_set_base_texture() before use.
|
||||
*
|
||||
* Return value: the new texture tower. Free with meta_texture_tower_free()
|
||||
*/
|
||||
MetaTextureTower *
|
||||
meta_texture_tower_new (void)
|
||||
{
|
||||
MetaTextureTower *tower;
|
||||
|
||||
tower = g_slice_new0 (MetaTextureTower);
|
||||
|
||||
return tower;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_free:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Frees a texture tower created with meta_texture_tower_new().
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_is_rectangle (CoglHandle texture)
|
||||
{
|
||||
GLuint gl_tex;
|
||||
GLenum gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
|
||||
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
|
||||
}
|
||||
|
||||
static void
|
||||
free_texture (CoglHandle texture)
|
||||
{
|
||||
GLuint gl_tex;
|
||||
GLenum gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
|
||||
|
||||
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &gl_tex);
|
||||
|
||||
cogl_handle_unref (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a MetaTextureTower
|
||||
* @texture: the new texture used as a base for scaled down versions
|
||||
*
|
||||
* Sets the base texture that is the scaled texture that the
|
||||
* scaled textures of the tower are derived from. The texture itself
|
||||
* will be used as level 0 of the tower and will be referenced until
|
||||
* unset or until the tower is freed.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (texture == tower->textures[0])
|
||||
return;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
if (tower->textures[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
free_texture (tower->textures[i]);
|
||||
tower->textures[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (tower->fbos[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_handle_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_handle_ref (tower->textures[0]);
|
||||
|
||||
width = cogl_texture_get_width (tower->textures[0]);
|
||||
height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
|
||||
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
|
||||
|
||||
meta_texture_tower_update_area (tower, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->n_levels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a MetaTextureTower
|
||||
* @x: X coordinate of upper left of rectangle that changed
|
||||
* @y: Y coordinate of upper left of rectangle that changed
|
||||
* @width: width of rectangle that changed
|
||||
* @height: height rectangle that changed
|
||||
*
|
||||
* Mark a region of the base texture as having changed; the next
|
||||
* time a scaled down version of the base texture is retrieved,
|
||||
* the appropriate area of the scaled down texture will be updated.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
Box invalid;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
invalid.x1 = x;
|
||||
invalid.y1 = y;
|
||||
invalid.x2 = x + width;
|
||||
invalid.y2 = y + height;
|
||||
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
invalid.x1 = invalid.x1 / 2;
|
||||
invalid.y1 = invalid.y1 / 2;
|
||||
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
|
||||
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
|
||||
|
||||
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
|
||||
tower->invalid[i].y1 == tower->invalid[i].y2)
|
||||
{
|
||||
tower->invalid[i] = invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
|
||||
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
|
||||
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
|
||||
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* It generally looks worse if we scale up a window texture by even a
|
||||
* small amount than if we scale it down using bilinear filtering, so
|
||||
* we always pick the *larger* adjacent level. */
|
||||
#define LOD_BIAS (-0.49)
|
||||
|
||||
/* This determines the appropriate level of detail to use when drawing the
|
||||
* texture, in a way that corresponds to what the GL specification does
|
||||
* when mip-mapping. This is probably fancier and slower than what we need,
|
||||
* but we do the computation only once each time we paint a window, and
|
||||
* its easier to just use the equations from the specification than to
|
||||
* come up with something simpler.
|
||||
*
|
||||
* If window is being painted at an angle from the viewer, then we have to
|
||||
* pick a point in the texture; we use the middle of the texture (which is
|
||||
* why the width/height are passed in.) This is not the normal case for
|
||||
* Meta.
|
||||
*/
|
||||
static int
|
||||
get_paint_level (int width, int height)
|
||||
{
|
||||
CoglMatrix projection, modelview, pm;
|
||||
float v[4];
|
||||
double viewport_width, viewport_height;
|
||||
double u0, v0;
|
||||
double xc, yc, wc;
|
||||
double dxdu_, dxdv_, dydu_, dydv_;
|
||||
double det_, det_sq;
|
||||
double rho_sq;
|
||||
double lambda;
|
||||
|
||||
/* See
|
||||
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
|
||||
* Section 3.8.9, p. 1.6.2. Here we have
|
||||
*
|
||||
* u(x,y) = x_o;
|
||||
* v(x,y) = y_o;
|
||||
*
|
||||
* Since we are mapping 1:1 from object coordinates into pixel
|
||||
* texture coordinates, the clip coordinates are:
|
||||
*
|
||||
* (x_c) (x_o) (u)
|
||||
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
|
||||
* (z_c) (z_o) (0)
|
||||
* (w_c) (w_o) (1)
|
||||
*/
|
||||
|
||||
cogl_get_projection_matrix (&projection);
|
||||
cogl_get_modelview_matrix (&modelview);
|
||||
|
||||
cogl_matrix_multiply (&pm, &projection, &modelview);
|
||||
|
||||
cogl_get_viewport (v);
|
||||
viewport_width = v[2];
|
||||
viewport_height = v[3];
|
||||
|
||||
u0 = width / 2.;
|
||||
v0 = height / 2.;
|
||||
|
||||
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
|
||||
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
|
||||
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
|
||||
|
||||
/* We'll simplify the equations below for a bit of micro-optimization.
|
||||
* The commented out code is the unsimplified version.
|
||||
|
||||
// Partial derivates of window coordinates:
|
||||
//
|
||||
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
|
||||
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
|
||||
//
|
||||
// with respect to u, v, using
|
||||
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
|
||||
|
||||
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
|
||||
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
|
||||
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
|
||||
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
|
||||
|
||||
// Compute the inverse partials as the matrix inverse
|
||||
det = dxdu * dydv - dxdv * dydu;
|
||||
|
||||
dudx = dydv / det;
|
||||
dudy = - dxdv / det;
|
||||
dvdx = - dydu / det;
|
||||
dvdy = dvdu / det;
|
||||
|
||||
// Scale factor; maximum of the distance in texels for a change of 1 pixel
|
||||
// in the X direction or 1 pixel in the Y direction
|
||||
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
|
||||
|
||||
// Level of detail
|
||||
lambda = log2 (rho) + LOD_BIAS;
|
||||
*/
|
||||
|
||||
/* dxdu * wc, etc */
|
||||
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
|
||||
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
|
||||
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
|
||||
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
|
||||
|
||||
/* det * wc^2 */
|
||||
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
|
||||
det_sq = det_ * det_;
|
||||
if (det_sq == 0.0)
|
||||
return -1;
|
||||
|
||||
/* (rho * det * wc)^2 */
|
||||
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
|
||||
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
|
||||
|
||||
#if 0
|
||||
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
|
||||
#endif
|
||||
|
||||
if (lambda <= 0.)
|
||||
return 0;
|
||||
else
|
||||
return (int)(0.5 + lambda);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_power_of_two (int x)
|
||||
{
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_create_texture (MetaTextureTower *tower,
|
||||
int level,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
|
||||
texture_is_rectangle (tower->textures[level - 1]))
|
||||
{
|
||||
GLuint tex = 0;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_RGBA, width,height,
|
||||
#if TEXTURE_FORMAT == COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
0, GL_BGRA, GL_UNSIGNED_BYTE,
|
||||
#else /* assume big endian */
|
||||
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
tower->textures[level] = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
|
||||
width, height,
|
||||
0, 0,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->textures[level] = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
|
||||
tower->invalid[level].x1 = 0;
|
||||
tower->invalid[level].y1 = 0;
|
||||
tower->invalid[level].x2 = width;
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
{
|
||||
/* Work around http://bugzilla.openedhand.com/show_bug.cgi?id=2110 */
|
||||
cogl_flush();
|
||||
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
}
|
||||
|
||||
if (tower->fbos[level] == COGL_INVALID_HANDLE)
|
||||
return FALSE;
|
||||
|
||||
cogl_push_framebuffer (tower->fbos[level]);
|
||||
|
||||
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
|
||||
cogl_set_source_texture (tower->textures[level - 1]);
|
||||
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_copy (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
memcpy (buf, source, width * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_scale_down (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
while (width > 1)
|
||||
{
|
||||
buf[0] = (source[0] + source[4]) / 2;
|
||||
buf[1] = (source[1] + source[5]) / 2;
|
||||
buf[2] = (source[2] + source[6]) / 2;
|
||||
buf[3] = (source[3] + source[7]) / 2;
|
||||
|
||||
buf += 4;
|
||||
source += 8;
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
buf[0] = source[0] / 2;
|
||||
buf[1] = source[1] / 2;
|
||||
buf[2] = source[2] / 2;
|
||||
buf[3] = source[3] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglHandle source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
guint source_rowstride;
|
||||
guchar *source_data;
|
||||
CoglHandle dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
int dest_x = tower->invalid[level].x1;
|
||||
int dest_y = tower->invalid[level].y1;
|
||||
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||
guchar *dest_data;
|
||||
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||
int i, j;
|
||||
|
||||
source_rowstride = source_texture_width * 4;
|
||||
|
||||
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||
source_data);
|
||||
|
||||
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
source_tmp1 = g_malloc (dest_width * 4);
|
||||
source_tmp2 = g_malloc (dest_width * 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
guchar *source1, *source2;
|
||||
guchar *dest;
|
||||
|
||||
if (dest_texture_width < source_texture_width)
|
||||
{
|
||||
fill_scale_down (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
fill_scale_down (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_copy (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
fill_copy (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
}
|
||||
|
||||
source1 = source_tmp1;
|
||||
source2 = source_tmp2;
|
||||
|
||||
dest = dest_row;
|
||||
for (j = 0; j < dest_width * 4; j++)
|
||||
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_texture_width < source_texture_width)
|
||||
fill_scale_down (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
else
|
||||
fill_copy (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride,
|
||||
dest_width);
|
||||
}
|
||||
}
|
||||
|
||||
cogl_texture_set_region (dest_texture,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
dest_width, dest_height,
|
||||
dest_width, dest_height,
|
||||
TEXTURE_FORMAT,
|
||||
4 * dest_width,
|
||||
dest_data);
|
||||
|
||||
if (dest_height < source_texture_height)
|
||||
{
|
||||
g_free (source_tmp1);
|
||||
g_free (source_tmp2);
|
||||
}
|
||||
|
||||
g_free (source_data);
|
||||
g_free (dest_data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_get_paint_texture:
|
||||
* @tower: a MetaTextureTower
|
||||
*
|
||||
* Gets the texture from the tower that best matches the current
|
||||
* rendering scale. (On the assumption here the texture is going to
|
||||
* be rendered with vertex coordinates that correspond to its
|
||||
* size in pixels, so a 200x200 texture will be rendered on the
|
||||
* rectangle (0, 0, 200, 200).
|
||||
*
|
||||
* Return value: the COGL texture handle to use for painting, or
|
||||
* %COGL_INVALID_HANDLE if no base texture has yet been set.
|
||||
*/
|
||||
CoglHandle
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
int level;
|
||||
|
||||
g_return_val_if_fail (tower != NULL, COGL_INVALID_HANDLE);
|
||||
|
||||
if (tower->textures[0] == COGL_INVALID_HANDLE)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
level = get_paint_level(texture_width, texture_height);
|
||||
if (level < 0) /* singular paint matrix, scaled to nothing */
|
||||
return COGL_INVALID_HANDLE;
|
||||
level = MIN (level, tower->n_levels - 1);
|
||||
|
||||
if (tower->textures[level] == COGL_INVALID_HANDLE ||
|
||||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
/* Use "floor" convention here to be consistent with the NPOT texture extension */
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
if (tower->textures[i] == COGL_INVALID_HANDLE)
|
||||
texture_tower_create_texture (tower, i, texture_width, texture_height);
|
||||
}
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1)
|
||||
texture_tower_revalidate (tower, i);
|
||||
}
|
||||
}
|
||||
|
||||
return tower->textures[level];
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_TEXTURE_TOWER_H__
|
||||
#define __META_TEXTURE_TOWER_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:MetaTextureTower
|
||||
* @short_description: mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* A #MetaTextureTower is used to get good looking scaled down images when
|
||||
* we can't use the GL drivers mipmap support. There are two separate reasons
|
||||
*
|
||||
* - Some cards (including radeon cards <= r5xx) only support
|
||||
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
|
||||
* are defined not to support mipmapping.
|
||||
* - Even when NPOT textures are available, the combination of NPOT
|
||||
* textures, texture_from_pixmap, and mipmapping doesn't typically
|
||||
* work, since the X server doesn't allocate pixmaps in the right
|
||||
* layout for mipmapping.
|
||||
*
|
||||
* So, what we do is create the "mipmap" levels ourselves by successive
|
||||
* power-of-two scaledowns, and when rendering pick the single texture
|
||||
* that best matches the scale we are rendering at. (Since we aren't
|
||||
* typically using perspective transforms, we'll frequently have a single
|
||||
* scale for the entire texture.)
|
||||
*/
|
||||
|
||||
typedef struct _MetaTextureTower MetaTextureTower;
|
||||
|
||||
MetaTextureTower *meta_texture_tower_new (void);
|
||||
void meta_texture_tower_free (MetaTextureTower *tower);
|
||||
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglHandle texture);
|
||||
void meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglHandle meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#endif /* __META_TEXTURE_TOWER_H__ */
|
||||
@@ -1,53 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_WINDOW_ACTOR_PRIVATE_H
|
||||
#define META_WINDOW_ACTOR_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include "compositor-mutter.h"
|
||||
|
||||
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
|
||||
|
||||
void meta_window_actor_destroy (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_show (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
void meta_window_actor_hide (MetaWindowActor *self,
|
||||
MetaCompEffect effect);
|
||||
|
||||
void meta_window_actor_maximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
void meta_window_actor_unmaximize (MetaWindowActor *self,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event);
|
||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
||||
|
||||
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||
void meta_window_actor_update_shape (MetaWindowActor *self,
|
||||
gboolean shaped);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
|
||||
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_visible_region (MetaWindowActor *self,
|
||||
cairo_region_t *visible_region);
|
||||
void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
|
||||
cairo_region_t *beneath_region);
|
||||
void meta_window_actor_reset_visible_regions (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,196 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define _ISOC99_SOURCE /* for roundf */
|
||||
#include <math.h>
|
||||
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
|
||||
struct _MetaWindowGroupClass
|
||||
{
|
||||
ClutterGroupClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaWindowGroup
|
||||
{
|
||||
ClutterGroup parent;
|
||||
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_GROUP);
|
||||
|
||||
/* We want to find out if the window is "close enough" to
|
||||
* 1:1 transform. We do that by converting the transformed coordinates
|
||||
* to 24.8 fixed-point before checking if they look right.
|
||||
*/
|
||||
static inline int
|
||||
round_to_fixed (float x)
|
||||
{
|
||||
return roundf (x * 256);
|
||||
}
|
||||
|
||||
/* We can only (easily) apply our logic for figuring out what a window
|
||||
* obscures if is not transformed. This function does that check and
|
||||
* as a side effect gets the position of the upper-left corner of the
|
||||
* actors.
|
||||
*
|
||||
* (We actually could handle scaled and non-integrally positioned actors
|
||||
* too as long as they weren't shaped - no filtering is done at the
|
||||
* edges so a rectangle stays a rectangle. But the gain from that is
|
||||
* small, especally since most of our windows are shaped. The simple
|
||||
* case we handle here is the case that matters when the user is just
|
||||
* using the desktop normally.)
|
||||
*
|
||||
* If we assume that the window group is untransformed (it better not
|
||||
* be!) then we could also make this determination by checking directly
|
||||
* if the actor itself is rotated, scaled, or at a non-integral position.
|
||||
* However, the criterion for "close enough" in that case get trickier,
|
||||
* since, for example, the allowed rotation depends on the size of
|
||||
* actor. The approach we take here is to just require everything
|
||||
* to be within 1/256th of a pixel.
|
||||
*/
|
||||
static gboolean
|
||||
actor_is_untransformed (ClutterActor *actor,
|
||||
int *x_origin,
|
||||
int *y_origin)
|
||||
{
|
||||
gfloat widthf, heightf;
|
||||
int width, height;
|
||||
ClutterVertex verts[4];
|
||||
int v0x, v0y, v1x, v1y, v2x, v2y, v3x, v3y;
|
||||
int x, y;
|
||||
|
||||
clutter_actor_get_size (actor, &widthf, &heightf);
|
||||
width = round_to_fixed (widthf); height = round_to_fixed (heightf);
|
||||
|
||||
clutter_actor_get_abs_allocation_vertices (actor, verts);
|
||||
v0x = round_to_fixed (verts[0].x); v0y = round_to_fixed (verts[0].y);
|
||||
v1x = round_to_fixed (verts[1].x); v1y = round_to_fixed (verts[1].y);
|
||||
v2x = round_to_fixed (verts[2].x); v2y = round_to_fixed (verts[2].y);
|
||||
v3x = round_to_fixed (verts[3].x); v3y = round_to_fixed (verts[3].y);
|
||||
|
||||
/* Using shifting for converting fixed => int, gets things right for
|
||||
* negative values. / 256. wouldn't do the same
|
||||
*/
|
||||
x = v0x >> 8;
|
||||
y = v0y >> 8;
|
||||
|
||||
/* At integral coordinates? */
|
||||
if (x * 256 != v0x || y * 256 != v0y)
|
||||
return FALSE;
|
||||
|
||||
/* Not scaled? */
|
||||
if (v1x - v0x != width || v2y - v0y != height)
|
||||
return FALSE;
|
||||
|
||||
/* Not rotated/skewed? */
|
||||
if (v0x != v2x || v0y != v1y ||
|
||||
v3x != v1x || v3y != v2y)
|
||||
return FALSE;
|
||||
|
||||
*x_origin = x;
|
||||
*y_origin = y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
cairo_region_t *visible_region;
|
||||
cairo_rectangle_int_t screen_rect = { 0 };
|
||||
GList *children, *l;
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
children = clutter_container_get_children (CLUTTER_CONTAINER (actor));
|
||||
children = g_list_reverse (children);
|
||||
|
||||
/* Start off with the full screen area (for a multihead setup, we
|
||||
* might want to use a more accurate union of the monitors to avoid
|
||||
* painting in holes from mismatched monitor sizes. That's just an
|
||||
* optimization, however.)
|
||||
*/
|
||||
meta_screen_get_size (window_group->screen, &screen_rect.width, &screen_rect.height);
|
||||
visible_region = cairo_region_create_rectangle (&screen_rect);
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
gboolean x, y;
|
||||
|
||||
if (!META_IS_WINDOW_ACTOR (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
continue;
|
||||
|
||||
window_actor = l->data;
|
||||
|
||||
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
continue;
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (visible_region, - x, - y);
|
||||
|
||||
meta_window_actor_set_visible_region (window_actor, visible_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
||||
{
|
||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
||||
if (obscured_region)
|
||||
cairo_region_subtract (visible_region, obscured_region);
|
||||
}
|
||||
|
||||
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
|
||||
cairo_region_destroy (visible_region);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
||||
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (!META_IS_WINDOW_ACTOR (l->data))
|
||||
continue;
|
||||
|
||||
window_actor = l->data;
|
||||
meta_window_actor_reset_visible_regions (window_actor);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_class_init (MetaWindowGroupClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->paint = meta_window_group_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_init (MetaWindowGroup *window_group)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_window_group_new (MetaScreen *screen)
|
||||
{
|
||||
MetaWindowGroup *window_group;
|
||||
|
||||
window_group = g_object_new (META_TYPE_WINDOW_GROUP, NULL);
|
||||
|
||||
window_group->screen = screen;
|
||||
|
||||
return CLUTTER_ACTOR (window_group);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_WINDOW_GROUP_H
|
||||
#define META_WINDOW_GROUP_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
/**
|
||||
* MetaWindowGroup:
|
||||
*
|
||||
* This class is a subclass of ClutterGroup with special handling for
|
||||
* MetaWindowActor when painting the group. When we are painting a stack
|
||||
* of 5-10 maximized windows, the standard bottom-to-top method of
|
||||
* drawing every actor results in a tremendous amount of overdraw
|
||||
* and can easily max out the available memory bandwidth on a low-end
|
||||
* graphics chipset. It's even worse if window textures are being accessed
|
||||
* over the AGP bus.
|
||||
*
|
||||
* The basic technique applied here is to do a pre-pass before painting
|
||||
* where we walk window from top to bottom and compute the visible area
|
||||
* at each step by subtracting out the windows above it. The visible
|
||||
* area is passed to MetaWindowActor which uses it to clip the portion of
|
||||
* the window which drawn and avoid redrawing the shadow if it is completely
|
||||
* obscured.
|
||||
*
|
||||
* A caveat is that this is ineffective if applications are using ARGB
|
||||
* visuals, since we have no way of knowing whether a window obscures
|
||||
* the windows behind it or not. Alternate approaches using the depth
|
||||
* or stencil buffer rather than client side regions might be able to
|
||||
* handle alpha windows, but the combination of glAlphaFunc and stenciling
|
||||
* tends not to be efficient except on newer cards. (And on newer cards
|
||||
* we have lots of memory and bandwidth.)
|
||||
*/
|
||||
|
||||
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
|
||||
#define META_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
|
||||
#define META_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
#define META_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
|
||||
#define META_IS_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
|
||||
#define META_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
|
||||
|
||||
typedef struct _MetaWindowGroup MetaWindowGroup;
|
||||
typedef struct _MetaWindowGroupClass MetaWindowGroupClass;
|
||||
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
|
||||
|
||||
GType meta_window_group_get_type (void);
|
||||
|
||||
ClutterActor *meta_window_group_new (MetaScreen *screen);
|
||||
|
||||
#endif /* META_WINDOW_GROUP_H */
|
||||
@@ -1,253 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-window-shape.h"
|
||||
#include "region-utils.h"
|
||||
|
||||
struct _MetaWindowShape
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
int top, right, bottom, left;
|
||||
int n_rectangles;
|
||||
cairo_rectangle_int_t *rectangles;
|
||||
guint hash;
|
||||
};
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_new (cairo_region_t *region)
|
||||
{
|
||||
MetaWindowShape *shape;
|
||||
MetaRegionIterator iter;
|
||||
cairo_rectangle_int_t extents;
|
||||
int max_yspan_y1 = 0;
|
||||
int max_yspan_y2 = 0;
|
||||
int max_xspan_x1 = -1;
|
||||
int max_xspan_x2 = -1;
|
||||
guint hash;
|
||||
|
||||
shape = g_slice_new0 (MetaWindowShape);
|
||||
shape->ref_count = 1;
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
|
||||
shape->n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
if (shape->n_rectangles == 0)
|
||||
{
|
||||
shape->rectangles = NULL;
|
||||
shape->top = shape->right = shape->bottom = shape->left = 0;
|
||||
shape->hash = 0;
|
||||
return shape;
|
||||
}
|
||||
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int max_line_xspan_x1 = -1;
|
||||
int max_line_xspan_x2 = -1;
|
||||
|
||||
if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
|
||||
{
|
||||
max_line_xspan_x1 = iter.rectangle.x;
|
||||
max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
}
|
||||
|
||||
if (iter.line_end)
|
||||
{
|
||||
if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
|
||||
{
|
||||
max_yspan_y1 = iter.rectangle.y;
|
||||
max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
}
|
||||
|
||||
if (max_xspan_x1 < 0) /* First line */
|
||||
{
|
||||
max_xspan_x1 = max_line_xspan_x1;
|
||||
max_xspan_x2 = max_line_xspan_x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
|
||||
max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
|
||||
|
||||
if (max_xspan_x2 < max_xspan_x1)
|
||||
max_xspan_x2 = max_xspan_x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
|
||||
max_xspan_x1, max_xspan_x2,
|
||||
max_yspan_y1, max_yspan_y2);
|
||||
#endif
|
||||
|
||||
shape->top = max_yspan_y1 - extents.y;
|
||||
shape->right = extents.x + extents.width - max_xspan_x2;
|
||||
shape->bottom = extents.y + extents.height - max_yspan_y2;
|
||||
shape->left = max_xspan_x1 - extents.x;
|
||||
|
||||
shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
|
||||
|
||||
hash = 0;
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
x1 = iter.rectangle.x;
|
||||
x2 = iter.rectangle.x + iter.rectangle.width;
|
||||
y1 = iter.rectangle.y;
|
||||
y2 = iter.rectangle.y + iter.rectangle.height;
|
||||
|
||||
if (x1 > max_xspan_x1)
|
||||
x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (x2 > max_xspan_x1)
|
||||
x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
|
||||
if (y1 > max_yspan_y1)
|
||||
y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
if (y2 > max_yspan_y1)
|
||||
y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
|
||||
|
||||
shape->rectangles[iter.i].x = x1 - extents.x;
|
||||
shape->rectangles[iter.i].y = y1 - extents.y;
|
||||
shape->rectangles[iter.i].width = x2 - x1;
|
||||
shape->rectangles[iter.i].height = y2 - y1;
|
||||
|
||||
#if 0
|
||||
g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
|
||||
i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
|
||||
shape->rectangles[i].x, shape->rectangles[i].y, shape->rectangles[i].width, shape->rectangles[i].height);
|
||||
#endif
|
||||
|
||||
hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
|
||||
}
|
||||
|
||||
shape->hash = hash;
|
||||
|
||||
#if 0
|
||||
g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
|
||||
#endif
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
MetaWindowShape *
|
||||
meta_window_shape_ref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count++;
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_unref (MetaWindowShape *shape)
|
||||
{
|
||||
shape->ref_count--;
|
||||
if (shape->ref_count == 0)
|
||||
{
|
||||
g_free (shape->rectangles);
|
||||
g_slice_free (MetaWindowShape, shape);
|
||||
}
|
||||
}
|
||||
|
||||
guint
|
||||
meta_window_shape_hash (MetaWindowShape *shape)
|
||||
{
|
||||
return shape->hash;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b)
|
||||
{
|
||||
if (shape_a->n_rectangles != shape_b->n_rectangles)
|
||||
return FALSE;
|
||||
|
||||
return memcmp (shape_a->rectangles, shape_b->rectangles,
|
||||
sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left)
|
||||
{
|
||||
if (border_top)
|
||||
*border_top = shape->top;
|
||||
if (border_right)
|
||||
*border_right = shape->right;
|
||||
if (border_bottom)
|
||||
*border_bottom = shape->bottom;
|
||||
if (border_left)
|
||||
*border_left = shape->left;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_shape_to_region:
|
||||
* @shape: a #MetaWindowShape
|
||||
* @center_width: size of the central region horizontally
|
||||
* @center_height: size of the central region vertically
|
||||
*
|
||||
* Converts the shape to to a cairo_region_t using the given width
|
||||
* and height for the central scaled region.
|
||||
*
|
||||
* Return value: a newly created region
|
||||
*/
|
||||
cairo_region_t *
|
||||
meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
int i;
|
||||
|
||||
region = cairo_region_create ();
|
||||
|
||||
for (i = 0; i < shape->n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect = shape->rectangles[i];
|
||||
|
||||
if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
|
||||
rect.width += center_width;
|
||||
else if (rect.x >= shape->left + 1)
|
||||
rect.x += center_width;
|
||||
|
||||
if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
|
||||
rect.height += center_height;
|
||||
else if (rect.y >= shape->top + 1)
|
||||
rect.y += center_height;
|
||||
|
||||
cairo_region_union_rectangle (region, &rect);
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaWindowShape
|
||||
*
|
||||
* Extracted invariant window shape
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_WINDOW_SHAPE_H__
|
||||
#define __META_WINDOW_SHAPE_H__
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* MetaWindowShape:
|
||||
* #MetaWindowShape represents a 9-sliced region with borders on all sides that
|
||||
* are unscaled, and a constant central region that is scaled. For example,
|
||||
* if you the regions representing two windows that around rounded rectangles,
|
||||
* with the same corner regions, but different sizes, they have the
|
||||
* same MetaWindowShape.
|
||||
*
|
||||
* #MetaWindowShape is designed to be used as part of a hash table key, so has
|
||||
* efficient hash and equal functions.
|
||||
*/
|
||||
typedef struct _MetaWindowShape MetaWindowShape;
|
||||
|
||||
MetaWindowShape * meta_window_shape_new (cairo_region_t *region);
|
||||
MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape);
|
||||
void meta_window_shape_unref (MetaWindowShape *shape);
|
||||
guint meta_window_shape_hash (MetaWindowShape *shape);
|
||||
gboolean meta_window_shape_equal (MetaWindowShape *shape_a,
|
||||
MetaWindowShape *shape_b);
|
||||
void meta_window_shape_get_borders (MetaWindowShape *shape,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left);
|
||||
cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape,
|
||||
int center_width,
|
||||
int center_height);
|
||||
|
||||
#endif /* __META_WINDOW_SHAPE_H __*/
|
||||
|
||||
2975
src/compositor/mutter/compositor-mutter.c
Normal file
2975
src/compositor/mutter/compositor-mutter.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,8 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "meta-plugin.h"
|
||||
#include "meta-module.h"
|
||||
#include "mutter-plugin.h"
|
||||
#include "mutter-module.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
@@ -32,23 +32,23 @@ enum
|
||||
PROP_PATH,
|
||||
};
|
||||
|
||||
struct _MetaModulePrivate
|
||||
struct _MutterModulePrivate
|
||||
{
|
||||
GModule *lib;
|
||||
gchar *path;
|
||||
GType plugin_type;
|
||||
};
|
||||
|
||||
#define META_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_MODULE, MetaModulePrivate))
|
||||
#define MUTTER_MODULE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate))
|
||||
|
||||
G_DEFINE_TYPE (MetaModule, meta_module, G_TYPE_TYPE_MODULE);
|
||||
G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE);
|
||||
|
||||
static gboolean
|
||||
meta_module_load (GTypeModule *gmodule)
|
||||
mutter_module_load (GTypeModule *gmodule)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
MetaPluginVersion *info = NULL;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
MutterPluginVersion *info = NULL;
|
||||
GType (*register_type) (GTypeModule *) = NULL;
|
||||
|
||||
if (priv->lib && priv->plugin_type)
|
||||
@@ -64,9 +64,9 @@ meta_module_load (GTypeModule *gmodule)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_module_symbol (priv->lib, "meta_plugin_version",
|
||||
if (g_module_symbol (priv->lib, "mutter_plugin_version",
|
||||
(gpointer *)(void *)&info) &&
|
||||
g_module_symbol (priv->lib, "meta_plugin_register_type",
|
||||
g_module_symbol (priv->lib, "mutter_plugin_register_type",
|
||||
(gpointer *)(void *)®ister_type) &&
|
||||
info && register_type)
|
||||
{
|
||||
@@ -97,9 +97,9 @@ meta_module_load (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_unload (GTypeModule *gmodule)
|
||||
mutter_module_unload (GTypeModule *gmodule)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
|
||||
|
||||
g_module_close (priv->lib);
|
||||
|
||||
@@ -108,29 +108,29 @@ meta_module_unload (GTypeModule *gmodule)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_dispose (GObject *object)
|
||||
mutter_module_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_finalize (GObject *object)
|
||||
mutter_module_finalize (GObject *object)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
|
||||
g_free (priv->path);
|
||||
priv->path = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_module_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
mutter_module_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -145,12 +145,12 @@ meta_module_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
mutter_module_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (object)->priv;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -164,18 +164,18 @@ meta_module_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_class_init (MetaModuleClass *klass)
|
||||
mutter_module_class_init (MutterModuleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = meta_module_finalize;
|
||||
gobject_class->dispose = meta_module_dispose;
|
||||
gobject_class->set_property = meta_module_set_property;
|
||||
gobject_class->get_property = meta_module_get_property;
|
||||
gobject_class->finalize = mutter_module_finalize;
|
||||
gobject_class->dispose = mutter_module_dispose;
|
||||
gobject_class->set_property = mutter_module_set_property;
|
||||
gobject_class->get_property = mutter_module_get_property;
|
||||
|
||||
gmodule_class->load = meta_module_load;
|
||||
gmodule_class->unload = meta_module_unload;
|
||||
gmodule_class->load = mutter_module_load;
|
||||
gmodule_class->unload = mutter_module_unload;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PATH,
|
||||
@@ -186,22 +186,22 @@ meta_module_class_init (MetaModuleClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaModulePrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_module_init (MetaModule *self)
|
||||
mutter_module_init (MutterModule *self)
|
||||
{
|
||||
MetaModulePrivate *priv;
|
||||
MutterModulePrivate *priv;
|
||||
|
||||
self->priv = priv = META_MODULE_GET_PRIVATE (self);
|
||||
self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self);
|
||||
|
||||
}
|
||||
|
||||
GType
|
||||
meta_module_get_plugin_type (MetaModule *module)
|
||||
mutter_module_get_plugin_type (MutterModule *module)
|
||||
{
|
||||
MetaModulePrivate *priv = META_MODULE (module)->priv;
|
||||
MutterModulePrivate *priv = MUTTER_MODULE (module)->priv;
|
||||
|
||||
return priv->plugin_type;
|
||||
}
|
||||
@@ -21,37 +21,37 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_MODULE_H_
|
||||
#define META_MODULE_H_
|
||||
#ifndef MUTTER_MODULE_H_
|
||||
#define MUTTER_MODULE_H_
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define META_TYPE_MODULE (meta_module_get_type ())
|
||||
#define META_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MODULE, MetaModule))
|
||||
#define META_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MODULE, MetaModuleClass))
|
||||
#define META_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_MODULE_TYPE))
|
||||
#define META_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MODULE))
|
||||
#define META_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MODULE, MetaModuleClass))
|
||||
#define MUTTER_TYPE_MODULE (mutter_module_get_type ())
|
||||
#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule))
|
||||
#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE))
|
||||
#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE))
|
||||
#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass))
|
||||
|
||||
typedef struct _MetaModule MetaModule;
|
||||
typedef struct _MetaModuleClass MetaModuleClass;
|
||||
typedef struct _MetaModulePrivate MetaModulePrivate;
|
||||
typedef struct _MutterModule MutterModule;
|
||||
typedef struct _MutterModuleClass MutterModuleClass;
|
||||
typedef struct _MutterModulePrivate MutterModulePrivate;
|
||||
|
||||
struct _MetaModule
|
||||
struct _MutterModule
|
||||
{
|
||||
GTypeModule parent;
|
||||
|
||||
MetaModulePrivate *priv;
|
||||
MutterModulePrivate *priv;
|
||||
};
|
||||
|
||||
struct _MetaModuleClass
|
||||
struct _MutterModuleClass
|
||||
{
|
||||
GTypeModuleClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType meta_module_get_type (void);
|
||||
GType mutter_module_get_type (void);
|
||||
|
||||
GType meta_module_get_plugin_type (MetaModule *module);
|
||||
GType mutter_module_get_plugin_type (MutterModule *module);
|
||||
|
||||
#endif
|
||||
@@ -22,55 +22,50 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "compositor-private.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include "prefs.h"
|
||||
#include "errors.h"
|
||||
#include "workspace.h"
|
||||
#include "meta-module.h"
|
||||
#include "../core/window-private.h"
|
||||
#include "mutter-module.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
/*
|
||||
* There is only one instace of each module per the process.
|
||||
*/
|
||||
static GHashTable *plugin_modules = NULL;
|
||||
|
||||
/*
|
||||
* We have one "default plugin manager" that acts for the first screen,
|
||||
* but also can be used before we open any screens, and additional
|
||||
* plugin managers for each screen. (This is ugly. Probably we should
|
||||
* have one plugin manager and only make the plugins per-screen.)
|
||||
*/
|
||||
static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr);
|
||||
|
||||
static MetaPluginManager *default_plugin_manager;
|
||||
|
||||
static gboolean meta_plugin_manager_reload (MetaPluginManager *plugin_mgr);
|
||||
|
||||
struct MetaPluginManager
|
||||
struct MutterPluginManager
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
|
||||
GList *unload; /* Plugins that are disabled and pending unload */
|
||||
GList /* MutterPluginPending */ *pending_plugin_modules; /* Plugins not yet fully loaded */
|
||||
GList /* MutterPlugin */ *plugins; /* TODO -- maybe use hash table */
|
||||
GList *unload; /* Plugins that are disabled and pending unload */
|
||||
|
||||
guint idle_unload_id;
|
||||
};
|
||||
|
||||
typedef struct MutterPluginPending
|
||||
{
|
||||
MutterModule *module;
|
||||
char *path;
|
||||
char *params;
|
||||
} MutterPluginPending;
|
||||
|
||||
/*
|
||||
* Checks that the plugin is compatible with the WM and sets up the plugin
|
||||
* struct.
|
||||
*/
|
||||
static MetaPlugin *
|
||||
meta_plugin_load (MetaPluginManager *mgr,
|
||||
MetaModule *module,
|
||||
const gchar *params)
|
||||
static MutterPlugin *
|
||||
mutter_plugin_load (MutterPluginManager *mgr,
|
||||
MutterModule *module,
|
||||
const gchar *params)
|
||||
{
|
||||
MetaPlugin *plugin = NULL;
|
||||
GType plugin_type = meta_module_get_plugin_type (module);
|
||||
MutterPlugin *plugin = NULL;
|
||||
GType plugin_type = mutter_module_get_plugin_type (module);
|
||||
|
||||
if (!plugin_type)
|
||||
{
|
||||
@@ -79,6 +74,7 @@ meta_plugin_load (MetaPluginManager *mgr,
|
||||
}
|
||||
|
||||
plugin = g_object_new (plugin_type,
|
||||
"screen", mgr->screen,
|
||||
"params", params,
|
||||
NULL);
|
||||
|
||||
@@ -91,9 +87,9 @@ meta_plugin_load (MetaPluginManager *mgr,
|
||||
* removal later.
|
||||
*/
|
||||
static gboolean
|
||||
meta_plugin_unload (MetaPlugin *plugin)
|
||||
mutter_plugin_unload (MutterPlugin *plugin)
|
||||
{
|
||||
if (meta_plugin_running (plugin))
|
||||
if (mutter_plugin_running (plugin))
|
||||
{
|
||||
g_object_set (plugin, "disabled", TRUE, NULL);
|
||||
return FALSE;
|
||||
@@ -109,16 +105,16 @@ meta_plugin_unload (MetaPlugin *plugin)
|
||||
* pending for removal.
|
||||
*/
|
||||
static gboolean
|
||||
meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
|
||||
mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *l = plugin_mgr->unload;
|
||||
gboolean dont_remove = TRUE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MutterPlugin *plugin = l->data;
|
||||
|
||||
if (meta_plugin_unload (plugin))
|
||||
if (mutter_plugin_unload (plugin))
|
||||
{
|
||||
/* Remove from list */
|
||||
GList *p = l->prev;
|
||||
@@ -154,23 +150,23 @@ meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
|
||||
* Unloads all plugins
|
||||
*/
|
||||
static void
|
||||
meta_plugin_manager_unload (MetaPluginManager *plugin_mgr)
|
||||
mutter_plugin_manager_unload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *plugins = plugin_mgr->plugins;
|
||||
|
||||
while (plugins)
|
||||
{
|
||||
MetaPlugin *plugin = plugins->data;
|
||||
MutterPlugin *plugin = plugins->data;
|
||||
|
||||
/* If the plugin could not be removed, move it to the unload list */
|
||||
if (!meta_plugin_unload (plugin))
|
||||
if (!mutter_plugin_unload (plugin))
|
||||
{
|
||||
plugin_mgr->unload = g_list_prepend (plugin_mgr->unload, plugin);
|
||||
|
||||
if (!plugin_mgr->idle_unload_id)
|
||||
{
|
||||
plugin_mgr->idle_unload_id = g_idle_add ((GSourceFunc)
|
||||
meta_plugin_manager_idle_unload,
|
||||
mutter_plugin_manager_idle_unload,
|
||||
plugin_mgr);
|
||||
}
|
||||
}
|
||||
@@ -186,21 +182,21 @@ static void
|
||||
prefs_changed_callback (MetaPreference pref,
|
||||
void *data)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr = data;
|
||||
MutterPluginManager *plugin_mgr = data;
|
||||
|
||||
if (pref == META_PREF_CLUTTER_PLUGINS)
|
||||
{
|
||||
meta_plugin_manager_reload (plugin_mgr);
|
||||
mutter_plugin_manager_reload (plugin_mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaModule *
|
||||
meta_plugin_manager_get_module (const gchar *path)
|
||||
static MutterModule *
|
||||
mutter_plugin_manager_get_module (const gchar *path)
|
||||
{
|
||||
MetaModule *module = g_hash_table_lookup (plugin_modules, path);
|
||||
MutterModule *module = g_hash_table_lookup (plugin_modules, path);
|
||||
|
||||
if (!module &&
|
||||
(module = g_object_new (META_TYPE_MODULE, "path", path, NULL)))
|
||||
(module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL)))
|
||||
{
|
||||
g_hash_table_insert (plugin_modules, g_strdup (path), module);
|
||||
}
|
||||
@@ -212,7 +208,7 @@ meta_plugin_manager_get_module (const gchar *path)
|
||||
* Loads all plugins listed in gconf registry.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
|
||||
GSList *plugins, *fallback = NULL;
|
||||
@@ -237,7 +233,7 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
|
||||
if (plugin_string)
|
||||
{
|
||||
MetaModule *module;
|
||||
MutterModule *module;
|
||||
gchar *path;
|
||||
|
||||
params = strchr (plugin_string, ':');
|
||||
@@ -253,7 +249,7 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
else
|
||||
path = g_strconcat (dpath, plugin_string, ".so", NULL);
|
||||
|
||||
module = meta_plugin_manager_get_module (path);
|
||||
module = mutter_plugin_manager_get_module (path);
|
||||
|
||||
if (module)
|
||||
{
|
||||
@@ -270,14 +266,12 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
|
||||
if (use_succeeded)
|
||||
{
|
||||
MetaPlugin *plugin = meta_plugin_load (plugin_mgr, module, params);
|
||||
|
||||
if (plugin)
|
||||
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
|
||||
else
|
||||
g_warning ("Plugin load for [%s] failed", path);
|
||||
|
||||
g_type_module_unuse (G_TYPE_MODULE (module));
|
||||
MutterPluginPending *pending = g_new0 (MutterPluginPending, 1);
|
||||
pending->module = module;
|
||||
pending->path = g_strdup (path);
|
||||
pending->params = g_strdup (params);
|
||||
plugin_mgr->pending_plugin_modules =
|
||||
g_list_prepend (plugin_mgr->pending_plugin_modules, pending);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -295,7 +289,7 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
if (fallback)
|
||||
g_slist_free (fallback);
|
||||
|
||||
if (plugin_mgr->plugins != NULL)
|
||||
if (plugin_mgr->pending_plugin_modules != NULL)
|
||||
{
|
||||
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
|
||||
return TRUE;
|
||||
@@ -305,23 +299,31 @@ meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
|
||||
mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
|
||||
for (iter = plugin_mgr->pending_plugin_modules; iter; iter = iter->next)
|
||||
{
|
||||
MetaPlugin *plugin = (MetaPlugin*) iter->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPluginPending *pending = (MutterPluginPending*) iter->data;
|
||||
MutterPlugin *p;
|
||||
|
||||
g_object_set (plugin,
|
||||
"screen", plugin_mgr->screen,
|
||||
NULL);
|
||||
if ((p = mutter_plugin_load (plugin_mgr, pending->module, pending->params)))
|
||||
{
|
||||
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Plugin load for [%s] failed", pending->path);
|
||||
}
|
||||
|
||||
if (klass->start)
|
||||
klass->start (plugin);
|
||||
g_type_module_unuse (G_TYPE_MODULE (pending->module));
|
||||
g_free (pending->path);
|
||||
g_free (pending->params);
|
||||
g_free (pending);
|
||||
}
|
||||
|
||||
g_list_free (plugin_mgr->pending_plugin_modules);
|
||||
plugin_mgr->pending_plugin_modules = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -329,24 +331,20 @@ meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
|
||||
* Reloads all plugins
|
||||
*/
|
||||
static gboolean
|
||||
meta_plugin_manager_reload (MetaPluginManager *plugin_mgr)
|
||||
mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
|
||||
{
|
||||
/* TODO -- brute force; should we build a list of plugins to load and list of
|
||||
* plugins to unload? We are probably not going to have large numbers of
|
||||
* plugins loaded at the same time, so it might not be worth it.
|
||||
*/
|
||||
|
||||
/* Prevent stale grabs on unloaded plugins */
|
||||
meta_check_end_modal (plugin_mgr->screen);
|
||||
|
||||
meta_plugin_manager_unload (plugin_mgr);
|
||||
return meta_plugin_manager_load (plugin_mgr);
|
||||
mutter_plugin_manager_unload (plugin_mgr);
|
||||
return mutter_plugin_manager_load (plugin_mgr);
|
||||
}
|
||||
|
||||
static MetaPluginManager *
|
||||
meta_plugin_manager_new (MetaScreen *screen)
|
||||
MutterPluginManager *
|
||||
mutter_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
MutterPluginManager *plugin_mgr;
|
||||
|
||||
if (!plugin_modules)
|
||||
{
|
||||
@@ -354,91 +352,37 @@ meta_plugin_manager_new (MetaScreen *screen)
|
||||
NULL);
|
||||
}
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr = g_new0 (MutterPluginManager, 1);
|
||||
|
||||
plugin_mgr->screen = screen;
|
||||
|
||||
if (screen)
|
||||
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_get_default (void)
|
||||
{
|
||||
if (!default_plugin_manager)
|
||||
{
|
||||
default_plugin_manager = meta_plugin_manager_new (NULL);
|
||||
}
|
||||
|
||||
return default_plugin_manager;
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_get (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
|
||||
plugin_mgr = g_object_get_data (G_OBJECT (screen), "meta-plugin-manager");
|
||||
if (plugin_mgr)
|
||||
return plugin_mgr;
|
||||
|
||||
if (!default_plugin_manager)
|
||||
meta_plugin_manager_get_default ();
|
||||
|
||||
if (!default_plugin_manager->screen)
|
||||
{
|
||||
/* The default plugin manager is so far unused, we can recycle it */
|
||||
default_plugin_manager->screen = screen;
|
||||
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", default_plugin_manager);
|
||||
|
||||
return default_plugin_manager;
|
||||
}
|
||||
else
|
||||
{
|
||||
return meta_plugin_manager_new (screen);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor)
|
||||
mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long events)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin)
|
||||
&& klass->kill_window_effects)
|
||||
klass->kill_window_effects (plugin, actor);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin)
|
||||
&& (meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE)
|
||||
&& klass->kill_switch_workspace)
|
||||
klass->kill_switch_workspace (plugin);
|
||||
if (!mutter_plugin_disabled (plugin)
|
||||
&& (mutter_plugin_features (plugin) & events)
|
||||
&& klass->kill_effect)
|
||||
klass->kill_effect (plugin, actor, events);
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define ALL_BUT_SWITCH \
|
||||
MUTTER_PLUGIN_ALL_EFFECTS & \
|
||||
~MUTTER_PLUGIN_SWITCH_WORKSPACE
|
||||
/*
|
||||
* Public method that the compositor hooks into for events that require
|
||||
* no additional parameters.
|
||||
@@ -449,55 +393,53 @@ meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & event))
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case META_PLUGIN_MINIMIZE:
|
||||
case MUTTER_PLUGIN_MINIMIZE:
|
||||
if (klass->minimize)
|
||||
{
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor);
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_MAP:
|
||||
case MUTTER_PLUGIN_MAP:
|
||||
if (klass->map)
|
||||
{
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor);
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_DESTROY:
|
||||
case MUTTER_PLUGIN_DESTROY:
|
||||
if (klass->destroy)
|
||||
{
|
||||
_meta_plugin_effect_started (plugin);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -522,54 +464,52 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & event))
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & event))
|
||||
{
|
||||
retval = TRUE;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case META_PLUGIN_MAXIMIZE:
|
||||
case MUTTER_PLUGIN_MAXIMIZE:
|
||||
if (klass->maximize)
|
||||
{
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor);
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->maximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_UNMAXIMIZE:
|
||||
case MUTTER_PLUGIN_UNMAXIMIZE:
|
||||
if (klass->unmaximize)
|
||||
{
|
||||
meta_plugin_manager_kill_window_effects (
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
actor);
|
||||
actor,
|
||||
ALL_BUT_SWITCH);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->unmaximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
@@ -595,33 +535,34 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
GList *l = plugin_mgr->plugins;
|
||||
gboolean retval = FALSE;
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (!meta_plugin_disabled (plugin) &&
|
||||
(meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE))
|
||||
if (!mutter_plugin_disabled (plugin) &&
|
||||
(mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) &&
|
||||
(actors && *actors))
|
||||
{
|
||||
if (klass->switch_workspace)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||
mutter_plugin_manager_kill_effect (
|
||||
plugin_mgr,
|
||||
MUTTER_WINDOW ((*actors)->data),
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, from, to, direction);
|
||||
_mutter_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, actors, from, to, direction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,43 +581,23 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
* appropriate post-effect cleanup is carried out.
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
|
||||
XEvent *xev)
|
||||
{
|
||||
GList *l;
|
||||
gboolean have_plugin_xevent_func;
|
||||
|
||||
if (!plugin_mgr)
|
||||
return FALSE;
|
||||
|
||||
l = plugin_mgr->plugins;
|
||||
|
||||
/* We need to make sure that clutter gets certain events, like
|
||||
* ConfigureNotify on the stage window. If there is a plugin that
|
||||
* provides an xevent_filter function, then it's the responsibility
|
||||
* of that plugin to pass events to Clutter. Otherwise, we send the
|
||||
* event directly to Clutter ourselves.
|
||||
*
|
||||
* What happens if there are two plugins with xevent_filter functions
|
||||
* is undefined; in general, multiple competing plugins are something
|
||||
* we don't support well or care much about.
|
||||
*
|
||||
* FIXME: Really, we should just always handle sending the event to
|
||||
* clutter if a plugin doesn't report the event as handled by
|
||||
* returning TRUE, but it doesn't seem worth breaking compatibility
|
||||
* of the plugin interface right now to achieve this; the way it is
|
||||
* now works fine in practice.
|
||||
*/
|
||||
have_plugin_xevent_func = FALSE;
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaPlugin *plugin = l->data;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MutterPlugin *plugin = l->data;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->xevent_filter)
|
||||
{
|
||||
have_plugin_xevent_func = TRUE;
|
||||
if (klass->xevent_filter (plugin, xev) == TRUE)
|
||||
return TRUE;
|
||||
}
|
||||
@@ -684,8 +605,5 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (!have_plugin_xevent_func)
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
63
src/compositor/mutter/mutter-plugin-manager.h
Normal file
63
src/compositor/mutter/mutter-plugin-manager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MUTTER_PLUGIN_MANAGER_H_
|
||||
#define MUTTER_PLUGIN_MANAGER_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define MUTTER_PLUGIN_FROM_MANAGER_
|
||||
#include "mutter-plugin.h"
|
||||
#undef MUTTER_PLUGIN_FROM_MANAGER_
|
||||
|
||||
typedef struct MutterPluginManager MutterPluginManager;
|
||||
|
||||
MutterPluginManager * mutter_plugin_manager_new (MetaScreen *screen);
|
||||
gboolean mutter_plugin_manager_load (MutterPluginManager *mgr);
|
||||
gboolean mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr);
|
||||
gboolean mutter_plugin_manager_event_simple (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event);
|
||||
|
||||
gboolean mutter_plugin_manager_event_maximize (MutterPluginManager *mgr,
|
||||
MutterWindow *actor,
|
||||
unsigned long event,
|
||||
gint target_x,
|
||||
gint target_y,
|
||||
gint target_width,
|
||||
gint target_height);
|
||||
void mutter_plugin_manager_update_workspaces (MutterPluginManager *mgr);
|
||||
|
||||
void mutter_plugin_manager_update_workspace (MutterPluginManager *mgr, MetaWorkspace *w);
|
||||
|
||||
gboolean mutter_plugin_manager_switch_workspace (MutterPluginManager *mgr,
|
||||
const GList **actors,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
#endif
|
||||
484
src/compositor/mutter/mutter-plugin.c
Normal file
484
src/compositor/mutter/mutter-plugin.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Intel Corp.
|
||||
*
|
||||
* Author: Tomas Frydrych <tf@linux.intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mutter-plugin.h"
|
||||
#include "screen.h"
|
||||
#include "display.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
|
||||
|
||||
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCREEN,
|
||||
PROP_PARAMS,
|
||||
PROP_FEATURES,
|
||||
PROP_DISABLED,
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MutterPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
gchar *params;
|
||||
gulong features;
|
||||
|
||||
gint running;
|
||||
|
||||
gboolean disabled : 1;
|
||||
gboolean debug : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_plugin_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_finalize (GObject *object)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
g_free (priv->params);
|
||||
priv->params = NULL;
|
||||
|
||||
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_parse_params (MutterPlugin *plugin)
|
||||
{
|
||||
char *p;
|
||||
gulong features = 0;
|
||||
MutterPluginPrivate *priv = plugin->priv;
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
/*
|
||||
* Feature flags: identify events that the plugin can handle; a plugin can
|
||||
* handle one or more events.
|
||||
*/
|
||||
if (klass->minimize)
|
||||
features |= MUTTER_PLUGIN_MINIMIZE;
|
||||
|
||||
if (klass->maximize)
|
||||
features |= MUTTER_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (klass->unmaximize)
|
||||
features |= MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (klass->map)
|
||||
features |= MUTTER_PLUGIN_MAP;
|
||||
|
||||
if (klass->destroy)
|
||||
features |= MUTTER_PLUGIN_DESTROY;
|
||||
|
||||
if (klass->switch_workspace)
|
||||
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
if (priv->params)
|
||||
{
|
||||
gboolean debug = FALSE;
|
||||
|
||||
if ((p = strstr (priv->params, "disable:")))
|
||||
{
|
||||
gchar *d = g_strdup (p+8);
|
||||
|
||||
p = strchr (d, ';');
|
||||
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
if (strstr (d, "minimize"))
|
||||
features &= ~ MUTTER_PLUGIN_MINIMIZE;
|
||||
|
||||
if (strstr (d, "maximize"))
|
||||
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
|
||||
|
||||
if (strstr (d, "unmaximize"))
|
||||
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
|
||||
|
||||
if (strstr (d, "map"))
|
||||
features &= ~ MUTTER_PLUGIN_MAP;
|
||||
|
||||
if (strstr (d, "destroy"))
|
||||
features &= ~ MUTTER_PLUGIN_DESTROY;
|
||||
|
||||
if (strstr (d, "switch-workspace"))
|
||||
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
|
||||
|
||||
g_free (d);
|
||||
}
|
||||
|
||||
if (strstr (priv->params, "debug"))
|
||||
debug = TRUE;
|
||||
|
||||
if (debug != priv->debug)
|
||||
{
|
||||
priv->debug = debug;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "debug-mode");
|
||||
}
|
||||
}
|
||||
|
||||
if (features != priv->features)
|
||||
{
|
||||
priv->features = features;
|
||||
|
||||
g_object_notify (G_OBJECT (plugin), "features");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
priv->params = g_value_dup_string (value);
|
||||
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
priv->disabled = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
priv->debug = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
g_value_set_string (value, priv->params);
|
||||
break;
|
||||
case PROP_DISABLED:
|
||||
g_value_set_boolean (value, priv->disabled);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
g_value_set_boolean (value, priv->debug);
|
||||
break;
|
||||
case PROP_FEATURES:
|
||||
g_value_set_ulong (value, priv->features);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mutter_plugin_class_init (MutterPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = mutter_plugin_finalize;
|
||||
gobject_class->dispose = mutter_plugin_dispose;
|
||||
gobject_class->set_property = mutter_plugin_set_property;
|
||||
gobject_class->get_property = mutter_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SCREEN,
|
||||
g_param_spec_object ("screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PARAMS,
|
||||
g_param_spec_string ("params",
|
||||
"Parameters",
|
||||
"Plugin Parameters",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FEATURES,
|
||||
g_param_spec_ulong ("features",
|
||||
"Features",
|
||||
"Plugin Features",
|
||||
0 , G_MAXULONG, 0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DISABLED,
|
||||
g_param_spec_boolean ("disabled",
|
||||
"Plugin disabled",
|
||||
"Plugin disabled",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEBUG_MODE,
|
||||
g_param_spec_boolean ("debug-mode",
|
||||
"Debug Mode",
|
||||
"Debug Mode",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_plugin_init (MutterPlugin *self)
|
||||
{
|
||||
MutterPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gulong
|
||||
mutter_plugin_features (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->features;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_disabled (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->disabled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_running (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mutter_plugin_debug_mode (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MutterPluginInfo *
|
||||
mutter_plugin_get_info (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass && klass->plugin_info)
|
||||
return klass->plugin_info (plugin);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_overlay_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_stage (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_stage_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_plugin_get_window_group (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_window_group_for_screen (priv->screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* _mutter_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MutterPluginManager.
|
||||
*/
|
||||
void
|
||||
_mutter_plugin_effect_started (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_effect_completed (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MutterPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = mutter_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
mutter_window_effect_completed (actor, event);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_query_screen_size (MutterPlugin *plugin,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
meta_screen_get_size (priv->screen, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
|
||||
gboolean reactive)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (reactive)
|
||||
mutter_set_stage_input_region (screen, None);
|
||||
else
|
||||
mutter_empty_stage_input_region (screen);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
|
||||
gint x, gint y, gint width, gint height)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
XRectangle rect;
|
||||
XserverRegion region;
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
region = XFixesCreateRegion (xdpy, &rect, 1);
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
XFixesDestroyRegion (xdpy, region);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
|
||||
XserverRegion region)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
GList *
|
||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return mutter_get_windows (priv->screen);
|
||||
}
|
||||
|
||||
Display *
|
||||
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
return xdpy;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_get_screen:
|
||||
* @plugin: a #MutterPlugin
|
||||
*
|
||||
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||
* is associated with exactly one screen; if Metacity is managing
|
||||
* multiple screens, multiple plugin instances will be created.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
MetaScreen *
|
||||
mutter_plugin_get_screen (MutterPlugin *plugin)
|
||||
{
|
||||
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
428
src/compositor/mutter/mutter-shaped-texture.c
Executable file
428
src/compositor/mutter/mutter-shaped-texture.c
Executable file
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "mutter-shaped-texture.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void mutter_shaped_texture_dispose (GObject *object);
|
||||
static void mutter_shaped_texture_finalize (GObject *object);
|
||||
|
||||
static void mutter_shaped_texture_paint (ClutterActor *actor);
|
||||
static void mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
|
||||
#else /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexturePrivate))
|
||||
|
||||
struct _MutterShapedTexturePrivate
|
||||
{
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
#if 1 /* see workaround comment in mutter_shaped_texture_paint */
|
||||
CoglHandle material_workaround;
|
||||
#endif
|
||||
|
||||
guint mask_width, mask_height;
|
||||
|
||||
GArray *rectangles;
|
||||
};
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
|
||||
gobject_class->dispose = mutter_shaped_texture_dispose;
|
||||
gobject_class->finalize = mutter_shaped_texture_finalize;
|
||||
|
||||
actor_class->paint = mutter_shaped_texture_paint;
|
||||
actor_class->pick = mutter_shaped_texture_pick;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_init (MutterShapedTexture *self)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
priv = self->priv = MUTTER_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
mutter_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#if 1 /* see comment in mutter_shaped_texture_paint */
|
||||
if (priv->material_workaround != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_material_unref (priv->material_workaround);
|
||||
priv->material_workaround = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_finalize (GObject *object)
|
||||
{
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_array_free (priv->rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE)
|
||||
{
|
||||
GLuint mask_gl_tex;
|
||||
GLenum mask_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_texture_unref (priv->mask_texture);
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
/* If the mask texture we have was created for a different size then
|
||||
recreate it */
|
||||
if (priv->mask_texture != COGL_INVALID_HANDLE
|
||||
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
|
||||
/* If we don't have a mask texture yet then create one */
|
||||
if (priv->mask_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
guchar *mask_data;
|
||||
const XRectangle *rect;
|
||||
GLenum paint_gl_target;
|
||||
|
||||
/* Create data for an empty image */
|
||||
mask_data = g_malloc0 (tex_width * tex_height);
|
||||
|
||||
/* Cut out a hole for each rectangle */
|
||||
for (rect = (XRectangle *) priv->rectangles->data
|
||||
+ priv->rectangles->len;
|
||||
rect-- > (XRectangle *) priv->rectangles->data;)
|
||||
{
|
||||
gint x1 = rect->x, x2 = x1 + rect->width;
|
||||
gint y1 = rect->y, y2 = y1 + rect->height;
|
||||
guchar *p;
|
||||
|
||||
/* Clip the rectangle to the size of the texture */
|
||||
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
|
||||
x2 = CLAMP (x2, x1, (gint) tex_width);
|
||||
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
|
||||
y2 = CLAMP (y2, y1, (gint) tex_height);
|
||||
|
||||
/* Fill the rectangle */
|
||||
for (p = mask_data + y1 * tex_width + x1;
|
||||
y1 < y2;
|
||||
y1++, p += tex_width)
|
||||
memset (p, 255, x2 - x1);
|
||||
}
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
|
||||
GL_ALPHA, tex_width, tex_height,
|
||||
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
|
||||
|
||||
priv->mask_texture
|
||||
= cogl_texture_new_from_foreign (tex,
|
||||
CGL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
}
|
||||
else
|
||||
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
tex_width,
|
||||
mask_data);
|
||||
|
||||
g_free (mask_data);
|
||||
|
||||
priv->mask_width = tex_width;
|
||||
priv->mask_height = tex_height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
CoglHandle paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
CoglHandle material;
|
||||
#if 1 /* please see comment below about workaround */
|
||||
guint depth;
|
||||
#endif
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_width == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
/* If there are no rectangles fallback to the regular paint
|
||||
method */
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class)
|
||||
->paint (actor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
priv->material = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (priv->material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
material = priv->material;
|
||||
|
||||
#if 1
|
||||
/* This was added as a workaround. It seems that with the intel
|
||||
* drivers when multi-texturing using an RGB TFP texture, the
|
||||
* texture is actually setup internally as an RGBA texture, where
|
||||
* the alpha channel is mostly 0.0 so you only see a shimmer of the
|
||||
* window. This workaround forcibly defines the alpha channel as
|
||||
* 1.0. Maybe there is some clutter/cogl state that is interacting
|
||||
* with this that is being overlooked, but for now this seems to
|
||||
* work. */
|
||||
g_object_get (stex, "pixmap-depth", &depth, NULL);
|
||||
if (depth == 24)
|
||||
{
|
||||
if (priv->material_workaround == COGL_INVALID_HANDLE)
|
||||
{
|
||||
material = priv->material_workaround = cogl_material_new ();
|
||||
|
||||
cogl_material_set_layer_combine (material, 0,
|
||||
"RGB = MODULATE (TEXTURE, PREVIOUS)"
|
||||
"A = REPLACE (PREVIOUS)",
|
||||
NULL);
|
||||
cogl_material_set_layer_combine (material, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
|
||||
material = priv->material_workaround;
|
||||
}
|
||||
#endif
|
||||
|
||||
cogl_material_set_layer (material, 0, paint_tex);
|
||||
cogl_material_set_layer (material, 1, priv->mask_texture);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_color (material, &color);
|
||||
}
|
||||
|
||||
cogl_set_source (material);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
cogl_rectangle (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
/* If there are no rectangles then use the regular pick */
|
||||
if (priv->rectangles->len < 1)
|
||||
CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class)
|
||||
->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
{
|
||||
CoglHandle paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
|
||||
if (tex_width == 0 || tex_width == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
mutter_shaped_texture_ensure_mask (stex);
|
||||
|
||||
cogl_set_source_color4ub (color->red, color->green, color->blue,
|
||||
color->alpha);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
/* Paint the mask rectangle in the given color */
|
||||
cogl_set_source_texture (priv->mask_texture);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1,
|
||||
0, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_shaped_texture_new (void)
|
||||
{
|
||||
ClutterActor *self = g_object_new (MUTTER_TYPE_SHAPED_TEXTURE, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_set_size (priv->rectangles, 0);
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect)
|
||||
{
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
mutter_shaped_texture_add_rectangles (stex, 1, rect);
|
||||
}
|
||||
|
||||
void
|
||||
mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects)
|
||||
{
|
||||
MutterShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
g_array_append_vals (priv->rectangles, rects, num_rects);
|
||||
|
||||
mutter_shaped_texture_dirty_mask (stex);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
95
src/compositor/mutter/mutter-shaped-texture.h
Normal file
95
src/compositor/mutter/mutter-shaped-texture.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* shaped texture
|
||||
*
|
||||
* An actor to draw a texture clipped to a list of rectangles
|
||||
*
|
||||
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MUTTER_SHAPED_TEXTURE_H__
|
||||
#define __MUTTER_SHAPED_TEXTURE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
#include <clutter/glx/clutter-glx.h>
|
||||
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define MUTTER_TYPE_SHAPED_TEXTURE \
|
||||
(mutter_shaped_texture_get_type())
|
||||
#define MUTTER_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTexture))
|
||||
#define MUTTER_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_IS_SHAPED_TEXTURE_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE))
|
||||
#define MUTTER_SHAPED_TEXTURE_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
MUTTER_TYPE_SHAPED_TEXTURE, \
|
||||
MutterShapedTextureClass))
|
||||
|
||||
typedef struct _MutterShapedTexture MutterShapedTexture;
|
||||
typedef struct _MutterShapedTextureClass MutterShapedTextureClass;
|
||||
typedef struct _MutterShapedTexturePrivate MutterShapedTexturePrivate;
|
||||
|
||||
struct _MutterShapedTextureClass
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmapClass parent_class;
|
||||
#else
|
||||
ClutterX11TexturePixmapClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MutterShapedTexture
|
||||
{
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
ClutterGLXTexturePixmap parent;
|
||||
#else
|
||||
ClutterX11TexturePixmap parent;
|
||||
#endif
|
||||
|
||||
MutterShapedTexturePrivate *priv;
|
||||
};
|
||||
|
||||
GType mutter_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *mutter_shaped_texture_new (void);
|
||||
|
||||
void mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex);
|
||||
|
||||
void mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
|
||||
const XRectangle *rect);
|
||||
void mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
|
||||
size_t num_rects,
|
||||
const XRectangle *rects);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MUTTER_SHAPED_TEXTURE_H__ */
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
pkglibdir=@MUTTER_PLUGIN_DIR@
|
||||
|
||||
if WITH_CLUTTER
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src/include -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@\"
|
||||
|
||||
default_la_CFLAGS = -fPIC
|
||||
@@ -16,3 +18,5 @@ pkglib_LTLIBRARIES = default.la
|
||||
install-exec-hook:
|
||||
-rm $(DESTDIR)$(pkglibdir)/*.a
|
||||
-rm $(DESTDIR)$(pkglibdir)/*.la
|
||||
|
||||
endif
|
||||
@@ -21,8 +21,7 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "meta-plugin.h"
|
||||
#include "window.h"
|
||||
#include "mutter-plugin.h"
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
@@ -40,78 +39,71 @@
|
||||
|
||||
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
|
||||
|
||||
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
|
||||
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
|
||||
#define META_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
|
||||
#define META_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_DEFAULT_PLUGIN_TYPE))
|
||||
#define META_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEFAULT_PLUGIN))
|
||||
#define META_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
|
||||
#define MUTTER_TYPE_DEFAULT_PLUGIN (mutter_default_plugin_get_type ())
|
||||
#define MUTTER_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPlugin))
|
||||
#define MUTTER_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
|
||||
#define MUTTER_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_DEFAULT_PLUGIN_TYPE))
|
||||
#define MUTTER_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_DEFAULT_PLUGIN))
|
||||
#define MUTTER_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
|
||||
|
||||
#define META_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginPrivate))
|
||||
#define MUTTER_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginPrivate))
|
||||
|
||||
typedef struct _MetaDefaultPlugin MetaDefaultPlugin;
|
||||
typedef struct _MetaDefaultPluginClass MetaDefaultPluginClass;
|
||||
typedef struct _MetaDefaultPluginPrivate MetaDefaultPluginPrivate;
|
||||
typedef struct _MutterDefaultPlugin MutterDefaultPlugin;
|
||||
typedef struct _MutterDefaultPluginClass MutterDefaultPluginClass;
|
||||
typedef struct _MutterDefaultPluginPrivate MutterDefaultPluginPrivate;
|
||||
|
||||
struct _MetaDefaultPlugin
|
||||
struct _MutterDefaultPlugin
|
||||
{
|
||||
MetaPlugin parent;
|
||||
MutterPlugin parent;
|
||||
|
||||
MetaDefaultPluginPrivate *priv;
|
||||
MutterDefaultPluginPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MetaDefaultPluginClass
|
||||
struct _MutterDefaultPluginClass
|
||||
{
|
||||
MetaPluginClass parent_class;
|
||||
MutterPluginClass parent_class;
|
||||
};
|
||||
|
||||
static GQuark actor_data_quark = 0;
|
||||
|
||||
static void minimize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void map (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void destroy (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void minimize (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void map (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void destroy (MutterPlugin *plugin,
|
||||
MutterWindow *actor);
|
||||
static void maximize (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
gint x, gint y, gint width, gint height);
|
||||
static void unmaximize (MutterPlugin *plugin,
|
||||
MutterWindow *actor,
|
||||
gint x, gint y, gint width, gint height);
|
||||
|
||||
static void switch_workspace (MetaPlugin *plugin,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
static void switch_workspace (MutterPlugin *plugin,
|
||||
const GList **actors, gint from, gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
static void kill_effect (MutterPlugin *plugin,
|
||||
MutterWindow *actor, gulong event);
|
||||
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
static const MutterPluginInfo * plugin_info (MutterPlugin *plugin);
|
||||
|
||||
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
|
||||
MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin);
|
||||
|
||||
/*
|
||||
* Plugin private data that we store in the .plugin_private member.
|
||||
*/
|
||||
struct _MetaDefaultPluginPrivate
|
||||
struct _MutterDefaultPluginPrivate
|
||||
{
|
||||
/* Valid only when switch_workspace effect is in progress */
|
||||
ClutterTimeline *tml_switch_workspace1;
|
||||
ClutterTimeline *tml_switch_workspace2;
|
||||
GList **actors;
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
MetaPluginInfo info;
|
||||
MutterPluginInfo info;
|
||||
|
||||
gboolean debug_mode : 1;
|
||||
};
|
||||
@@ -136,26 +128,26 @@ typedef struct _ActorPrivate
|
||||
typedef struct
|
||||
{
|
||||
ClutterActor *actor;
|
||||
MetaPlugin *plugin;
|
||||
MutterPlugin *plugin;
|
||||
} EffectCompleteData;
|
||||
|
||||
|
||||
static void
|
||||
meta_default_plugin_dispose (GObject *object)
|
||||
mutter_default_plugin_dispose (GObject *object)
|
||||
{
|
||||
/* MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (object)->priv;
|
||||
/* MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
|
||||
*/
|
||||
G_OBJECT_CLASS (meta_default_plugin_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_default_plugin_finalize (GObject *object)
|
||||
mutter_default_plugin_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_default_plugin_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_default_plugin_set_property (GObject *object,
|
||||
mutter_default_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
@@ -169,7 +161,7 @@ meta_default_plugin_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_default_plugin_get_property (GObject *object,
|
||||
mutter_default_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
@@ -183,9 +175,10 @@ meta_default_plugin_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
start (MetaPlugin *plugin)
|
||||
mutter_default_plugin_constructed (GObject *object)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
MutterPlugin *plugin = MUTTER_PLUGIN (object);
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
|
||||
|
||||
guint destroy_timeout = DESTROY_TIMEOUT;
|
||||
guint minimize_timeout = MINIMIZE_TIMEOUT;
|
||||
@@ -193,7 +186,7 @@ start (MetaPlugin *plugin)
|
||||
guint map_timeout = MAP_TIMEOUT;
|
||||
guint switch_timeout = SWITCH_TIMEOUT;
|
||||
|
||||
if (meta_plugin_debug_mode (plugin))
|
||||
if (mutter_plugin_debug_mode (plugin))
|
||||
{
|
||||
g_debug ("Plugin %s: Entering debug mode.", priv->info.name);
|
||||
|
||||
@@ -208,39 +201,39 @@ start (MetaPlugin *plugin)
|
||||
map_timeout *= 2;
|
||||
switch_timeout *= 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
mutter_default_plugin_class_init (MutterDefaultPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
|
||||
MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = meta_default_plugin_finalize;
|
||||
gobject_class->dispose = meta_default_plugin_dispose;
|
||||
gobject_class->set_property = meta_default_plugin_set_property;
|
||||
gobject_class->get_property = meta_default_plugin_get_property;
|
||||
gobject_class->finalize = mutter_default_plugin_finalize;
|
||||
gobject_class->dispose = mutter_default_plugin_dispose;
|
||||
gobject_class->constructed = mutter_default_plugin_constructed;
|
||||
gobject_class->set_property = mutter_default_plugin_set_property;
|
||||
gobject_class->get_property = mutter_default_plugin_get_property;
|
||||
|
||||
plugin_class->start = start;
|
||||
plugin_class->map = map;
|
||||
plugin_class->minimize = minimize;
|
||||
plugin_class->maximize = maximize;
|
||||
plugin_class->unmaximize = unmaximize;
|
||||
plugin_class->destroy = destroy;
|
||||
plugin_class->switch_workspace = switch_workspace;
|
||||
plugin_class->kill_effect = kill_effect;
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
|
||||
g_type_class_add_private (gobject_class, sizeof (MutterDefaultPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_default_plugin_init (MetaDefaultPlugin *self)
|
||||
mutter_default_plugin_init (MutterDefaultPlugin *self)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv;
|
||||
MutterDefaultPluginPrivate *priv;
|
||||
|
||||
self->priv = priv = META_DEFAULT_PLUGIN_GET_PRIVATE (self);
|
||||
self->priv = priv = MUTTER_DEFAULT_PLUGIN_GET_PRIVATE (self);
|
||||
|
||||
priv->info.name = "Default Effects";
|
||||
priv->info.version = "0.1";
|
||||
@@ -260,7 +253,7 @@ free_actor_private (gpointer data)
|
||||
}
|
||||
|
||||
static ActorPrivate *
|
||||
get_actor_private (MetaWindowActor *actor)
|
||||
get_actor_private (MutterWindow *actor)
|
||||
{
|
||||
ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark);
|
||||
|
||||
@@ -279,18 +272,26 @@ get_actor_private (MetaWindowActor *actor)
|
||||
return priv;
|
||||
}
|
||||
|
||||
typedef struct SwitchWorkspaceData
|
||||
{
|
||||
MutterPlugin *plugin;
|
||||
const GList **actors;
|
||||
} SwitchWorkspaceData;
|
||||
|
||||
static void
|
||||
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
|
||||
{
|
||||
MetaPlugin *plugin = META_PLUGIN (data);
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l = meta_plugin_get_window_actors (plugin);
|
||||
SwitchWorkspaceData *sw_data = data;
|
||||
MutterPlugin *plugin = sw_data->plugin;
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l = *((GList**)sw_data->actors);
|
||||
MutterWindow *actor_for_cb = l->data;
|
||||
|
||||
while (l)
|
||||
{
|
||||
ClutterActor *a = l->data;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (a);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (a);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
if (apriv->orig_parent)
|
||||
{
|
||||
@@ -304,32 +305,40 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
|
||||
clutter_actor_destroy (priv->desktop1);
|
||||
clutter_actor_destroy (priv->desktop2);
|
||||
|
||||
priv->actors = NULL;
|
||||
priv->tml_switch_workspace1 = NULL;
|
||||
priv->tml_switch_workspace2 = NULL;
|
||||
priv->desktop1 = NULL;
|
||||
priv->desktop2 = NULL;
|
||||
|
||||
meta_plugin_switch_workspace_completed (plugin);
|
||||
g_free (data);
|
||||
|
||||
mutter_plugin_effect_completed (plugin, actor_for_cb,
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
}
|
||||
|
||||
static void
|
||||
switch_workspace (MetaPlugin *plugin,
|
||||
gint from, gint to,
|
||||
switch_workspace (MutterPlugin *plugin,
|
||||
const GList **actors, gint from, gint to,
|
||||
MetaMotionDirection direction)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
GList *l;
|
||||
gint n_workspaces;
|
||||
ClutterActor *workspace0 = clutter_group_new ();
|
||||
ClutterActor *workspace1 = clutter_group_new ();
|
||||
ClutterActor *stage;
|
||||
int screen_width, screen_height;
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
MetaScreen *screen = mutter_plugin_get_screen (plugin);
|
||||
SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1);
|
||||
ClutterAnimation *animation;
|
||||
|
||||
stage = meta_plugin_get_stage (plugin);
|
||||
sw_data->plugin = plugin;
|
||||
sw_data->actors = actors;
|
||||
|
||||
meta_plugin_query_screen_size (plugin,
|
||||
stage = mutter_plugin_get_stage (plugin);
|
||||
|
||||
mutter_plugin_query_screen_size (plugin,
|
||||
&screen_width,
|
||||
&screen_height);
|
||||
clutter_actor_set_anchor_point (workspace1,
|
||||
@@ -346,31 +355,32 @@ switch_workspace (MetaPlugin *plugin,
|
||||
|
||||
if (from == to)
|
||||
{
|
||||
meta_plugin_switch_workspace_completed (plugin);
|
||||
mutter_plugin_effect_completed (plugin, NULL,
|
||||
MUTTER_PLUGIN_SWITCH_WORKSPACE);
|
||||
return;
|
||||
}
|
||||
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
|
||||
l = g_list_last (meta_plugin_get_window_actors (plugin));
|
||||
l = g_list_last (*((GList**) actors));
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
gint win_workspace;
|
||||
MutterWindow *mc_window = l->data;
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
ClutterActor *window = CLUTTER_ACTOR (mc_window);
|
||||
gint win_workspace;
|
||||
|
||||
win_workspace = meta_window_actor_get_workspace (window_actor);
|
||||
win_workspace = mutter_window_get_workspace (mc_window);
|
||||
|
||||
if (win_workspace == to || win_workspace == from)
|
||||
{
|
||||
apriv->orig_parent = clutter_actor_get_parent (actor);
|
||||
apriv->orig_parent = clutter_actor_get_parent (window);
|
||||
|
||||
clutter_actor_reparent (actor,
|
||||
clutter_actor_reparent (window,
|
||||
win_workspace == to ? workspace1 : workspace0);
|
||||
clutter_actor_show_all (actor);
|
||||
clutter_actor_raise_top (actor);
|
||||
clutter_actor_show_all (window);
|
||||
clutter_actor_raise_top (window);
|
||||
}
|
||||
else if (win_workspace < 0)
|
||||
{
|
||||
@@ -380,13 +390,14 @@ switch_workspace (MetaPlugin *plugin,
|
||||
else
|
||||
{
|
||||
/* Window on some other desktop */
|
||||
clutter_actor_hide (actor);
|
||||
clutter_actor_hide (window);
|
||||
apriv->orig_parent = NULL;
|
||||
}
|
||||
|
||||
l = l->prev;
|
||||
}
|
||||
|
||||
priv->actors = (GList **)actors;
|
||||
priv->desktop1 = workspace0;
|
||||
priv->desktop2 = workspace1;
|
||||
|
||||
@@ -399,7 +410,7 @@ switch_workspace (MetaPlugin *plugin,
|
||||
g_signal_connect (priv->tml_switch_workspace1,
|
||||
"completed",
|
||||
G_CALLBACK (on_switch_workspace_effect_complete),
|
||||
plugin);
|
||||
sw_data);
|
||||
|
||||
animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
|
||||
SWITCH_TIMEOUT,
|
||||
@@ -421,11 +432,11 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* Must reverse the effect of the effect; must hide it first to ensure
|
||||
* that the restoration will not be visible.
|
||||
*/
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
ActorPrivate *apriv;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
|
||||
apriv = get_actor_private (META_WINDOW_ACTOR (data->actor));
|
||||
apriv = get_actor_private (MUTTER_WINDOW (data->actor));
|
||||
apriv->tml_minimize = NULL;
|
||||
|
||||
clutter_actor_hide (data->actor);
|
||||
@@ -437,7 +448,8 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MINIMIZE);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -447,20 +459,18 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
minimize (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
{
|
||||
MetaWindowType type;
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
@@ -482,7 +492,8 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
|
||||
}
|
||||
else
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -495,9 +506,9 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
MutterPlugin * plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
apriv->tml_maximize = NULL;
|
||||
|
||||
@@ -507,7 +518,8 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAXIMIZE);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -521,26 +533,25 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
* (Something like a sound would be more appropriate.)
|
||||
*/
|
||||
static void
|
||||
maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
maximize (MutterPlugin *plugin,
|
||||
MutterWindow *mc_window,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
gfloat anchor_x = 0;
|
||||
gfloat anchor_y = 0;
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
gfloat width, height;
|
||||
gfloat x, y;
|
||||
|
||||
@@ -578,7 +589,8 @@ maximize (MetaPlugin *plugin,
|
||||
return;
|
||||
}
|
||||
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAXIMIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -587,22 +599,22 @@ maximize (MetaPlugin *plugin,
|
||||
* (Just a skeleton code.)
|
||||
*/
|
||||
static void
|
||||
unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
unmaximize (MutterPlugin *plugin,
|
||||
MutterWindow *mc_window,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaWindowType type = meta_window_get_window_type (meta_window);
|
||||
MetaCompWindowType type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
apriv->is_maximized = FALSE;
|
||||
}
|
||||
|
||||
/* Do this conditionally, if the effect requires completion callback. */
|
||||
meta_plugin_unmaximize_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_UNMAXIMIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -611,9 +623,9 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
apriv->tml_map = NULL;
|
||||
|
||||
@@ -621,7 +633,7 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
@@ -631,19 +643,18 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
* completion).
|
||||
*/
|
||||
static void
|
||||
map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
map (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
{
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
@@ -668,7 +679,8 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
|
||||
}
|
||||
else
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_MAP);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -678,32 +690,32 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
static void
|
||||
on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
{
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
MutterPlugin *plugin = data->plugin;
|
||||
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
apriv->tml_destroy = NULL;
|
||||
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple TV-out like effect.
|
||||
*/
|
||||
static void
|
||||
destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
destroy (MutterPlugin *plugin, MutterWindow *mc_window)
|
||||
{
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaCompWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
type = mutter_window_get_window_type (mc_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
if (type == META_COMP_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
ActorPrivate *apriv = get_actor_private (mc_window);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
@@ -722,59 +734,64 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
data);
|
||||
}
|
||||
else
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
mutter_plugin_effect_completed (plugin, mc_window,
|
||||
MUTTER_PLUGIN_DESTROY);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_switch_workspace (MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->tml_switch_workspace1)
|
||||
{
|
||||
clutter_timeline_stop (priv->tml_switch_workspace1);
|
||||
clutter_timeline_stop (priv->tml_switch_workspace2);
|
||||
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor)
|
||||
kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event)
|
||||
{
|
||||
ActorPrivate *apriv;
|
||||
|
||||
apriv = get_actor_private (window_actor);
|
||||
if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE)
|
||||
{
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
if (apriv->tml_minimize)
|
||||
if (priv->tml_switch_workspace1)
|
||||
{
|
||||
clutter_timeline_stop (priv->tml_switch_workspace1);
|
||||
clutter_timeline_stop (priv->tml_switch_workspace2);
|
||||
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
|
||||
}
|
||||
|
||||
if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE))
|
||||
{
|
||||
/* Workspace switch only, nothing more to do */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
apriv = get_actor_private (mc_window);
|
||||
|
||||
if ((event & MUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_minimize);
|
||||
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
|
||||
}
|
||||
|
||||
if (apriv->tml_maximize)
|
||||
if ((event & MUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_maximize);
|
||||
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
|
||||
}
|
||||
|
||||
if (apriv->tml_map)
|
||||
if ((event & MUTTER_PLUGIN_MAP) && apriv->tml_map)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_map);
|
||||
g_signal_emit_by_name (apriv->tml_map, "completed", NULL);
|
||||
}
|
||||
|
||||
if (apriv->tml_destroy)
|
||||
if ((event & MUTTER_PLUGIN_DESTROY) && apriv->tml_destroy)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_destroy);
|
||||
g_signal_emit_by_name (apriv->tml_destroy, "completed", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static const MetaPluginInfo *
|
||||
plugin_info (MetaPlugin *plugin)
|
||||
static const MutterPluginInfo *
|
||||
plugin_info (MutterPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
|
||||
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
|
||||
|
||||
return &priv->info;
|
||||
}
|
||||
610
src/compositor/mutter/tidy/tidy-texture-frame.c
Normal file
610
src/compositor/mutter/tidy/tidy-texture-frame.c
Normal file
@@ -0,0 +1,610 @@
|
||||
/* tidy-texture-frame.h: Expandible texture actor
|
||||
*
|
||||
* Copyright (C) 2007 OpenedHand
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:tidy-texture-frame
|
||||
* @short_description: Stretch a texture to fit the entire allocation
|
||||
*
|
||||
* #TidyTextureFrame
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "tidy-texture-frame.h"
|
||||
|
||||
#define TIDY_PARAM_READABLE \
|
||||
(G_PARAM_READABLE | \
|
||||
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
|
||||
|
||||
#define TIDY_PARAM_READWRITE \
|
||||
(G_PARAM_READABLE | G_PARAM_WRITABLE | \
|
||||
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_PARENT_TEXTURE,
|
||||
|
||||
PROP_LEFT,
|
||||
PROP_TOP,
|
||||
PROP_RIGHT,
|
||||
PROP_BOTTOM
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (TidyTextureFrame, tidy_texture_frame, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate))
|
||||
|
||||
struct _TidyTextureFramePrivate
|
||||
{
|
||||
ClutterTexture *parent_texture;
|
||||
|
||||
gfloat left;
|
||||
gfloat top;
|
||||
gfloat right;
|
||||
gfloat bottom;
|
||||
|
||||
CoglHandle material;
|
||||
};
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
{
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
|
||||
/* by directly querying the parent texture's class implementation
|
||||
* we are going around any override mechanism the parent texture
|
||||
* might have in place, and we ask directly for the original
|
||||
* preferred width
|
||||
*/
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
||||
klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture),
|
||||
for_height,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
{
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
|
||||
/* by directly querying the parent texture's class implementation
|
||||
* we are going around any override mechanism the parent texture
|
||||
* might have in place, and we ask directly for the original
|
||||
* preferred height
|
||||
*/
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
|
||||
klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture),
|
||||
for_width,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_realize (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
priv->material = cogl_material_new ();
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_unrealize (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
|
||||
if (priv->material == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_paint (ClutterActor *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
|
||||
CoglHandle cogl_texture = COGL_INVALID_HANDLE;
|
||||
ClutterActorBox box = { 0, };
|
||||
gfloat width, height;
|
||||
gfloat tex_width, tex_height;
|
||||
gfloat ex, ey;
|
||||
gfloat tx1, ty1, tx2, ty2;
|
||||
guint8 opacity;
|
||||
|
||||
/* no need to paint stuff if we don't have a texture */
|
||||
if (G_UNLIKELY (priv->parent_texture == NULL))
|
||||
return;
|
||||
|
||||
/* parent texture may have been hidden, so need to make sure it gets
|
||||
* realized
|
||||
*/
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture));
|
||||
|
||||
cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture);
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (cogl_texture);
|
||||
tex_height = cogl_texture_get_height (cogl_texture);
|
||||
|
||||
clutter_actor_get_allocation_box (self, &box);
|
||||
width = box.x2 - box.x1;
|
||||
height = box.y2 - box.y1;
|
||||
|
||||
tx1 = priv->left / tex_width;
|
||||
tx2 = (tex_width - priv->right) / tex_width;
|
||||
ty1 = priv->top / tex_height;
|
||||
ty2 = (tex_height - priv->bottom) / tex_height;
|
||||
|
||||
ex = width - priv->right;
|
||||
if (ex < 0)
|
||||
ex = priv->right; /* FIXME ? */
|
||||
|
||||
ey = height - priv->bottom;
|
||||
if (ey < 0)
|
||||
ey = priv->bottom; /* FIXME ? */
|
||||
|
||||
opacity = clutter_actor_get_paint_opacity (self);
|
||||
|
||||
g_assert (priv->material != COGL_INVALID_HANDLE);
|
||||
|
||||
/* set the source material using the parent texture's COGL handle */
|
||||
cogl_material_set_color4ub (priv->material, opacity, opacity, opacity, opacity);
|
||||
cogl_material_set_layer (priv->material, 0, cogl_texture);
|
||||
cogl_set_source (priv->material);
|
||||
|
||||
/* top left corner */
|
||||
cogl_rectangle_with_texture_coords (0, 0, priv->left, priv->top,
|
||||
0.0, 0.0,
|
||||
tx1, ty1);
|
||||
|
||||
/* top middle */
|
||||
cogl_rectangle_with_texture_coords (priv->left, 0, ex, priv->top,
|
||||
tx1, 0.0,
|
||||
tx2, ty1);
|
||||
|
||||
/* top right */
|
||||
cogl_rectangle_with_texture_coords (ex, 0, width, priv->top,
|
||||
tx2, 0.0,
|
||||
1.0, ty1);
|
||||
|
||||
/* mid left */
|
||||
cogl_rectangle_with_texture_coords (0, priv->top, priv->left, ey,
|
||||
0.0, ty1,
|
||||
tx1, ty2);
|
||||
|
||||
/* center */
|
||||
cogl_rectangle_with_texture_coords (priv->left, priv->top, ex, ey,
|
||||
tx1, ty1,
|
||||
tx2, ty2);
|
||||
|
||||
/* mid right */
|
||||
cogl_rectangle_with_texture_coords (ex, priv->top, width, ey,
|
||||
tx2, ty1,
|
||||
1.0, ty2);
|
||||
|
||||
/* bottom left */
|
||||
cogl_rectangle_with_texture_coords (0, ey, priv->left, height,
|
||||
0.0, ty2,
|
||||
tx1, 1.0);
|
||||
|
||||
/* bottom center */
|
||||
cogl_rectangle_with_texture_coords (priv->left, ey, ex, height,
|
||||
tx1, ty2,
|
||||
tx2, 1.0);
|
||||
|
||||
/* bottom right */
|
||||
cogl_rectangle_with_texture_coords (ex, ey, width, height,
|
||||
tx2, ty2,
|
||||
1.0, 1.0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
tidy_texture_frame_set_frame_internal (TidyTextureFrame *frame,
|
||||
gfloat left,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = frame->priv;
|
||||
GObject *gobject = G_OBJECT (frame);
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_object_freeze_notify (gobject);
|
||||
|
||||
if (priv->top != top)
|
||||
{
|
||||
priv->top = top;
|
||||
g_object_notify (gobject, "top");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->right != right)
|
||||
{
|
||||
priv->right = right;
|
||||
g_object_notify (gobject, "right");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->bottom != bottom)
|
||||
{
|
||||
priv->bottom = bottom;
|
||||
g_object_notify (gobject, "bottom");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->left != left)
|
||||
{
|
||||
priv->left = left;
|
||||
g_object_notify (gobject, "left");
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame))
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (frame));
|
||||
|
||||
g_object_thaw_notify (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TidyTextureFrame *frame = TIDY_TEXTURE_FRAME (gobject);
|
||||
TidyTextureFramePrivate *priv = frame->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_TEXTURE:
|
||||
tidy_texture_frame_set_parent_texture (frame,
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_TOP:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->left,
|
||||
g_value_get_float (value),
|
||||
priv->right,
|
||||
priv->bottom);
|
||||
break;
|
||||
|
||||
case PROP_RIGHT:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
g_value_get_float (value),
|
||||
priv->bottom,
|
||||
priv->left);
|
||||
break;
|
||||
|
||||
case PROP_BOTTOM:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
priv->right,
|
||||
g_value_get_float (value),
|
||||
priv->left);
|
||||
break;
|
||||
|
||||
case PROP_LEFT:
|
||||
tidy_texture_frame_set_frame_internal (frame,
|
||||
priv->top,
|
||||
priv->right,
|
||||
priv->bottom,
|
||||
g_value_get_float (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT_TEXTURE:
|
||||
g_value_set_object (value, priv->parent_texture);
|
||||
break;
|
||||
|
||||
case PROP_LEFT:
|
||||
g_value_set_float (value, priv->left);
|
||||
break;
|
||||
|
||||
case PROP_TOP:
|
||||
g_value_set_float (value, priv->top);
|
||||
break;
|
||||
|
||||
case PROP_RIGHT:
|
||||
g_value_set_float (value, priv->right);
|
||||
break;
|
||||
|
||||
case PROP_BOTTOM:
|
||||
g_value_set_float (value, priv->bottom);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_dispose (GObject *gobject)
|
||||
{
|
||||
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
|
||||
|
||||
if (priv->parent_texture)
|
||||
{
|
||||
g_object_unref (priv->parent_texture);
|
||||
priv->parent_texture = NULL;
|
||||
}
|
||||
|
||||
if (priv->material)
|
||||
{
|
||||
cogl_material_unref (priv->material);
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (tidy_texture_frame_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_class_init (TidyTextureFrameClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate));
|
||||
|
||||
actor_class->get_preferred_width =
|
||||
tidy_texture_frame_get_preferred_width;
|
||||
actor_class->get_preferred_height =
|
||||
tidy_texture_frame_get_preferred_height;
|
||||
actor_class->realize = tidy_texture_frame_realize;
|
||||
actor_class->unrealize = tidy_texture_frame_unrealize;
|
||||
actor_class->paint = tidy_texture_frame_paint;
|
||||
|
||||
gobject_class->set_property = tidy_texture_frame_set_property;
|
||||
gobject_class->get_property = tidy_texture_frame_get_property;
|
||||
gobject_class->dispose = tidy_texture_frame_dispose;
|
||||
|
||||
pspec = g_param_spec_object ("parent-texture",
|
||||
"Parent Texture",
|
||||
"The parent ClutterTexture",
|
||||
CLUTTER_TYPE_TEXTURE,
|
||||
TIDY_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT);
|
||||
g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("left",
|
||||
"Left",
|
||||
"Left offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_LEFT, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("top",
|
||||
"Top",
|
||||
"Top offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_TOP, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("bottom",
|
||||
"Bottom",
|
||||
"Bottom offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec);
|
||||
|
||||
pspec = g_param_spec_float ("right",
|
||||
"Right",
|
||||
"Right offset",
|
||||
0, G_MAXFLOAT,
|
||||
0,
|
||||
TIDY_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_RIGHT, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
tidy_texture_frame_init (TidyTextureFrame *self)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
|
||||
self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self);
|
||||
|
||||
priv->material = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* tidy_texture_frame_new:
|
||||
* @texture: a #ClutterTexture or %NULL
|
||||
* @left: left margin preserving its content
|
||||
* @top: top margin preserving its content
|
||||
* @right: right margin preserving its content
|
||||
* @bottom: bottom margin preserving its content
|
||||
*
|
||||
* A #TidyTextureFrame is a specialized texture that efficiently clones
|
||||
* an area of the given @texture while keeping preserving portions of the
|
||||
* same texture.
|
||||
*
|
||||
* A #TidyTextureFrame can be used to make a rectangular texture fit a
|
||||
* given size without stretching its borders.
|
||||
*
|
||||
* Return value: the newly created #TidyTextureFrame
|
||||
*/
|
||||
ClutterActor*
|
||||
tidy_texture_frame_new (ClutterTexture *texture,
|
||||
gfloat left,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom)
|
||||
{
|
||||
g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return g_object_new (TIDY_TYPE_TEXTURE_FRAME,
|
||||
"parent-texture", texture,
|
||||
"left", left,
|
||||
"top", top,
|
||||
"right", right,
|
||||
"bottom", bottom,
|
||||
NULL);
|
||||
}
|
||||
|
||||
ClutterTexture *
|
||||
tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame)
|
||||
{
|
||||
g_return_val_if_fail (TIDY_IS_TEXTURE_FRAME (frame), NULL);
|
||||
|
||||
return frame->priv->parent_texture;
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
|
||||
ClutterTexture *texture)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
gboolean was_visible;
|
||||
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture));
|
||||
|
||||
priv = frame->priv;
|
||||
|
||||
was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame);
|
||||
|
||||
if (priv->parent_texture == texture)
|
||||
return;
|
||||
|
||||
if (priv->parent_texture)
|
||||
{
|
||||
g_object_unref (priv->parent_texture);
|
||||
priv->parent_texture = NULL;
|
||||
|
||||
if (was_visible)
|
||||
clutter_actor_hide (CLUTTER_ACTOR (frame));
|
||||
}
|
||||
|
||||
if (texture)
|
||||
{
|
||||
priv->parent_texture = g_object_ref (texture);
|
||||
|
||||
if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture))
|
||||
clutter_actor_show (CLUTTER_ACTOR (frame));
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
|
||||
|
||||
g_object_notify (G_OBJECT (frame), "parent-texture");
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_set_frame (TidyTextureFrame *frame,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left)
|
||||
{
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
|
||||
tidy_texture_frame_set_frame_internal (frame, top, right, bottom, left);
|
||||
}
|
||||
|
||||
void
|
||||
tidy_texture_frame_get_frame (TidyTextureFrame *frame,
|
||||
gfloat *top,
|
||||
gfloat *right,
|
||||
gfloat *bottom,
|
||||
gfloat *left)
|
||||
{
|
||||
TidyTextureFramePrivate *priv;
|
||||
|
||||
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
|
||||
|
||||
priv = frame->priv;
|
||||
|
||||
if (top)
|
||||
*top = priv->top;
|
||||
|
||||
if (right)
|
||||
*right = priv->right;
|
||||
|
||||
if (bottom)
|
||||
*bottom = priv->bottom;
|
||||
|
||||
if (left)
|
||||
*left = priv->left;
|
||||
}
|
||||
81
src/compositor/mutter/tidy/tidy-texture-frame.h
Normal file
81
src/compositor/mutter/tidy/tidy-texture-frame.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* tidy-texture-frame.h: Expandible texture actor
|
||||
*
|
||||
* Copyright (C) 2007, 2008 OpenedHand Ltd
|
||||
* Copyright (C) 2009 Intel Corp.
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _HAVE_TIDY_TEXTURE_FRAME_H
|
||||
#define _HAVE_TIDY_TEXTURE_FRAME_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ())
|
||||
#define TIDY_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame))
|
||||
#define TIDY_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
|
||||
#define TIDY_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIDY_TYPE_TEXTURE_FRAME))
|
||||
#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIDY_TYPE_TEXTURE_FRAME))
|
||||
#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
|
||||
|
||||
typedef struct _TidyTextureFrame TidyTextureFrame;
|
||||
typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate;
|
||||
typedef struct _TidyTextureFrameClass TidyTextureFrameClass;
|
||||
|
||||
struct _TidyTextureFrame
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent_instance;
|
||||
|
||||
TidyTextureFramePrivate *priv;
|
||||
};
|
||||
|
||||
struct _TidyTextureFrameClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_clutter_box_1) (void);
|
||||
void (*_clutter_box_2) (void);
|
||||
void (*_clutter_box_3) (void);
|
||||
void (*_clutter_box_4) (void);
|
||||
};
|
||||
|
||||
GType tidy_texture_frame_get_type (void) G_GNUC_CONST;
|
||||
ClutterActor * tidy_texture_frame_new (ClutterTexture *texture,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left);
|
||||
void tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
|
||||
ClutterTexture *texture);
|
||||
ClutterTexture *tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame);
|
||||
void tidy_texture_frame_set_frame (TidyTextureFrame *frame,
|
||||
gfloat top,
|
||||
gfloat right,
|
||||
gfloat bottom,
|
||||
gfloat left);
|
||||
void tidy_texture_frame_get_frame (TidyTextureFrame *frame,
|
||||
gfloat *top,
|
||||
gfloat *right,
|
||||
gfloat *bottom,
|
||||
gfloat *left);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _HAVE_TIDY_TEXTURE_FRAME_H */
|
||||
@@ -1,334 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Utilities for region manipulation
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "region-utils.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* MetaRegionBuilder */
|
||||
|
||||
/* Various algorithms in this file require unioning together a set of rectangles
|
||||
* that are unsorted or overlap; unioning such a set of rectangles 1-by-1
|
||||
* using cairo_region_union_rectangle() produces O(N^2) behavior (if the union
|
||||
* adds or removes rectangles in the middle of the region, then it has to
|
||||
* move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder
|
||||
* creates regions for small groups of rectangles and merges them together in
|
||||
* a binary tree.
|
||||
*
|
||||
* Possible improvement: From a glance at the code, accumulating all the rectangles
|
||||
* into a flat array and then calling the (not usefully documented)
|
||||
* cairo_region_create_rectangles() would have the same behavior and would be
|
||||
* simpler and a bit more efficient.
|
||||
*/
|
||||
|
||||
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
|
||||
* But using 8 may be more robust to systems with slow malloc(). */
|
||||
#define MAX_CHUNK_RECTANGLES 8
|
||||
#define MAX_LEVELS 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* To merge regions in a binary tree, we need to keep track of The way these are filled is in the pattern:
|
||||
*
|
||||
* |a |
|
||||
* |b |a |
|
||||
* |c | |ab |
|
||||
* |d |c |ab |
|
||||
* |e | | |abcd|
|
||||
*/
|
||||
cairo_region_t *levels[MAX_LEVELS];
|
||||
int n_levels;
|
||||
} MetaRegionBuilder;
|
||||
|
||||
static void
|
||||
meta_region_builder_init (MetaRegionBuilder *builder)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_LEVELS; i++)
|
||||
builder->levels[i] = NULL;
|
||||
builder->n_levels = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int i;
|
||||
|
||||
if (builder->levels[0] == NULL)
|
||||
builder->levels[0] = cairo_region_create ();
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
cairo_region_union_rectangle (builder->levels[0], &rect);
|
||||
if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES)
|
||||
{
|
||||
for (i = 1; i < builder->n_levels + 1; i++)
|
||||
{
|
||||
if (builder->levels[i] == NULL)
|
||||
{
|
||||
if (i < MAX_LEVELS)
|
||||
{
|
||||
builder->levels[i] = builder->levels[i - 1];
|
||||
builder->levels[i - 1] = NULL;
|
||||
if (i == builder->n_levels)
|
||||
builder->n_levels++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_region_union (builder->levels[i], builder->levels[i - 1]);
|
||||
cairo_region_destroy (builder->levels[i - 1]);
|
||||
builder->levels[i - 1] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
meta_region_builder_finish (MetaRegionBuilder *builder)
|
||||
{
|
||||
cairo_region_t *result = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < builder->n_levels; i++)
|
||||
{
|
||||
if (builder->levels[i])
|
||||
{
|
||||
if (result == NULL)
|
||||
result = builder->levels[i];
|
||||
else
|
||||
{
|
||||
cairo_region_union(result, builder->levels[i]);
|
||||
cairo_region_destroy (builder->levels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
result = cairo_region_create ();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* MetaRegionIterator */
|
||||
|
||||
void
|
||||
meta_region_iterator_init (MetaRegionIterator *iter,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
iter->region = region;
|
||||
iter->i = 0;
|
||||
iter->n_rectangles = cairo_region_num_rectangles (region);
|
||||
iter->line_start = TRUE;
|
||||
|
||||
if (iter->n_rectangles > 1)
|
||||
{
|
||||
cairo_region_get_rectangle (region, 0, &iter->rectangle);
|
||||
cairo_region_get_rectangle (region, 1, &iter->next_rectangle);
|
||||
|
||||
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
|
||||
}
|
||||
else if (iter->n_rectangles > 0)
|
||||
{
|
||||
cairo_region_get_rectangle (region, 0, &iter->rectangle);
|
||||
iter->line_end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_region_iterator_at_end (MetaRegionIterator *iter)
|
||||
{
|
||||
return iter->i >= iter->n_rectangles;
|
||||
}
|
||||
|
||||
void
|
||||
meta_region_iterator_next (MetaRegionIterator *iter)
|
||||
{
|
||||
iter->i++;
|
||||
iter->rectangle = iter->next_rectangle;
|
||||
iter->line_start = iter->line_end;
|
||||
|
||||
if (iter->i < iter->n_rectangles)
|
||||
{
|
||||
cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle);
|
||||
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->line_end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_expanded_rect (MetaRegionBuilder *builder,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
if (flip)
|
||||
meta_region_builder_add_rectangle (builder,
|
||||
y - y_amount, x - x_amount,
|
||||
height + 2 * y_amount, width + 2 * x_amount);
|
||||
else
|
||||
meta_region_builder_add_rectangle (builder,
|
||||
x - x_amount, y - y_amount,
|
||||
width + 2 * x_amount, height + 2 * y_amount);
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
expand_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
MetaRegionBuilder builder;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
meta_region_builder_init (&builder);
|
||||
|
||||
n = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
add_expanded_rect (&builder,
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
x_amount, y_amount, flip);
|
||||
}
|
||||
|
||||
return meta_region_builder_finish (&builder);
|
||||
}
|
||||
|
||||
/* This computes a (clipped version) of the inverse of the region
|
||||
* and expands it by the given amount */
|
||||
static cairo_region_t *
|
||||
expand_region_inverse (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
MetaRegionBuilder builder;
|
||||
MetaRegionIterator iter;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_region_t *chunk;
|
||||
|
||||
int last_x;
|
||||
|
||||
meta_region_builder_init (&builder);
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x, extents.y - 1, extents.width, 1,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x - 1, extents.y, 1, extents.height,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x + extents.width, extents.y, 1, extents.height,
|
||||
x_amount, y_amount, flip);
|
||||
add_expanded_rect (&builder,
|
||||
extents.x, extents.y + extents.height, extents.width, 1,
|
||||
x_amount, y_amount, flip);
|
||||
|
||||
chunk = NULL;
|
||||
|
||||
last_x = extents.x;
|
||||
for (meta_region_iterator_init (&iter, region);
|
||||
!meta_region_iterator_at_end (&iter);
|
||||
meta_region_iterator_next (&iter))
|
||||
{
|
||||
if (chunk == NULL)
|
||||
chunk = cairo_region_create ();
|
||||
|
||||
if (iter.rectangle.x > last_x)
|
||||
add_expanded_rect (&builder,
|
||||
last_x, iter.rectangle.y,
|
||||
iter.rectangle.x - last_x, iter.rectangle.height,
|
||||
x_amount, y_amount, flip);
|
||||
|
||||
if (iter.line_end)
|
||||
{
|
||||
if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width)
|
||||
add_expanded_rect (&builder,
|
||||
iter.rectangle.x + iter.rectangle.width, iter.rectangle.y,
|
||||
(extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height,
|
||||
x_amount, y_amount, flip);
|
||||
last_x = extents.x;
|
||||
}
|
||||
else
|
||||
last_x = iter.rectangle.x + iter.rectangle.width;
|
||||
}
|
||||
|
||||
return meta_region_builder_finish (&builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_make_border_region:
|
||||
* @region: a #cairo_region_t
|
||||
* @x_amount: distance from the border to extend horizontally
|
||||
* @y_amount: distance from the border to extend vertically
|
||||
* @flip: if true, the result is computed with x and y interchanged
|
||||
*
|
||||
* Computes the "border region" of a given region, which is roughly
|
||||
* speaking the set of points near the boundary of the region. If we
|
||||
* define the operation of growing a region as computing the set of
|
||||
* points within a given manhattan distance of the region, then the
|
||||
* border is 'grow(region) intersect grow(inverse(region))'.
|
||||
*
|
||||
* If we create an image by filling the region with a solid color,
|
||||
* the border is the region affected by blurring the region.
|
||||
*
|
||||
* Return value: a new region which is the border of the given region
|
||||
*/
|
||||
cairo_region_t *
|
||||
meta_make_border_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip)
|
||||
{
|
||||
cairo_region_t *border_region;
|
||||
cairo_region_t *inverse_region;
|
||||
|
||||
border_region = expand_region (region, x_amount, y_amount, flip);
|
||||
inverse_region = expand_region_inverse (region, x_amount, y_amount, flip);
|
||||
cairo_region_intersect (border_region, inverse_region);
|
||||
cairo_region_destroy (inverse_region);
|
||||
|
||||
return border_region;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Utilities for region manipulation
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_REGION_UTILS_H__
|
||||
#define __META_REGION_UTILS_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
/**
|
||||
* MetaRegionIterator:
|
||||
* @region: region being iterated
|
||||
* @rectangle: current rectangle
|
||||
* @line_start: whether the current rectangle starts a horizontal band
|
||||
* @line_end: whether the current rectangle ends a horizontal band
|
||||
*
|
||||
* cairo_region_t is a yx banded region; sometimes its useful to iterate through
|
||||
* such a region treating the start and end of each horizontal band in a distinct
|
||||
* fashion.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* MetaRegionIterator iter;
|
||||
* for (meta_region_iterator_init (&iter, region);
|
||||
* !meta_region_iterator_at_end (&iter);
|
||||
* meta_region_iterator_next (&iter))
|
||||
* {
|
||||
* [ Use iter.rectangle, iter.line_start, iter.line_end ]
|
||||
* }
|
||||
*/
|
||||
typedef struct _MetaRegionIterator MetaRegionIterator;
|
||||
|
||||
struct _MetaRegionIterator {
|
||||
cairo_region_t *region;
|
||||
cairo_rectangle_int_t rectangle;
|
||||
gboolean line_start;
|
||||
gboolean line_end;
|
||||
int i;
|
||||
|
||||
/*< private >*/
|
||||
int n_rectangles;
|
||||
cairo_rectangle_int_t next_rectangle;
|
||||
};
|
||||
|
||||
void meta_region_iterator_init (MetaRegionIterator *iter,
|
||||
cairo_region_t *region);
|
||||
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
|
||||
void meta_region_iterator_next (MetaRegionIterator *iter);
|
||||
|
||||
cairo_region_t *meta_make_border_region (cairo_region_t *region,
|
||||
int x_amount,
|
||||
int y_amount,
|
||||
gboolean flip);
|
||||
|
||||
#endif /* __META_REGION_UTILS_H__ */
|
||||
138
src/core/alttabhandler.c
Normal file
138
src/core/alttabhandler.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Alt-Tab abstraction */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "alttabhandlerdefault.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
static GType handler_type = G_TYPE_INVALID;
|
||||
|
||||
GType meta_alt_tab_handler_default_get_type (void);
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_register (GType type)
|
||||
{
|
||||
handler_type = type;
|
||||
}
|
||||
|
||||
MetaAltTabHandler *
|
||||
meta_alt_tab_handler_new (MetaScreen *screen,
|
||||
gboolean immediate)
|
||||
{
|
||||
if (handler_type == G_TYPE_INVALID)
|
||||
handler_type = meta_alt_tab_handler_default_get_type ();
|
||||
|
||||
return g_object_new (handler_type,
|
||||
"screen", screen,
|
||||
"immediate", immediate,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void meta_alt_tab_handler_class_init (GObjectClass *object_class);
|
||||
|
||||
GType
|
||||
meta_alt_tab_handler_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||
{
|
||||
const GTypeInfo type_info =
|
||||
{
|
||||
sizeof (MetaAltTabHandlerInterface), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc)meta_alt_tab_handler_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
0,
|
||||
0, /* n_preallocs */
|
||||
NULL
|
||||
};
|
||||
GType g_define_type_id =
|
||||
g_type_register_static (G_TYPE_INTERFACE, "MetaAltTabHandler",
|
||||
&type_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
|
||||
|
||||
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_class_init (GObjectClass *object_class)
|
||||
{
|
||||
g_object_interface_install_property (object_class,
|
||||
g_param_spec_object ("screen",
|
||||
"Screen",
|
||||
"MetaScreen this is the switcher for",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_interface_install_property (object_class,
|
||||
g_param_spec_boolean ("immediate",
|
||||
"Immediate mode",
|
||||
"Whether or not to select windows immediately",
|
||||
FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
|
||||
MetaWindow *window)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->add_window (handler, window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_show (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->show (handler,
|
||||
initial_selection);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_destroy (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->destroy (handler);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_forward (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->forward (handler);
|
||||
}
|
||||
|
||||
void
|
||||
meta_alt_tab_handler_backward (MetaAltTabHandler *handler)
|
||||
{
|
||||
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->backward (handler);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler)
|
||||
{
|
||||
return META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->get_selected (handler);
|
||||
}
|
||||
223
src/core/alttabhandlerdefault.c
Normal file
223
src/core/alttabhandlerdefault.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Alt-Tab abstraction: default implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "alttabhandlerdefault.h"
|
||||
#include "frame-private.h"
|
||||
#include "window-private.h"
|
||||
|
||||
static void meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaAltTabHandlerDefault, meta_alt_tab_handler_default, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_ALT_TAB_HANDLER,
|
||||
meta_alt_tab_handler_default_interface_init))
|
||||
|
||||
enum {
|
||||
PROP_SCREEN = 1,
|
||||
PROP_IMMEDIATE
|
||||
};
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_init (MetaAltTabHandlerDefault *hd)
|
||||
{
|
||||
hd->entries = g_array_new (FALSE, FALSE, sizeof (MetaTabEntry));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
hd->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_IMMEDIATE:
|
||||
hd->immediate_mode = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_finalize (GObject *object)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
|
||||
|
||||
g_array_free (hd->entries, TRUE);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_free (hd->tab_popup);
|
||||
|
||||
G_OBJECT_CLASS (meta_alt_tab_handler_default_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_add_window (MetaAltTabHandler *handler,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
MetaTabEntry entry;
|
||||
MetaRectangle r;
|
||||
|
||||
entry.key = (MetaTabEntryKey) window;
|
||||
entry.title = window->title;
|
||||
entry.icon = window->icon;
|
||||
entry.blank = FALSE;
|
||||
entry.hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entry.demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (hd->immediate_mode || !entry.hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_outer_rect (window, &r);
|
||||
entry.rect = r;
|
||||
|
||||
/* Find inside of highlight rectangle to be used when window is
|
||||
* outlined for tabbing. This should be the size of the
|
||||
* east/west frame, and the size of the south frame, on those
|
||||
* sides. On the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
#define OUTLINE_WIDTH 5
|
||||
/* Top side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entry.inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entry.inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entry.inner_rect.height = r.height
|
||||
- entry.inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entry.inner_rect.height = r.height
|
||||
- entry.inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entry.hidden && window->frame && window->frame->child_x != 0)
|
||||
entry.inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entry.inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entry.hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entry.inner_rect.width = r.width
|
||||
- entry.inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entry.inner_rect.width = r.width
|
||||
- entry.inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
g_array_append_val (hd->entries, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_show (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
return;
|
||||
|
||||
hd->tab_popup = meta_ui_tab_popup_new ((MetaTabEntry *)hd->entries->data,
|
||||
hd->screen->number,
|
||||
hd->entries->len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
meta_ui_tab_popup_select (hd->tab_popup, (MetaTabEntryKey) initial_selection);
|
||||
meta_ui_tab_popup_set_showing (hd->tab_popup, !hd->immediate_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_destroy (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (hd->tab_popup);
|
||||
hd->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_forward (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_forward (hd->tab_popup);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_backward (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
meta_ui_tab_popup_backward (hd->tab_popup);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_alt_tab_handler_default_get_selected (MetaAltTabHandler *handler)
|
||||
{
|
||||
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
|
||||
|
||||
if (hd->tab_popup)
|
||||
return (MetaWindow *)meta_ui_tab_popup_get_selected (hd->tab_popup);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_class_init (MetaAltTabHandlerDefaultClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = meta_alt_tab_handler_default_set_property;
|
||||
object_class->finalize = meta_alt_tab_handler_default_finalize;
|
||||
|
||||
g_object_class_override_property (object_class, PROP_SCREEN, "screen");
|
||||
g_object_class_override_property (object_class, PROP_IMMEDIATE, "immediate");
|
||||
}
|
||||
|
||||
static void
|
||||
meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface)
|
||||
{
|
||||
handler_iface->add_window = meta_alt_tab_handler_default_add_window;
|
||||
handler_iface->show = meta_alt_tab_handler_default_show;
|
||||
handler_iface->destroy = meta_alt_tab_handler_default_destroy;
|
||||
handler_iface->forward = meta_alt_tab_handler_default_forward;
|
||||
handler_iface->backward = meta_alt_tab_handler_default_backward;
|
||||
handler_iface->get_selected = meta_alt_tab_handler_default_get_selected;
|
||||
}
|
||||
@@ -52,9 +52,6 @@
|
||||
#include "bell.h"
|
||||
#include "screen-private.h"
|
||||
#include "prefs.h"
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Flashes one entire screen. This is done by making a window the size of the
|
||||
@@ -231,18 +228,18 @@ bell_flash_window_frame (MetaWindow *window)
|
||||
*/
|
||||
static void
|
||||
bell_flash_frame (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
MetaWindow *window;
|
||||
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window))
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
{
|
||||
window = display->focus_window;
|
||||
}
|
||||
if (window && window->frame)
|
||||
if (window)
|
||||
{
|
||||
bell_flash_window_frame (window);
|
||||
}
|
||||
@@ -288,48 +285,6 @@ meta_bell_notify (MetaDisplay *display,
|
||||
/* flash something */
|
||||
if (meta_prefs_get_visual_bell ())
|
||||
bell_visual_notify (display, xkb_ev);
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
if (meta_prefs_bell_is_audible ())
|
||||
{
|
||||
ca_proplist *p;
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
|
||||
MetaWindow *window;
|
||||
int res;
|
||||
|
||||
ca_proplist_create (&p);
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
window = display->focus_window;
|
||||
|
||||
if (window)
|
||||
{
|
||||
ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title);
|
||||
ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow);
|
||||
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name);
|
||||
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid);
|
||||
}
|
||||
|
||||
/* First, we try to play a real sound ... */
|
||||
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
|
||||
|
||||
ca_proplist_destroy (p);
|
||||
|
||||
if (res != CA_SUCCESS && res != CA_ERROR_DISABLED)
|
||||
{
|
||||
/* ...and in case that failed we use the classic X11 bell. */
|
||||
XkbForceDeviceBell (display->xdisplay,
|
||||
xkb_bell_event->device,
|
||||
xkb_bell_event->bell_class,
|
||||
xkb_bell_event->bell_id,
|
||||
xkb_bell_event->percent);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
@@ -337,19 +292,11 @@ void
|
||||
meta_bell_set_audible (MetaDisplay *display, gboolean audible)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
/* When we are playing sounds using libcanberra support, we handle the
|
||||
* bell whether its an audible bell or a visible bell */
|
||||
gboolean enable_system_bell = FALSE;
|
||||
#else
|
||||
gboolean enable_system_bell = audible;
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
enable_system_bell ? XkbAudibleBellMask : 0);
|
||||
#endif /* HAVE_XKB */
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
audible ? XkbAudibleBellMask : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -376,7 +323,11 @@ meta_bell_init (MetaDisplay *display)
|
||||
XkbUseCoreKbd,
|
||||
XkbBellNotifyMask,
|
||||
XkbBellNotifyMask);
|
||||
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
meta_prefs_bell_is_audible ()
|
||||
? XkbAudibleBellMask : 0);
|
||||
if (visual_bell_auto_reset) {
|
||||
XkbSetAutoResetControls (display->xdisplay,
|
||||
XkbAudibleBellMask,
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Simple box operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005, 2006 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_BOXES_PRIVATE_H
|
||||
#define META_BOXES_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "common.h"
|
||||
#include "boxes.h"
|
||||
|
||||
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
|
||||
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
|
||||
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
|
||||
#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FIXED_DIRECTION_NONE = 0,
|
||||
FIXED_DIRECTION_X = 1 << 0,
|
||||
FIXED_DIRECTION_Y = 1 << 1,
|
||||
} FixedDirections;
|
||||
|
||||
/* Output functions -- note that the output buffer had better be big enough:
|
||||
* rect_to_string: RECT_LENGTH
|
||||
* region_to_string: (RECT_LENGTH+strlen(separator_string)) *
|
||||
* g_list_length (region)
|
||||
* edge_to_string: EDGE_LENGTH
|
||||
* edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
|
||||
* g_list_length (edge_list)
|
||||
*/
|
||||
#define RECT_LENGTH 27
|
||||
#define EDGE_LENGTH 37
|
||||
char* meta_rectangle_to_string (const MetaRectangle *rect,
|
||||
char *output);
|
||||
char* meta_rectangle_region_to_string (GList *region,
|
||||
const char *separator_string,
|
||||
char *output);
|
||||
char* meta_rectangle_edge_to_string (const MetaEdge *edge,
|
||||
char *output);
|
||||
char* meta_rectangle_edge_list_to_string (
|
||||
GList *edge_list,
|
||||
const char *separator_string,
|
||||
char *output);
|
||||
|
||||
/* Resize old_rect to the given new_width and new_height, but store the
|
||||
* result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
|
||||
* A MOVERESIZE OPERATION (that simplies the routine a little bit as it
|
||||
* means there's no difference between NorthWestGravity and StaticGravity.
|
||||
* Also, I lied a little bit--technically, you could use it in a MoveResize
|
||||
* operation if you muck with old_rect just right).
|
||||
*/
|
||||
void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
|
||||
MetaRectangle *rect,
|
||||
int gravity,
|
||||
int new_width,
|
||||
int new_height);
|
||||
|
||||
/* find a list of rectangles with the property that a window is contained
|
||||
* in the given region if and only if it is contained in one of the
|
||||
* rectangles in the list.
|
||||
*
|
||||
* In this case, the region is given by taking basic_rect, removing from
|
||||
* it the intersections with all the rectangles in the all_struts list,
|
||||
* then expanding all the rectangles in the resulting list by the given
|
||||
* amounts on each side.
|
||||
*
|
||||
* See boxes.c for more details.
|
||||
*/
|
||||
GList* meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Expand all rectangles in region by the given amount on each side */
|
||||
GList* meta_rectangle_expand_region (GList *region,
|
||||
const int left_expand,
|
||||
const int right_expand,
|
||||
const int top_expand,
|
||||
const int bottom_expand);
|
||||
/* Same as for meta_rectangle_expand_region except that rectangles not at
|
||||
* least min_x or min_y in size are not expanded in that direction
|
||||
*/
|
||||
GList* meta_rectangle_expand_region_conditionally (
|
||||
GList *region,
|
||||
const int left_expand,
|
||||
const int right_expand,
|
||||
const int top_expand,
|
||||
const int bottom_expand,
|
||||
const int min_x,
|
||||
const int min_y);
|
||||
|
||||
/* Expand rect in direction to the size of expand_to, and then clip out any
|
||||
* overlapping struts oriented orthognal to the expansion direction. (Think
|
||||
* horizontal or vertical maximization)
|
||||
*/
|
||||
void meta_rectangle_expand_to_avoiding_struts (
|
||||
MetaRectangle *rect,
|
||||
const MetaRectangle *expand_to,
|
||||
const MetaDirection direction,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Free the list created by
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region()
|
||||
* or
|
||||
* meta_rectangle_find_onscreen_edges ()
|
||||
* or
|
||||
* meta_rectangle_find_nonintersected_monitor_edges()
|
||||
*/
|
||||
void meta_rectangle_free_list_and_elements (GList *filled_list);
|
||||
|
||||
/* could_fit_in_region determines whether one of the spanning_rects is
|
||||
* big enough to contain rect. contained_in_region checks whether one
|
||||
* actually contains it.
|
||||
*/
|
||||
gboolean meta_rectangle_could_fit_in_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
gboolean meta_rectangle_contained_in_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
gboolean meta_rectangle_overlaps_with_region (
|
||||
const GList *spanning_rects,
|
||||
const MetaRectangle *rect);
|
||||
|
||||
/* Make the rectangle small enough to fit into one of the spanning_rects,
|
||||
* but make it no smaller than min_size.
|
||||
*/
|
||||
void meta_rectangle_clamp_to_fit_into_region (
|
||||
const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect,
|
||||
const MetaRectangle *min_size);
|
||||
|
||||
/* Clip the rectangle so that it fits into one of the spanning_rects, assuming
|
||||
* it overlaps with at least one of them
|
||||
*/
|
||||
void meta_rectangle_clip_to_region (const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/* Shove the rectangle into one of the spanning_rects, assuming it fits in
|
||||
* one of them.
|
||||
*/
|
||||
void meta_rectangle_shove_into_region(
|
||||
const GList *spanning_rects,
|
||||
FixedDirections fixed_directions,
|
||||
MetaRectangle *rect);
|
||||
|
||||
/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
|
||||
* to (px, py). Useful for finding an optimal rectangle size when given a
|
||||
* range between two sizes that are all candidates.
|
||||
*/
|
||||
void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1,
|
||||
double x2, double y2,
|
||||
double px, double py,
|
||||
double *valx, double *valy);
|
||||
|
||||
/***************************************************************************/
|
||||
/* */
|
||||
/* Switching gears to code for edges instead of just rectangles */
|
||||
/* */
|
||||
/***************************************************************************/
|
||||
|
||||
/* Return whether an edge overlaps or is adjacent to the rectangle in the
|
||||
* nonzero-width dimension of the edge.
|
||||
*/
|
||||
gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
|
||||
const MetaEdge *edge);
|
||||
|
||||
/* Compare two edges, so that sorting functions can put a list of edges in
|
||||
* canonical order.
|
||||
*/
|
||||
gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
|
||||
|
||||
/* Compare two edges, so that sorting functions can put a list of edges in
|
||||
* order. This function doesn't separate left edges first, then right edges,
|
||||
* etc., but rather compares only upon location.
|
||||
*/
|
||||
gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
|
||||
|
||||
/* Removes an parts of edges in the given list that intersect any box in the
|
||||
* given rectangle list. Returns the result.
|
||||
*/
|
||||
GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
|
||||
GList *edges,
|
||||
const GSList *rectangles);
|
||||
|
||||
/* Finds all the edges of an onscreen region, returning a GList* of
|
||||
* MetaEdgeRect's.
|
||||
*/
|
||||
GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Finds edges between adjacent monitors which are not covered by the given
|
||||
* struts.
|
||||
*/
|
||||
GList* meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_rects,
|
||||
const GSList *all_struts);
|
||||
|
||||
#endif /* META_BOXES_PRIVATE_H */
|
||||
@@ -26,39 +26,10 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "boxes-private.h"
|
||||
#include "boxes.h"
|
||||
#include "util.h"
|
||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||
|
||||
/* It would make sense to use GSlice here, but until we clean up the
|
||||
* rest of this file and the internal API to use these functions, we
|
||||
* leave it using g_malloc()/g_free() for consistency.
|
||||
*/
|
||||
|
||||
MetaRectangle *
|
||||
meta_rectangle_copy (const MetaRectangle *rect)
|
||||
{
|
||||
return g_memdup (rect, sizeof (MetaRectangle));
|
||||
}
|
||||
|
||||
void
|
||||
meta_rectangle_free (MetaRectangle *rect)
|
||||
{
|
||||
g_free (rect);
|
||||
}
|
||||
|
||||
GType
|
||||
meta_rectangle_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("MetaRectangle"),
|
||||
(GBoxedCopyFunc) meta_rectangle_copy,
|
||||
(GBoxedFreeFunc) meta_rectangle_free);
|
||||
return type_id;
|
||||
}
|
||||
|
||||
char*
|
||||
meta_rectangle_to_string (const MetaRectangle *rect,
|
||||
char *output)
|
||||
@@ -529,12 +500,7 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
return b_area - a_area; /* positive ret value denotes b > a, ... */
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region:
|
||||
* @basic_rect: Input rectangle
|
||||
* @all_struts: (element-type Meta.Rectangle): List of struts
|
||||
*
|
||||
* This function is trying to find a "minimal spanning set (of rectangles)"
|
||||
/* This function is trying to find a "minimal spanning set (of rectangles)"
|
||||
* for a given region.
|
||||
*
|
||||
* The region is given by taking basic_rect, then removing the areas
|
||||
@@ -547,7 +513,10 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
* the region if and only if it is contained within at least one of the
|
||||
* rectangles.
|
||||
*
|
||||
* Returns: (transfer full) (element-type Meta.Rectangle): Minimal spanning set
|
||||
* The GList* returned will be a list of (allocated) MetaRectangles.
|
||||
* The list will need to be freed by calling
|
||||
* meta_rectangle_free_spanning_set() on it (or by manually
|
||||
* implementing that function...)
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
@@ -566,7 +535,7 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
* enough to make this worth bothering. Further, it is only called from
|
||||
* workspace.c:ensure_work_areas_validated (at least as of the time of
|
||||
* writing this comment), which in turn should only be called if the
|
||||
* strut list changes or the screen or monitor size changes. If it ever
|
||||
* strut list changes or the screen or xinerama size changes. If it ever
|
||||
* does show up on profiles (most likely because people start using
|
||||
* ridiculously huge numbers of partial struts), possible optimizations
|
||||
* include:
|
||||
@@ -680,10 +649,6 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_expand_region: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_expand_region (GList *region,
|
||||
const int left_expand,
|
||||
@@ -700,10 +665,6 @@ meta_rectangle_expand_region (GList *region,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_expand_region_conditionally: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_expand_region_conditionally (GList *region,
|
||||
const int left_expand,
|
||||
@@ -1681,10 +1642,7 @@ fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_remove_intersections_with_boxes_from_edges: (skip)
|
||||
*
|
||||
* This function removes intersections of edges with the rectangles from the
|
||||
/* This function removes intersections of edges with the rectangles from the
|
||||
* list of edges.
|
||||
*/
|
||||
GList*
|
||||
@@ -1750,11 +1708,7 @@ meta_rectangle_remove_intersections_with_boxes_from_edges (
|
||||
return edges;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_find_onscreen_edges: (skip)
|
||||
*
|
||||
* This function is trying to find all the edges of an onscreen region.
|
||||
*/
|
||||
/* This function is trying to find all the edges of an onscreen region. */
|
||||
GList*
|
||||
meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts)
|
||||
@@ -1837,19 +1791,15 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_find_nonintersected_monitor_edges: (skip)
|
||||
*
|
||||
*/
|
||||
GList*
|
||||
meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_rects,
|
||||
meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
const GList *xinerama_rects,
|
||||
const GSList *all_struts)
|
||||
{
|
||||
/* This function cannot easily be merged with
|
||||
* meta_rectangle_find_onscreen_edges() because real screen edges
|
||||
* and strut edges both are of the type "there ain't anything
|
||||
* immediately on the other side"; monitor edges are different.
|
||||
* immediately on the other side"; xinerama edges are different.
|
||||
*/
|
||||
GList *ret;
|
||||
const GList *cur;
|
||||
@@ -1858,14 +1808,14 @@ meta_rectangle_find_nonintersected_monitor_edges (
|
||||
/* Initialize the return list to be empty */
|
||||
ret = NULL;
|
||||
|
||||
/* start of ret with all the edges of monitors that are adjacent to
|
||||
* another monitor.
|
||||
/* start of ret with all the edges of xineramas that are adjacent to
|
||||
* another xinerama.
|
||||
*/
|
||||
cur = monitor_rects;
|
||||
cur = xinerama_rects;
|
||||
while (cur)
|
||||
{
|
||||
MetaRectangle *cur_rect = cur->data;
|
||||
const GList *compare = monitor_rects;
|
||||
const GList *compare = xinerama_rects;
|
||||
while (compare)
|
||||
{
|
||||
MetaRectangle *compare_rect = compare->data;
|
||||
@@ -1899,15 +1849,15 @@ meta_rectangle_find_nonintersected_monitor_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (x != INT_MIN)
|
||||
{
|
||||
/* We need a left edge for the monitor on the right, and
|
||||
* a right edge for the monitor on the left. Just fill
|
||||
/* We need a left edge for the xinerama on the right, and
|
||||
* a right edge for the xinerama on the left. Just fill
|
||||
* up the edges and stick 'em on the list.
|
||||
*/
|
||||
MetaEdge *new_edge = g_new (MetaEdge, 1);
|
||||
|
||||
new_edge->rect = meta_rect (x, y, width, height);
|
||||
new_edge->side_type = side_type;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
new_edge->edge_type = META_EDGE_XINERAMA;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
@@ -1942,15 +1892,15 @@ meta_rectangle_find_nonintersected_monitor_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (y != INT_MIN)
|
||||
{
|
||||
/* We need a top edge for the monitor on the bottom, and
|
||||
* a bottom edge for the monitor on the top. Just fill
|
||||
/* We need a top edge for the xinerama on the bottom, and
|
||||
* a bottom edge for the xinerama on the top. Just fill
|
||||
* up the edges and stick 'em on the list.
|
||||
*/
|
||||
MetaEdge *new_edge = g_new (MetaEdge, 1);
|
||||
|
||||
new_edge->rect = meta_rect (x, y, width, height);
|
||||
new_edge->side_type = side_type;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
new_edge->edge_type = META_EDGE_XINERAMA;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,9 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "boxes-private.h"
|
||||
#include "constraints.h"
|
||||
#include "workspace-private.h"
|
||||
#include "place.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
@@ -95,11 +93,10 @@ typedef enum
|
||||
{
|
||||
PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
|
||||
PRIORITY_ASPECT_RATIO = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
|
||||
PRIORITY_SIZE_HINTS_INCREMENTS = 1,
|
||||
PRIORITY_MAXIMIZATION = 2,
|
||||
PRIORITY_TILING = 2,
|
||||
PRIORITY_FULLSCREEN = 2,
|
||||
PRIORITY_SIZE_HINTS_LIMITS = 3,
|
||||
PRIORITY_TITLEBAR_VISIBLE = 4,
|
||||
@@ -130,30 +127,23 @@ typedef struct
|
||||
int resize_gravity;
|
||||
FixedDirections fixed_directions;
|
||||
|
||||
/* work_area_monitor - current monitor region minus struts
|
||||
* entire_monitor - current monitor, including strut regions
|
||||
/* work_area_xinerama - current xinerama region minus struts
|
||||
* entire_xinerama - current xienrama, including strut regions
|
||||
*/
|
||||
MetaRectangle work_area_monitor;
|
||||
MetaRectangle entire_monitor;
|
||||
MetaRectangle work_area_xinerama;
|
||||
MetaRectangle entire_xinerama;
|
||||
|
||||
/* Spanning rectangles for the non-covered (by struts) region of the
|
||||
* screen and also for just the current monitor
|
||||
* screen and also for just the current xinerama
|
||||
*/
|
||||
GList *usable_screen_region;
|
||||
GList *usable_monitor_region;
|
||||
GList *usable_xinerama_region;
|
||||
} ConstraintInfo;
|
||||
static gboolean constrain_modal_dialog (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
|
||||
static gboolean constrain_maximization (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_tiling (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_fullscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
@@ -170,7 +160,7 @@ static gboolean constrain_aspect_ratio (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_to_single_monitor (MetaWindow *window,
|
||||
static gboolean constrain_to_single_xinerama (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
@@ -219,14 +209,12 @@ typedef struct {
|
||||
} Constraint;
|
||||
|
||||
static const Constraint all_constraints[] = {
|
||||
{constrain_modal_dialog, "constrain_modal_dialog"},
|
||||
{constrain_maximization, "constrain_maximization"},
|
||||
{constrain_tiling, "constrain_tiling"},
|
||||
{constrain_fullscreen, "constrain_fullscreen"},
|
||||
{constrain_size_increments, "constrain_size_increments"},
|
||||
{constrain_size_limits, "constrain_size_limits"},
|
||||
{constrain_aspect_ratio, "constrain_aspect_ratio"},
|
||||
{constrain_to_single_monitor, "constrain_to_single_monitor"},
|
||||
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
|
||||
{constrain_fully_onscreen, "constrain_fully_onscreen"},
|
||||
{constrain_titlebar_visible, "constrain_titlebar_visible"},
|
||||
{constrain_partially_onscreen, "constrain_partially_onscreen"},
|
||||
@@ -323,7 +311,7 @@ meta_window_constrain (MetaWindow *window,
|
||||
*new = info.current;
|
||||
|
||||
/* We may need to update window->require_fully_onscreen,
|
||||
* window->require_on_single_monitor, and perhaps other quantities
|
||||
* window->require_on_single_xinerama, and perhaps other quantities
|
||||
* if this was a user move or user move-and-resize operation.
|
||||
*/
|
||||
update_onscreen_requirements (window, &info);
|
||||
@@ -345,7 +333,7 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
const MetaRectangle *orig,
|
||||
MetaRectangle *new)
|
||||
{
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
MetaWorkspace *cur_workspace;
|
||||
|
||||
info->orig = *orig;
|
||||
@@ -399,15 +387,15 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
if (!info->is_user_action)
|
||||
info->fixed_directions = FIXED_DIRECTION_NONE;
|
||||
|
||||
monitor_info =
|
||||
meta_screen_get_monitor_for_rect (window->screen, &info->current);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor_info->number,
|
||||
&info->work_area_monitor);
|
||||
xinerama_info =
|
||||
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xinerama_info->number,
|
||||
&info->work_area_xinerama);
|
||||
|
||||
if (!window->fullscreen || window->fullscreen_monitors[0] == -1)
|
||||
{
|
||||
info->entire_monitor = monitor_info->rect;
|
||||
info->entire_xinerama = xinerama_info->rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -415,29 +403,28 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
long monitor;
|
||||
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
info->entire_monitor =
|
||||
window->screen->monitor_infos[monitor].rect;
|
||||
info->entire_xinerama =
|
||||
window->screen->xinerama_infos[monitor].rect;
|
||||
for (i = 1; i <= 3; i++)
|
||||
{
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
meta_rectangle_union (&info->entire_monitor,
|
||||
&window->screen->monitor_infos[monitor].rect,
|
||||
&info->entire_monitor);
|
||||
meta_rectangle_union (&info->entire_xinerama,
|
||||
&window->screen->xinerama_infos[monitor].rect,
|
||||
&info->entire_xinerama);
|
||||
}
|
||||
}
|
||||
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_screen_region =
|
||||
meta_workspace_get_onscreen_region (cur_workspace);
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
if (meta_rectangle_equal (new, &xinerama_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
@@ -461,8 +448,8 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
" is_user_action : %s\n"
|
||||
" resize_gravity : %s\n"
|
||||
" fixed_directions: %s\n"
|
||||
" work_area_monitor: %d,%d +%d,%d\n"
|
||||
" entire_monitor : %d,%d +%d,%d\n",
|
||||
" work_area_xinerama: %d,%d +%d,%d\n"
|
||||
" entire_xinerama : %d,%d +%d,%d\n",
|
||||
info->orig.x, info->orig.y, info->orig.width, info->orig.height,
|
||||
info->current.x, info->current.y,
|
||||
info->current.width, info->current.height,
|
||||
@@ -478,11 +465,11 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
(info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
|
||||
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
|
||||
"Freakin' Invalid Stupid",
|
||||
info->work_area_monitor.x, info->work_area_monitor.y,
|
||||
info->work_area_monitor.width,
|
||||
info->work_area_monitor.height,
|
||||
info->entire_monitor.x, info->entire_monitor.y,
|
||||
info->entire_monitor.width, info->entire_monitor.height);
|
||||
info->work_area_xinerama.x, info->work_area_xinerama.y,
|
||||
info->work_area_xinerama.width,
|
||||
info->work_area_xinerama.height,
|
||||
info->entire_xinerama.x, info->entire_xinerama.y,
|
||||
info->entire_xinerama.width, info->entire_xinerama.height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -506,25 +493,25 @@ place_window_if_needed(MetaWindow *window,
|
||||
{
|
||||
MetaRectangle placed_rect = info->orig;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
|
||||
meta_window_place (window, info->fgeom, info->orig.x, info->orig.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
/* placing the window may have changed the monitor. Find the
|
||||
* new monitor and update the ConstraintInfo
|
||||
/* placing the window may have changed the xinerama. Find the
|
||||
* new xinerama and update the ConstraintInfo
|
||||
*/
|
||||
monitor_info =
|
||||
meta_screen_get_monitor_for_rect (window->screen, &placed_rect);
|
||||
info->entire_monitor = monitor_info->rect;
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor_info->number,
|
||||
&info->work_area_monitor);
|
||||
xinerama_info =
|
||||
meta_screen_get_xinerama_for_rect (window->screen, &placed_rect);
|
||||
info->entire_xinerama = xinerama_info->rect;
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xinerama_info->number,
|
||||
&info->work_area_xinerama);
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
|
||||
|
||||
info->current.x = placed_rect.x;
|
||||
@@ -539,23 +526,22 @@ place_window_if_needed(MetaWindow *window,
|
||||
if (window->placed || did_placement)
|
||||
{
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
window->maximize_vertically_after_placement ||
|
||||
window->fullscreen_after_placement)
|
||||
window->maximize_vertically_after_placement)
|
||||
{
|
||||
/* define a sane saved_rect so that the user can unmaximize or
|
||||
* make unfullscreen to something reasonable.
|
||||
/* define a sane saved_rect so that the user can unmaximize to
|
||||
* something reasonable.
|
||||
*/
|
||||
if (info->current.width >= info->work_area_monitor.width)
|
||||
if (info->current.width >= info->work_area_xinerama.width)
|
||||
{
|
||||
info->current.width = .75 * info->work_area_monitor.width;
|
||||
info->current.x = info->work_area_monitor.x +
|
||||
.125 * info->work_area_monitor.width;
|
||||
info->current.width = .75 * info->work_area_xinerama.width;
|
||||
info->current.x = info->work_area_xinerama.x +
|
||||
.125 * info->work_area_xinerama.width;
|
||||
}
|
||||
if (info->current.height >= info->work_area_monitor.height)
|
||||
if (info->current.height >= info->work_area_xinerama.height)
|
||||
{
|
||||
info->current.height = .75 * info->work_area_monitor.height;
|
||||
info->current.y = info->work_area_monitor.y +
|
||||
.083 * info->work_area_monitor.height;
|
||||
info->current.height = .75 * info->work_area_xinerama.height;
|
||||
info->current.y = info->work_area_xinerama.y +
|
||||
.083 * info->work_area_xinerama.height;
|
||||
}
|
||||
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
@@ -570,15 +556,6 @@ place_window_if_needed(MetaWindow *window,
|
||||
if (window->frame && !window->fullscreen)
|
||||
meta_frame_calc_geometry (window->frame, info->fgeom);
|
||||
|
||||
if (window->fullscreen_after_placement)
|
||||
{
|
||||
window->saved_rect = info->current;
|
||||
window->fullscreen = TRUE;
|
||||
window->fullscreen_after_placement = FALSE;
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
|
||||
window->maximize_horizontally_after_placement = FALSE;
|
||||
window->maximize_vertically_after_placement = FALSE;
|
||||
}
|
||||
@@ -612,7 +589,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
return;
|
||||
|
||||
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
|
||||
* require_on_single_monitor, and require_titlebar_visible flags to
|
||||
* require_on_single_xinerama, and require_titlebar_visible flags to
|
||||
* *become false* due to user interactions (which is allowed since
|
||||
* certain constraints are ignored for user interactions regardless of
|
||||
* the setting of these flags). However, whether to make these flags
|
||||
@@ -626,7 +603,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
* problematic case but this may need to be revisited.
|
||||
*/
|
||||
|
||||
/* The require onscreen/on-single-monitor and titlebar_visible
|
||||
/* The require onscreen/on-single-xinerama and titlebar_visible
|
||||
* stuff is relative to the outer window, not the inner
|
||||
*/
|
||||
extend_by_frame (&info->current, info->fgeom);
|
||||
@@ -645,17 +622,17 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_fully_onscreen ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* window to be on a single monitor.
|
||||
* window to be on a single xinerama.
|
||||
*/
|
||||
old = window->require_on_single_monitor;
|
||||
window->require_on_single_monitor =
|
||||
meta_rectangle_contained_in_region (info->usable_monitor_region,
|
||||
old = window->require_on_single_xinerama;
|
||||
window->require_on_single_xinerama =
|
||||
meta_rectangle_contained_in_region (info->usable_xinerama_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_on_single_monitor)
|
||||
if (old ^ window->require_on_single_xinerama)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_on_single_monitor for %s toggled to %s\n",
|
||||
"require_on_single_xinerama for %s toggled to %s\n",
|
||||
window->desc,
|
||||
window->require_on_single_monitor ? "TRUE" : "FALSE");
|
||||
window->require_on_single_xinerama ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* titlebar to be visible.
|
||||
@@ -723,62 +700,11 @@ get_size_limits (const MetaWindow *window,
|
||||
|
||||
min_size->width += fw;
|
||||
min_size->height += fh;
|
||||
/* Do check to avoid overflow (e.g. max_size->width & max_size->height
|
||||
* may be set to G_MAXINT by meta_set_normal_hints()).
|
||||
*/
|
||||
if (max_size->width < (G_MAXINT - fw))
|
||||
max_size->width += fw;
|
||||
else
|
||||
max_size->width = G_MAXINT;
|
||||
if (max_size->height < (G_MAXINT - fh))
|
||||
max_size->height += fh;
|
||||
else
|
||||
max_size->height = G_MAXINT;
|
||||
max_size->width += fw;
|
||||
max_size->height += fh;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_modal_dialog (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
int x, y;
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
gboolean constraint_already_satisfied;
|
||||
|
||||
if (!meta_prefs_get_attach_modal_dialogs ())
|
||||
return TRUE;
|
||||
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
|
||||
return TRUE;
|
||||
|
||||
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
|
||||
y = 0;
|
||||
if (parent->frame)
|
||||
{
|
||||
MetaFrameGeometry fgeom;
|
||||
|
||||
x += parent->frame->rect.x;
|
||||
y += parent->frame->rect.y;
|
||||
|
||||
meta_frame_calc_geometry (parent->frame, &fgeom);
|
||||
y += fgeom.top_height;
|
||||
|
||||
y += info->fgeom->top_height;
|
||||
}
|
||||
else
|
||||
y = parent->rect.y + info->fgeom->top_height;
|
||||
|
||||
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
|
||||
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
info->current.y = y;
|
||||
info->current.x = x;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_maximization (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
@@ -795,13 +721,12 @@ constrain_maximization (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if ((!window->maximized_horizontally && !window->maximized_vertically) ||
|
||||
META_WINDOW_TILED (window))
|
||||
if (!window->maximized_horizontally && !window->maximized_vertically)
|
||||
return TRUE;
|
||||
|
||||
/* Calculate target_size = maximized size of (window + frame) */
|
||||
if (window->maximized_horizontally && window->maximized_vertically)
|
||||
target_size = info->work_area_monitor;
|
||||
target_size = info->work_area_xinerama;
|
||||
else
|
||||
{
|
||||
/* Amount of maximization possible in a single direction depends
|
||||
@@ -823,7 +748,7 @@ constrain_maximization (MetaWindow *window,
|
||||
target_size = info->current;
|
||||
extend_by_frame (&target_size, info->fgeom);
|
||||
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
||||
&info->entire_monitor,
|
||||
&info->entire_xinerama,
|
||||
direction,
|
||||
active_workspace_struts);
|
||||
}
|
||||
@@ -864,66 +789,13 @@ constrain_maximization (MetaWindow *window,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_tiling (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
MetaRectangle target_size;
|
||||
MetaRectangle min_size, max_size;
|
||||
gboolean hminbad, vminbad;
|
||||
gboolean horiz_equal, vert_equal;
|
||||
gboolean constraint_already_satisfied;
|
||||
|
||||
if (priority > PRIORITY_TILING)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if (!META_WINDOW_TILED (window))
|
||||
return TRUE;
|
||||
|
||||
/* Calculate target_size - as the tile previews need this as well, we
|
||||
* use an external function for the actual calculation
|
||||
*/
|
||||
meta_window_get_current_tile_area (window, &target_size);
|
||||
unextend_by_frame (&target_size, info->fgeom);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored as for
|
||||
* maximized windows.
|
||||
*/
|
||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width;
|
||||
vminbad = target_size.height < min_size.height;
|
||||
if (hminbad || vminbad)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
horiz_equal = target_size.x == info->current.x &&
|
||||
target_size.width == info->current.width;
|
||||
vert_equal = target_size.y == info->current.y &&
|
||||
target_size.height == info->current.height;
|
||||
constraint_already_satisfied = horiz_equal && vert_equal;
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
info->current.x = target_size.x;
|
||||
info->current.width = target_size.width;
|
||||
info->current.y = target_size.y;
|
||||
info->current.height = target_size.height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
constrain_fullscreen (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
MetaRectangle min_size, max_size, monitor;
|
||||
MetaRectangle min_size, max_size, xinerama;
|
||||
gboolean too_big, too_small, constraint_already_satisfied;
|
||||
|
||||
if (priority > PRIORITY_FULLSCREEN)
|
||||
@@ -933,22 +805,22 @@ constrain_fullscreen (MetaWindow *window,
|
||||
if (!window->fullscreen)
|
||||
return TRUE;
|
||||
|
||||
monitor = info->entire_monitor;
|
||||
xinerama = info->entire_xinerama;
|
||||
|
||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
||||
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
||||
too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama);
|
||||
if (too_big || too_small)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
constraint_already_satisfied =
|
||||
meta_rectangle_equal (&info->current, &monitor);
|
||||
meta_rectangle_equal (&info->current, &xinerama);
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
info->current = monitor;
|
||||
info->current = xinerama;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -968,7 +840,7 @@ constrain_size_increments (MetaWindow *window,
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
|
||||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
|
||||
info->action_type == ACTION_MOVE)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
@@ -1099,7 +971,7 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
constraints_are_inconsistent = minr > maxr;
|
||||
if (constraints_are_inconsistent ||
|
||||
META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
|
||||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
|
||||
info->action_type == ACTION_MOVE)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is. We
|
||||
@@ -1210,7 +1082,7 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_screen_and_monitor_relative_constraints (
|
||||
do_screen_and_xinerama_relative_constraints (
|
||||
MetaWindow *window,
|
||||
GList *region_spanning_rectangles,
|
||||
ConstraintInfo *info,
|
||||
@@ -1226,7 +1098,7 @@ do_screen_and_monitor_relative_constraints (
|
||||
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"screen/monitor constraint; region_spanning_rectangles: %s\n",
|
||||
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
|
||||
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
|
||||
spanning_region));
|
||||
}
|
||||
@@ -1284,32 +1156,32 @@ do_screen_and_monitor_relative_constraints (
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_to_single_monitor (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
constrain_to_single_xinerama (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA)
|
||||
return TRUE;
|
||||
|
||||
/* Exit early if we know the constraint won't apply--note that this constraint
|
||||
* is only meant for normal windows (e.g. we don't want docks to be shoved
|
||||
* "onscreen" by their own strut) and we can't apply it to frameless windows
|
||||
* or else users will be unable to move windows such as XMMS across monitors.
|
||||
* or else users will be unable to move windows such as XMMS across xineramas.
|
||||
*/
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
window->type == META_WINDOW_DOCK ||
|
||||
window->screen->n_monitor_infos == 1 ||
|
||||
!window->require_on_single_monitor ||
|
||||
window->screen->n_xinerama_infos == 1 ||
|
||||
!window->require_on_single_xinerama ||
|
||||
!window->frame ||
|
||||
info->is_user_action)
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_monitor_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_xinerama_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1333,10 +1205,10 @@ constrain_fully_onscreen (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1409,10 +1281,10 @@ constrain_titlebar_visible (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
-horiz_amount_offscreen,
|
||||
-horiz_amount_offscreen,
|
||||
@@ -1484,10 +1356,10 @@ constrain_partially_onscreen (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
|
||||
-horiz_amount_offscreen,
|
||||
-horiz_amount_offscreen,
|
||||
|
||||
136
src/core/core.c
136
src/core/core.c
@@ -28,7 +28,6 @@
|
||||
#include "frame-private.h"
|
||||
#include "workspace-private.h"
|
||||
#include "prefs.h"
|
||||
#include "errors.h"
|
||||
|
||||
/* Looks up the MetaWindow representing the frame of the given X window.
|
||||
* Used as a helper function by a bunch of the functions below.
|
||||
@@ -117,8 +116,65 @@ meta_core_get (Display *xdisplay,
|
||||
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
|
||||
break;
|
||||
case META_CORE_GET_FRAME_TYPE:
|
||||
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
|
||||
break;
|
||||
{
|
||||
MetaFrameType base_type = META_FRAME_TYPE_LAST;
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
case META_WINDOW_NORMAL:
|
||||
base_type = META_FRAME_TYPE_NORMAL;
|
||||
break;
|
||||
|
||||
case META_WINDOW_DIALOG:
|
||||
base_type = META_FRAME_TYPE_DIALOG;
|
||||
break;
|
||||
|
||||
case META_WINDOW_MODAL_DIALOG:
|
||||
base_type = META_FRAME_TYPE_MODAL_DIALOG;
|
||||
break;
|
||||
|
||||
case META_WINDOW_MENU:
|
||||
base_type = META_FRAME_TYPE_MENU;
|
||||
break;
|
||||
|
||||
case META_WINDOW_UTILITY:
|
||||
base_type = META_FRAME_TYPE_UTILITY;
|
||||
break;
|
||||
|
||||
case META_WINDOW_DESKTOP:
|
||||
case META_WINDOW_DOCK:
|
||||
case META_WINDOW_TOOLBAR:
|
||||
case META_WINDOW_SPLASHSCREEN:
|
||||
case META_WINDOW_DROPDOWN_MENU:
|
||||
case META_WINDOW_POPUP_MENU:
|
||||
case META_WINDOW_TOOLTIP:
|
||||
case META_WINDOW_NOTIFICATION:
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_DND:
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
/* No frame */
|
||||
base_type = META_FRAME_TYPE_LAST;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (base_type == META_FRAME_TYPE_LAST)
|
||||
{
|
||||
/* can't add border if undecorated */
|
||||
*((MetaFrameType*)answer) = META_FRAME_TYPE_LAST;
|
||||
}
|
||||
else if (window->border_only)
|
||||
{
|
||||
/* override base frame type */
|
||||
*((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((MetaFrameType*)answer) = base_type;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case META_CORE_GET_MINI_ICON:
|
||||
*((GdkPixbuf**)answer) = window->mini_icon;
|
||||
break;
|
||||
@@ -204,14 +260,15 @@ meta_core_user_raise (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lower_window_and_transients (MetaWindow *window,
|
||||
gpointer data)
|
||||
void
|
||||
meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_lower (window);
|
||||
|
||||
meta_window_foreach_transient (window, lower_window_and_transients, NULL);
|
||||
|
||||
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
|
||||
meta_prefs_get_raise_on_click ())
|
||||
{
|
||||
@@ -239,59 +296,11 @@ lower_window_and_transients (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
lower_window_and_transients (window, NULL);
|
||||
|
||||
/* Rather than try to figure that out whether we just lowered
|
||||
* the focus window, assume that's always the case. (Typically,
|
||||
* this will be invoked via keyboard action or by a mouse action;
|
||||
* in either case the window or a modal child will have been focused.) */
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
NULL,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_lower_beneath_focus_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
MetaWindow *focus_window;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = meta_display_screen_for_xwindow (display, xwindow);
|
||||
focus_window = meta_stack_get_top (screen->stack);
|
||||
|
||||
if (focus_window == NULL)
|
||||
return;
|
||||
|
||||
changes.stack_mode = Below;
|
||||
changes.sibling = focus_window->frame ? focus_window->frame->xwindow
|
||||
: focus_window->xwindow;
|
||||
|
||||
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||
xwindow,
|
||||
changes.sibling,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XConfigureWindow (xdisplay,
|
||||
xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (display);
|
||||
/* focus the default window, if needed */
|
||||
if (window->has_focus)
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
NULL,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -517,9 +526,6 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||
|
||||
switch (menu_op)
|
||||
{
|
||||
case META_MENU_OP_NONE:
|
||||
/* No keybinding for this one */
|
||||
break;
|
||||
case META_MENU_OP_DELETE:
|
||||
name = "close";
|
||||
break;
|
||||
@@ -760,7 +766,7 @@ meta_invalidate_default_icons (void)
|
||||
if (display == NULL)
|
||||
return; /* We can validly be called before the display is opened. */
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
windows = meta_display_list_windows (display);
|
||||
for (l = windows; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = (MetaWindow*)l->data;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE /* for kill() */
|
||||
#define _GNU_SOURCE
|
||||
#define _SVID_SOURCE /* for gethostname() */
|
||||
|
||||
#include <config.h>
|
||||
#include "util.h"
|
||||
@@ -31,7 +32,6 @@
|
||||
#include "workspace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@@ -55,16 +55,27 @@ delete_ping_reply_func (MetaDisplay *display,
|
||||
/* we do nothing */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
delete_window_callback (gpointer w_p)
|
||||
{
|
||||
meta_window_kill ((MetaWindow*) w_p);
|
||||
|
||||
return FALSE; /* don't do it again */
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
{
|
||||
MetaWindow *ours = (MetaWindow*) user_data;
|
||||
|
||||
ours->dialog_pid = -1;
|
||||
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
|
||||
{
|
||||
if (arg1 == 1 /* pressed "force quit" */)
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
delete_window_callback, user_data, NULL);
|
||||
|
||||
/* exit status of 1 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||
meta_window_kill (ours);
|
||||
ours->dialog_pid = -1; /* forget it anyway */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -75,7 +86,7 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
{
|
||||
MetaWindow *window = user_data;
|
||||
char *window_title;
|
||||
gchar *window_content, *tmp;
|
||||
gchar *window_content;
|
||||
GPid dialog_pid;
|
||||
|
||||
meta_topic (META_DEBUG_PING,
|
||||
@@ -90,14 +101,11 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
|
||||
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
|
||||
|
||||
/* Translators: %s is a window title */
|
||||
tmp = g_strdup_printf (_("<tt>%s</tt> is not responding."),
|
||||
window_title);
|
||||
window_content = g_strdup_printf (
|
||||
"<big><b>%s</b></big>\n\n<i>%s</i>",
|
||||
tmp,
|
||||
_("You may choose to wait a short while for it to "
|
||||
"continue or force the application to quit entirely."));
|
||||
window_content = g_strdup_printf(
|
||||
_("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
|
||||
"<i>You may choose to wait a short while for it to "
|
||||
"continue or force the application to quit entirely.</i>"),
|
||||
window_title);
|
||||
|
||||
g_free (window_title);
|
||||
|
||||
@@ -109,10 +117,13 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
NULL, NULL);
|
||||
|
||||
g_free (window_content);
|
||||
g_free (tmp);
|
||||
|
||||
window->dialog_pid = dialog_pid;
|
||||
g_child_watch_add (dialog_pid, dialog_exited, window);
|
||||
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
window);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -136,7 +147,7 @@ meta_window_delete (MetaWindow *window,
|
||||
window->desc);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
}
|
||||
meta_error_trap_pop (window->display);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
|
||||
meta_display_ping_window (window->display,
|
||||
window,
|
||||
@@ -178,29 +189,42 @@ meta_window_delete (MetaWindow *window,
|
||||
void
|
||||
meta_window_kill (MetaWindow *window)
|
||||
{
|
||||
char buf[257];
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s brutally\n",
|
||||
window->desc);
|
||||
|
||||
if (!meta_window_is_remote (window) &&
|
||||
if (window->wm_client_machine != NULL &&
|
||||
window->net_wm_pid > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s with kill()\n",
|
||||
window->desc);
|
||||
if (gethostname (buf, sizeof(buf)-1) == 0)
|
||||
{
|
||||
if (strcmp (buf, window->wm_client_machine) == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s with kill()\n",
|
||||
window->desc);
|
||||
|
||||
if (kill (window->net_wm_pid, 9) < 0)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Failed to signal %s: %s\n",
|
||||
window->desc, strerror (errno));
|
||||
if (kill (window->net_wm_pid, 9) < 0)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Failed to signal %s: %s\n",
|
||||
window->desc, strerror (errno));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Failed to get hostname: %s\n"),
|
||||
strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Disconnecting %s with XKillClient()\n",
|
||||
window->desc);
|
||||
meta_error_trap_push (window->display);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
meta_error_trap_pop (window->display);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -229,7 +253,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
||||
* mutter-dialog
|
||||
*/
|
||||
|
||||
windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
||||
windows = meta_display_list_windows (window->display);
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
|
||||
@@ -61,10 +61,6 @@ typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||
} MetaListWindowsFlags;
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
||||
@@ -83,11 +79,10 @@ struct _MetaDisplay
|
||||
|
||||
char *name;
|
||||
Display *xdisplay;
|
||||
char *hostname;
|
||||
|
||||
Window leader_window;
|
||||
Window timestamp_pinging_window;
|
||||
|
||||
|
||||
/* Pull in all the names of atoms as fields; we will intern them when the
|
||||
* class is constructed.
|
||||
*/
|
||||
@@ -151,15 +146,6 @@ struct _MetaDisplay
|
||||
|
||||
guint32 current_time;
|
||||
|
||||
/* We maintain a sequence counter, incremented for each #MetaWindow
|
||||
* created. This is exposed by meta_window_get_stable_sequence()
|
||||
* but is otherwise not used inside mutter.
|
||||
*
|
||||
* It can be useful to plugins which want to sort windows in a
|
||||
* stable fashion.
|
||||
*/
|
||||
guint32 window_sequence_counter;
|
||||
|
||||
/* Pings which we're waiting for a reply from */
|
||||
GSList *pending_pings;
|
||||
|
||||
@@ -184,16 +170,19 @@ struct _MetaDisplay
|
||||
gulong grab_mask;
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_wireframe_active : 1;
|
||||
guint grab_was_cancelled : 1; /* Only used in wireframe mode */
|
||||
guint grab_frame_action : 1;
|
||||
/* During a resize operation, the directions in which we've broken
|
||||
* out of the initial maximization state */
|
||||
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
|
||||
MetaRectangle grab_wireframe_rect;
|
||||
MetaRectangle grab_wireframe_last_xor_rect;
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
int grab_wireframe_last_display_width;
|
||||
int grab_wireframe_last_display_height;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -230,8 +219,8 @@ struct _MetaDisplay
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
|
||||
/* Monitor cache */
|
||||
unsigned int monitor_cache_invalidated : 1;
|
||||
/* Xinerama cache */
|
||||
unsigned int xinerama_cache_invalidated : 1;
|
||||
|
||||
/* Opening the display */
|
||||
unsigned int display_opening : 1;
|
||||
@@ -256,18 +245,6 @@ struct _MetaDisplay
|
||||
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
int render_event_base;
|
||||
int render_error_base;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
int composite_minor_version;
|
||||
int damage_event_base;
|
||||
int damage_error_base;
|
||||
int xfixes_event_base;
|
||||
int xfixes_error_base;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
SnDisplay *sn_display;
|
||||
@@ -280,6 +257,20 @@ struct _MetaDisplay
|
||||
int shape_event_base;
|
||||
int shape_error_base;
|
||||
#endif
|
||||
#ifdef HAVE_RENDER
|
||||
int render_event_base;
|
||||
int render_error_base;
|
||||
#endif
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
int composite_minor_version;
|
||||
int damage_event_base;
|
||||
int damage_error_base;
|
||||
int xfixes_event_base;
|
||||
int xfixes_error_base;
|
||||
#endif
|
||||
#ifdef HAVE_XSYNC
|
||||
unsigned int have_xsync : 1;
|
||||
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
|
||||
@@ -292,14 +283,24 @@ struct _MetaDisplay
|
||||
#else
|
||||
#define META_DISPLAY_HAS_SHAPE(display) FALSE
|
||||
#endif
|
||||
#ifdef HAVE_RENDER
|
||||
unsigned int have_render : 1;
|
||||
#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render)
|
||||
#else
|
||||
#define META_DISPLAY_HAS_RENDER(display) FALSE
|
||||
#endif
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
unsigned int have_composite : 1;
|
||||
unsigned int have_damage : 1;
|
||||
unsigned int have_xfixes : 1;
|
||||
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
|
||||
#define META_DISPLAY_HAS_DAMAGE(display) ((display)->have_damage)
|
||||
#define META_DISPLAY_HAS_XFIXES(display) ((display)->have_xfixes)
|
||||
#else
|
||||
#define META_DISPLAY_HAS_COMPOSITE(display) FALSE
|
||||
#define META_DISPLAY_HAS_DAMAGE(display) FALSE
|
||||
#define META_DISPLAY_HAS_XFIXES(display) FALSE
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MetaDisplayClass
|
||||
@@ -307,15 +308,22 @@ struct _MetaDisplayClass
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* Xserver time can wraparound, thus comparing two timestamps needs to take
|
||||
* this into account. Here's a little macro to help out. If no wraparound
|
||||
* has occurred, this is equivalent to
|
||||
* time1 < time2
|
||||
* Of course, the rest of the ugliness of this macro comes from accounting
|
||||
* for the fact that wraparound can occur and the fact that a timestamp of
|
||||
* 0 must be special-cased since it means older than anything else.
|
||||
*
|
||||
* Note that this is NOT an equivalent for time1 <= time2; if that's what
|
||||
* you need then you'll need to swap the order of the arguments and negate
|
||||
* the result.
|
||||
*/
|
||||
#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
|
||||
( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \
|
||||
(( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \
|
||||
)
|
||||
/**
|
||||
* XSERVER_TIME_IS_BEFORE:
|
||||
*
|
||||
* See the docs for meta_display_xserver_time_is_before().
|
||||
*/
|
||||
#define XSERVER_TIME_IS_BEFORE(time1, time2) \
|
||||
( (time1) == 0 || \
|
||||
(XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \
|
||||
@@ -354,12 +362,12 @@ void meta_display_register_x_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
void meta_display_unregister_x_window (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
/* Return whether the xwindow is a no focus window for any of the screens */
|
||||
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
void meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
GSList* meta_display_list_windows (MetaDisplay *display,
|
||||
MetaListWindowsFlags flags);
|
||||
GSList* meta_display_list_windows (MetaDisplay *display);
|
||||
GSList* meta_display_list_all_windows (MetaDisplay *display);
|
||||
|
||||
MetaDisplay* meta_display_for_x_display (Display *xdisplay);
|
||||
MetaDisplay* meta_get_display (void);
|
||||
@@ -387,8 +395,9 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
/* Next function is defined in edge-resistance.c */
|
||||
void meta_display_cleanup_edges (MetaDisplay *display);
|
||||
/* Next two functions are defined in edge-resistance.c */
|
||||
void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display);
|
||||
void meta_display_cleanup_edges (MetaDisplay *display);
|
||||
|
||||
/* make a request to ensure the event serial has changed */
|
||||
void meta_display_increment_event_serial (MetaDisplay *display);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "edge-resistance.h"
|
||||
#include "boxes-private.h"
|
||||
#include "boxes.h"
|
||||
#include "display-private.h"
|
||||
#include "workspace-private.h"
|
||||
|
||||
@@ -63,8 +63,6 @@ struct MetaEdgeResistanceData
|
||||
ResistanceDataForAnEdge bottom_data;
|
||||
};
|
||||
|
||||
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
|
||||
|
||||
/* !WARNING!: this function can return invalid indices (namely, either -1 or
|
||||
* edges->len); this is by design, but you need to remember this.
|
||||
*/
|
||||
@@ -342,12 +340,12 @@ apply_edge_resistance (MetaWindow *window,
|
||||
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
|
||||
|
||||
/* Quit if no movement was specified */
|
||||
@@ -425,8 +423,8 @@ apply_edge_resistance (MetaWindow *window,
|
||||
case META_EDGE_WINDOW:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
|
||||
break;
|
||||
case META_EDGE_MONITOR:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
|
||||
case META_EDGE_XINERAMA:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
|
||||
@@ -470,11 +468,11 @@ apply_edge_resistance (MetaWindow *window,
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
|
||||
break;
|
||||
case META_EDGE_MONITOR:
|
||||
case META_EDGE_XINERAMA:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA;
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
@@ -552,9 +550,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
gboolean modified;
|
||||
int new_left, new_right, new_top, new_bottom;
|
||||
|
||||
if (display->grab_edge_resistance_data == NULL)
|
||||
compute_resistance_and_snapping_edges (display);
|
||||
|
||||
g_assert (display->grab_edge_resistance_data != NULL);
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
|
||||
if (auto_snap)
|
||||
@@ -675,8 +671,7 @@ meta_display_cleanup_edges (MetaDisplay *display)
|
||||
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
|
||||
GHashTable *edges_to_be_freed;
|
||||
|
||||
if (edge_data == NULL) /* Not currently cached */
|
||||
return;
|
||||
g_assert (edge_data != NULL);
|
||||
|
||||
/* We first need to clean out any window edges */
|
||||
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
@@ -766,7 +761,7 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
|
||||
static void
|
||||
cache_edges (MetaDisplay *display,
|
||||
GList *window_edges,
|
||||
GList *monitor_edges,
|
||||
GList *xinerama_edges,
|
||||
GList *screen_edges)
|
||||
{
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
@@ -781,7 +776,7 @@ cache_edges (MetaDisplay *display,
|
||||
if (meta_is_verbose())
|
||||
{
|
||||
int max_edges = MAX (MAX( g_list_length (window_edges),
|
||||
g_list_length (monitor_edges)),
|
||||
g_list_length (xinerama_edges)),
|
||||
g_list_length (screen_edges));
|
||||
char big_buffer[(EDGE_LENGTH+2)*max_edges];
|
||||
|
||||
@@ -789,9 +784,9 @@ cache_edges (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"Window edges for resistance : %s\n", big_buffer);
|
||||
|
||||
meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
|
||||
meta_rectangle_edge_list_to_string (xinerama_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"Monitor edges for resistance: %s\n", big_buffer);
|
||||
"Xinerama edges for resistance: %s\n", big_buffer);
|
||||
|
||||
meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
@@ -812,7 +807,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = monitor_edges;
|
||||
tmp = xinerama_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@@ -849,7 +844,7 @@ cache_edges (MetaDisplay *display,
|
||||
* 2nd: Allocate the edges
|
||||
*/
|
||||
g_assert (display->grab_edge_resistance_data == NULL);
|
||||
display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1);
|
||||
display->grab_edge_resistance_data = g_new (MetaEdgeResistanceData, 1);
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
edge_data->left_edges = g_array_sized_new (FALSE,
|
||||
FALSE,
|
||||
@@ -880,7 +875,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = monitor_edges;
|
||||
tmp = xinerama_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@@ -943,8 +938,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
edge_data->bottom_data.keyboard_buildup = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
void
|
||||
meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
{
|
||||
GList *stacked_windows;
|
||||
GList *cur_window_iter;
|
||||
@@ -957,11 +952,6 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
*/
|
||||
GSList *rem_windows, *rem_win_stacking;
|
||||
|
||||
g_assert (display->grab_window != NULL);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Computing edges to resist-movement or snap-to for %s.\n",
|
||||
display->grab_window->desc);
|
||||
|
||||
/*
|
||||
* 1st: Get the list of relevant windows, from bottom to top
|
||||
*/
|
||||
@@ -1120,12 +1110,12 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
|
||||
/*
|
||||
* 5th: Cache the combination of these edges with the onscreen and
|
||||
* monitor edges in an array for quick access. Free the edges since
|
||||
* xinerama edges in an array for quick access. Free the edges since
|
||||
* they've been cached elsewhere.
|
||||
*/
|
||||
cache_edges (display,
|
||||
edges,
|
||||
display->grab_screen->active_workspace->monitor_edges,
|
||||
display->grab_screen->active_workspace->xinerama_edges,
|
||||
display->grab_screen->active_workspace->screen_edges);
|
||||
g_list_free (edges);
|
||||
|
||||
@@ -1151,8 +1141,17 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
MetaRectangle old_outer, proposed_outer, new_outer;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
|
||||
if (window == window->display->grab_window &&
|
||||
window->display->grab_wireframe_active)
|
||||
{
|
||||
meta_window_get_xor_rect (window,
|
||||
&window->display->grab_wireframe_rect,
|
||||
&old_outer);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
}
|
||||
proposed_outer = old_outer;
|
||||
proposed_outer.x += (*new_x - old_x);
|
||||
proposed_outer.y += (*new_y - old_y);
|
||||
@@ -1237,7 +1236,17 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int proposed_outer_width, proposed_outer_height;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
if (window == window->display->grab_window &&
|
||||
window->display->grab_wireframe_active)
|
||||
{
|
||||
meta_window_get_xor_rect (window,
|
||||
&window->display->grab_wireframe_rect,
|
||||
&old_outer);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
}
|
||||
proposed_outer_width = old_outer.width + (*new_width - old_width);
|
||||
proposed_outer_height = old_outer.height + (*new_height - old_height);
|
||||
meta_rectangle_resize_with_gravity (&old_outer,
|
||||
|
||||
735
src/core/effects.c
Normal file
735
src/core/effects.c
Normal file
@@ -0,0 +1,735 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file effects.c "Special effects" other than compositor effects.
|
||||
*
|
||||
* Before we had a serious compositor, we supported swooping
|
||||
* rectangles for minimising and so on. These are still supported
|
||||
* today, even when the compositor is enabled. The file contains two
|
||||
* parts:
|
||||
*
|
||||
* 1) A set of functions, each of which implements a special effect.
|
||||
* (Only the minimize function does anything interesting; we should
|
||||
* probably get rid of the rest.)
|
||||
*
|
||||
* 2) A set of functions for moving a highlighted wireframe box around
|
||||
* the screen, optionally with height and width shown in the middle.
|
||||
* This is used for moving and resizing when reduced_resources is set.
|
||||
*
|
||||
* There was formerly a system which allowed callers to drop in their
|
||||
* own handlers for various things; it was never used (people who want
|
||||
* their own handlers can just modify this file, after all) and it added
|
||||
* a good deal of extra complexity, so it has been removed. If you want it,
|
||||
* it can be found in svn r3769.
|
||||
*
|
||||
* Once upon a time there were three different ways of drawing the box
|
||||
* animation: window wireframe, window opaque, and root. People who had
|
||||
* the shape extension theoretically had the choice of all three, and
|
||||
* people who didn't weren't given the choice of the wireframe option.
|
||||
* In practice, though, the opaque animation was never perfect, so it came
|
||||
* down to the wireframe option for those who had the extension and
|
||||
* the root option for those who didn't; there was actually no way of choosing
|
||||
* any other option anyway. Work on the opaque animation stopped in 2002;
|
||||
* anyone who wants something like that these days will be using the
|
||||
* compositor anyway.
|
||||
*
|
||||
* In svn r3769 this was made explicit.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "effects.h"
|
||||
#include "display-private.h"
|
||||
#include "ui.h"
|
||||
#include "window-private.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
|
||||
#define META_MINIMIZE_ANIMATION_LENGTH 0.25
|
||||
#define META_SHADE_ANIMATION_LENGTH 0.2
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct MetaEffect MetaEffect;
|
||||
typedef struct MetaEffectPriv MetaEffectPriv;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
double millisecs_duration;
|
||||
GTimeVal start_time;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
/** For wireframe window */
|
||||
Window wireframe_xwindow;
|
||||
#else
|
||||
/** Rectangle to erase */
|
||||
MetaRectangle last_rect;
|
||||
|
||||
/** First time we've plotted anything in this animation? */
|
||||
gboolean first_time;
|
||||
|
||||
/** For wireframe drawn on root window */
|
||||
GC gc;
|
||||
#endif
|
||||
|
||||
MetaRectangle start_rect;
|
||||
MetaRectangle end_rect;
|
||||
|
||||
} BoxAnimationContext;
|
||||
|
||||
/**
|
||||
* Information we need to know during a maximise or minimise effect.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** This is the normal-size window. */
|
||||
MetaRectangle window_rect;
|
||||
/** This is the size of the window when it's an icon. */
|
||||
MetaRectangle icon_rect;
|
||||
} MetaMinimizeEffect, MetaUnminimizeEffect;
|
||||
|
||||
struct MetaEffectPriv
|
||||
{
|
||||
MetaEffectFinished finished;
|
||||
gpointer finished_data;
|
||||
};
|
||||
|
||||
struct MetaEffect
|
||||
{
|
||||
/** The window the effect is applied to. */
|
||||
MetaWindow *window;
|
||||
/** Which effect is happening here. */
|
||||
MetaEffectType type;
|
||||
/** The effect handler can hang data here. */
|
||||
gpointer info;
|
||||
|
||||
union
|
||||
{
|
||||
MetaMinimizeEffect minimize;
|
||||
/* ... and theoretically anything else */
|
||||
} u;
|
||||
|
||||
MetaEffectPriv *priv;
|
||||
};
|
||||
|
||||
static void run_default_effect_handler (MetaEffect *effect);
|
||||
static void run_handler (MetaEffect *effect);
|
||||
static void effect_free (MetaEffect *effect);
|
||||
|
||||
static MetaEffect *
|
||||
create_effect (MetaEffectType type,
|
||||
MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer finished_data);
|
||||
|
||||
static void
|
||||
draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration);
|
||||
|
||||
/**
|
||||
* Creates an effect.
|
||||
*
|
||||
*/
|
||||
static MetaEffect*
|
||||
create_effect (MetaEffectType type,
|
||||
MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer finished_data)
|
||||
{
|
||||
MetaEffect *effect = g_new (MetaEffect, 1);
|
||||
|
||||
effect->type = type;
|
||||
effect->window = window;
|
||||
effect->priv = g_new (MetaEffectPriv, 1);
|
||||
effect->priv->finished = finished;
|
||||
effect->priv->finished_data = finished_data;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys an effect. If the effect has a "finished" hook, it will be
|
||||
* called before cleanup.
|
||||
*
|
||||
* \param effect The effect.
|
||||
*/
|
||||
static void
|
||||
effect_free (MetaEffect *effect)
|
||||
{
|
||||
if (effect->priv->finished)
|
||||
effect->priv->finished (effect->priv->finished_data);
|
||||
|
||||
g_free (effect->priv);
|
||||
g_free (effect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effect_run_focus (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
|
||||
effect = create_effect (META_EFFECT_FOCUS, window, finished, data);
|
||||
|
||||
run_handler (effect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effect_run_minimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
g_return_if_fail (icon_rect != NULL);
|
||||
|
||||
effect = create_effect (META_EFFECT_MINIMIZE, window, finished, data);
|
||||
|
||||
effect->u.minimize.window_rect = *window_rect;
|
||||
effect->u.minimize.icon_rect = *icon_rect;
|
||||
|
||||
run_handler (effect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effect_run_unminimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
g_return_if_fail (icon_rect != NULL);
|
||||
|
||||
effect = create_effect (META_EFFECT_UNMINIMIZE, window, finished, data);
|
||||
|
||||
effect->u.minimize.window_rect = *window_rect;
|
||||
effect->u.minimize.icon_rect = *icon_rect;
|
||||
|
||||
run_handler (effect);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effect_run_close (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
g_return_if_fail (window != NULL);
|
||||
|
||||
effect = create_effect (META_EFFECT_CLOSE, window,
|
||||
finished, data);
|
||||
|
||||
run_handler (effect);
|
||||
}
|
||||
|
||||
|
||||
/* old ugly minimization effect */
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
update_wireframe_window (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
const MetaRectangle *rect)
|
||||
{
|
||||
XMoveResizeWindow (display->xdisplay,
|
||||
xwindow,
|
||||
rect->x, rect->y,
|
||||
rect->width, rect->height);
|
||||
|
||||
#define OUTLINE_WIDTH 3
|
||||
|
||||
if (rect->width > OUTLINE_WIDTH * 2 &&
|
||||
rect->height > OUTLINE_WIDTH * 2)
|
||||
{
|
||||
XRectangle xrect;
|
||||
Region inner_xregion;
|
||||
Region outer_xregion;
|
||||
|
||||
inner_xregion = XCreateRegion ();
|
||||
outer_xregion = XCreateRegion ();
|
||||
|
||||
xrect.x = 0;
|
||||
xrect.y = 0;
|
||||
xrect.width = rect->width;
|
||||
xrect.height = rect->height;
|
||||
|
||||
XUnionRectWithRegion (&xrect, outer_xregion, outer_xregion);
|
||||
|
||||
xrect.x += OUTLINE_WIDTH;
|
||||
xrect.y += OUTLINE_WIDTH;
|
||||
xrect.width -= OUTLINE_WIDTH * 2;
|
||||
xrect.height -= OUTLINE_WIDTH * 2;
|
||||
|
||||
XUnionRectWithRegion (&xrect, inner_xregion, inner_xregion);
|
||||
|
||||
XSubtractRegion (outer_xregion, inner_xregion, outer_xregion);
|
||||
|
||||
XShapeCombineRegion (display->xdisplay, xwindow,
|
||||
ShapeBounding, 0, 0, outer_xregion, ShapeSet);
|
||||
|
||||
XDestroyRegion (outer_xregion);
|
||||
XDestroyRegion (inner_xregion);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unset the shape */
|
||||
XShapeCombineMask (display->xdisplay, xwindow,
|
||||
ShapeBounding, 0, 0, None, ShapeSet);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A hack to force the X server to synchronize with the
|
||||
* graphics hardware.
|
||||
*/
|
||||
static void
|
||||
graphics_sync (BoxAnimationContext *context)
|
||||
{
|
||||
XImage *image;
|
||||
|
||||
image = XGetImage (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
0, 0, 1, 1,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
XDestroyImage (image);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
||||
{
|
||||
double elapsed;
|
||||
GTimeVal current_time;
|
||||
MetaRectangle draw_rect;
|
||||
double fraction;
|
||||
|
||||
#ifndef HAVE_SHAPE
|
||||
if (!context->first_time)
|
||||
{
|
||||
/* Restore the previously drawn background */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
context->last_rect.x, context->last_rect.y,
|
||||
context->last_rect.width, context->last_rect.height);
|
||||
}
|
||||
else
|
||||
context->first_time = FALSE;
|
||||
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
g_get_current_time (¤t_time);
|
||||
|
||||
/* We use milliseconds for all times */
|
||||
elapsed =
|
||||
((((double)current_time.tv_sec - context->start_time.tv_sec) * G_USEC_PER_SEC +
|
||||
(current_time.tv_usec - context->start_time.tv_usec))) / 1000.0;
|
||||
|
||||
if (elapsed < 0)
|
||||
{
|
||||
/* Probably the system clock was set backwards? */
|
||||
meta_warning ("System clock seemed to go backwards?\n");
|
||||
elapsed = G_MAXDOUBLE; /* definitely done. */
|
||||
}
|
||||
|
||||
if (elapsed > context->millisecs_duration)
|
||||
{
|
||||
/* All done */
|
||||
#ifdef HAVE_SHAPE
|
||||
XDestroyWindow (context->screen->display->xdisplay,
|
||||
context->wireframe_xwindow);
|
||||
#else
|
||||
meta_display_ungrab (context->screen->display);
|
||||
meta_ui_pop_delay_exposes (context->screen->ui);
|
||||
XFreeGC (context->screen->display->xdisplay,
|
||||
context->gc);
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
graphics_sync (context);
|
||||
|
||||
g_free (context);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (context->millisecs_duration > 0.0);
|
||||
fraction = elapsed / context->millisecs_duration;
|
||||
|
||||
draw_rect = context->start_rect;
|
||||
|
||||
/* Now add a delta proportional to elapsed time. */
|
||||
draw_rect.x += (context->end_rect.x - context->start_rect.x) * fraction;
|
||||
draw_rect.y += (context->end_rect.y - context->start_rect.y) * fraction;
|
||||
draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction;
|
||||
draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction;
|
||||
|
||||
/* don't confuse X or gdk-pixbuf with bogus rectangles */
|
||||
if (draw_rect.width < 1)
|
||||
draw_rect.width = 1;
|
||||
if (draw_rect.height < 1)
|
||||
draw_rect.height = 1;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
update_wireframe_window (context->screen->display,
|
||||
context->wireframe_xwindow,
|
||||
&draw_rect);
|
||||
#else
|
||||
context->last_rect = draw_rect;
|
||||
|
||||
/* Draw the rectangle */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
draw_rect.x, draw_rect.y,
|
||||
draw_rect.width, draw_rect.height);
|
||||
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
/* kick changes onto the server */
|
||||
graphics_sync (context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration)
|
||||
{
|
||||
BoxAnimationContext *context;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
XSetWindowAttributes attrs;
|
||||
#else
|
||||
XGCValues gc_values;
|
||||
#endif
|
||||
|
||||
g_return_if_fail (seconds_duration > 0.0);
|
||||
|
||||
if (g_getenv ("MUTTER_DEBUG_EFFECTS"))
|
||||
seconds_duration *= 10; /* slow things down */
|
||||
|
||||
/* Create the animation context */
|
||||
context = g_new0 (BoxAnimationContext, 1);
|
||||
|
||||
context->screen = screen;
|
||||
|
||||
context->millisecs_duration = seconds_duration * 1000.0;
|
||||
|
||||
context->start_rect = *initial_rect;
|
||||
context->end_rect = *destination_rect;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
|
||||
attrs.override_redirect = True;
|
||||
attrs.background_pixel = BlackPixel (screen->display->xdisplay,
|
||||
screen->number);
|
||||
|
||||
context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
initial_rect->x,
|
||||
initial_rect->y,
|
||||
initial_rect->width,
|
||||
initial_rect->height,
|
||||
0,
|
||||
CopyFromParent,
|
||||
CopyFromParent,
|
||||
(Visual *)CopyFromParent,
|
||||
CWOverrideRedirect | CWBackPixel,
|
||||
&attrs);
|
||||
|
||||
update_wireframe_window (screen->display,
|
||||
context->wireframe_xwindow,
|
||||
initial_rect);
|
||||
|
||||
XMapWindow (screen->display->xdisplay,
|
||||
context->wireframe_xwindow);
|
||||
|
||||
#else /* !HAVE_SHAPE */
|
||||
|
||||
context->first_time = TRUE;
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
gc_values.function = GXinvert;
|
||||
|
||||
context->gc = XCreateGC (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
GCSubwindowMode | GCFunction,
|
||||
&gc_values);
|
||||
|
||||
/* Grab the X server to avoid screen dirt */
|
||||
meta_display_grab (context->screen->display);
|
||||
meta_ui_push_delay_exposes (context->screen->ui);
|
||||
#endif
|
||||
|
||||
/* Do this only after we get the pixbuf from the server,
|
||||
* so that the animation doesn't get truncated.
|
||||
*/
|
||||
g_get_current_time (&context->start_time);
|
||||
|
||||
/* Add the timeout - a short one, could even use an idle,
|
||||
* but this is maybe more CPU-friendly.
|
||||
*/
|
||||
g_timeout_add (15,
|
||||
(GSourceFunc)effects_draw_box_animation_timeout,
|
||||
context);
|
||||
|
||||
/* kick changes onto the server */
|
||||
XFlush (context->screen->display->xdisplay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effects_begin_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *rect,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
/* Grab the X server to avoid screen dirt */
|
||||
meta_display_grab (screen->display);
|
||||
meta_ui_push_delay_exposes (screen->ui);
|
||||
|
||||
meta_effects_update_wireframe (screen,
|
||||
NULL, -1, -1,
|
||||
rect, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_xor_rect (MetaScreen *screen,
|
||||
const MetaRectangle *rect,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
/* The lines in the center can't overlap the rectangle or each
|
||||
* other, or the XOR gets reversed. So we have to draw things
|
||||
* a bit oddly.
|
||||
*/
|
||||
XSegment segments[8];
|
||||
MetaRectangle shrunk_rect;
|
||||
int i;
|
||||
|
||||
#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH
|
||||
|
||||
/* We don't want the wireframe going outside the window area.
|
||||
* It makes it harder for the user to position windows and it exposes other
|
||||
* annoying bugs.
|
||||
*/
|
||||
shrunk_rect = *rect;
|
||||
|
||||
shrunk_rect.x += LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
||||
shrunk_rect.y += LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
||||
shrunk_rect.width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
|
||||
shrunk_rect.height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
|
||||
|
||||
XDrawRectangle (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
screen->root_xor_gc,
|
||||
shrunk_rect.x, shrunk_rect.y,
|
||||
shrunk_rect.width, shrunk_rect.height);
|
||||
|
||||
/* Don't put lines inside small rectangles where they won't fit */
|
||||
if (shrunk_rect.width < (LINE_WIDTH * 4) ||
|
||||
shrunk_rect.height < (LINE_WIDTH * 4))
|
||||
return;
|
||||
|
||||
if ((width >= 0) && (height >= 0))
|
||||
{
|
||||
XGCValues gc_values = { 0 };
|
||||
|
||||
if (XGetGCValues (screen->display->xdisplay,
|
||||
screen->root_xor_gc,
|
||||
GCFont, &gc_values))
|
||||
{
|
||||
char *text;
|
||||
int text_length;
|
||||
|
||||
XFontStruct *font_struct;
|
||||
int text_width, text_height;
|
||||
int box_x, box_y;
|
||||
int box_width, box_height;
|
||||
|
||||
font_struct = XQueryFont (screen->display->xdisplay,
|
||||
gc_values.font);
|
||||
|
||||
if (font_struct != NULL)
|
||||
{
|
||||
text = g_strdup_printf ("%d x %d", width, height);
|
||||
text_length = strlen (text);
|
||||
|
||||
text_width = text_length * font_struct->max_bounds.width;
|
||||
text_height = font_struct->max_bounds.descent +
|
||||
font_struct->max_bounds.ascent;
|
||||
|
||||
box_width = text_width + 2 * LINE_WIDTH;
|
||||
box_height = text_height + 2 * LINE_WIDTH;
|
||||
|
||||
|
||||
box_x = shrunk_rect.x + (shrunk_rect.width - box_width) / 2;
|
||||
box_y = shrunk_rect.y + (shrunk_rect.height - box_height) / 2;
|
||||
|
||||
if ((box_width < shrunk_rect.width) &&
|
||||
(box_height < shrunk_rect.height))
|
||||
{
|
||||
XFillRectangle (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
screen->root_xor_gc,
|
||||
box_x, box_y,
|
||||
box_width, box_height);
|
||||
XDrawString (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
screen->root_xor_gc,
|
||||
box_x + LINE_WIDTH,
|
||||
box_y + LINE_WIDTH + font_struct->max_bounds.ascent,
|
||||
text, text_length);
|
||||
}
|
||||
|
||||
g_free (text);
|
||||
|
||||
XFreeFontInfo (NULL, font_struct, 1);
|
||||
|
||||
if ((box_width + LINE_WIDTH) >= (shrunk_rect.width / 3))
|
||||
return;
|
||||
|
||||
if ((box_height + LINE_WIDTH) >= (shrunk_rect.height / 3))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Two vertical lines at 1/3 and 2/3 */
|
||||
segments[0].x1 = shrunk_rect.x + shrunk_rect.width / 3;
|
||||
segments[0].y1 = shrunk_rect.y + LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
||||
segments[0].x2 = segments[0].x1;
|
||||
segments[0].y2 = shrunk_rect.y + shrunk_rect.height - LINE_WIDTH / 2;
|
||||
|
||||
segments[1] = segments[0];
|
||||
segments[1].x1 = shrunk_rect.x + (shrunk_rect.width / 3) * 2;
|
||||
segments[1].x2 = segments[1].x1;
|
||||
|
||||
/* Now make two horizontal lines at 1/3 and 2/3, but not
|
||||
* overlapping the verticals
|
||||
*/
|
||||
|
||||
segments[2].x1 = shrunk_rect.x + LINE_WIDTH / 2 + LINE_WIDTH % 2;
|
||||
segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2;
|
||||
segments[2].y1 = shrunk_rect.y + shrunk_rect.height / 3;
|
||||
segments[2].y2 = segments[2].y1;
|
||||
|
||||
segments[3] = segments[2];
|
||||
segments[3].x1 = segments[2].x2 + LINE_WIDTH;
|
||||
segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2;
|
||||
|
||||
segments[4] = segments[3];
|
||||
segments[4].x1 = segments[3].x2 + LINE_WIDTH;
|
||||
segments[4].x2 = shrunk_rect.x + shrunk_rect.width - LINE_WIDTH / 2;
|
||||
|
||||
/* Second horizontal line is just like the first, but
|
||||
* shifted down
|
||||
*/
|
||||
i = 5;
|
||||
while (i < 8)
|
||||
{
|
||||
segments[i] = segments[i - 3];
|
||||
segments[i].y1 = shrunk_rect.y + (shrunk_rect.height / 3) * 2;
|
||||
segments[i].y2 = segments[i].y1;
|
||||
++i;
|
||||
}
|
||||
|
||||
XDrawSegments (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
screen->root_xor_gc,
|
||||
segments,
|
||||
G_N_ELEMENTS (segments));
|
||||
}
|
||||
|
||||
void
|
||||
meta_effects_update_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int old_width,
|
||||
int old_height,
|
||||
const MetaRectangle *new_rect,
|
||||
int new_width,
|
||||
int new_height)
|
||||
{
|
||||
if (old_rect)
|
||||
draw_xor_rect (screen, old_rect, old_width, old_height);
|
||||
|
||||
if (new_rect)
|
||||
draw_xor_rect (screen, new_rect, new_width, new_height);
|
||||
|
||||
XFlush (screen->display->xdisplay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_effects_end_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int old_width,
|
||||
int old_height)
|
||||
{
|
||||
meta_effects_update_wireframe (screen,
|
||||
old_rect, old_width, old_height,
|
||||
NULL, -1, -1);
|
||||
|
||||
meta_display_ungrab (screen->display);
|
||||
meta_ui_pop_delay_exposes (screen->ui);
|
||||
}
|
||||
|
||||
static void
|
||||
run_default_effect_handler (MetaEffect *effect)
|
||||
{
|
||||
switch (effect->type)
|
||||
{
|
||||
case META_EFFECT_MINIMIZE:
|
||||
draw_box_animation (effect->window->screen,
|
||||
&(effect->u.minimize.window_rect),
|
||||
&(effect->u.minimize.icon_rect),
|
||||
META_MINIMIZE_ANIMATION_LENGTH);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
run_handler (MetaEffect *effect)
|
||||
{
|
||||
if (meta_prefs_get_gnome_animations ())
|
||||
run_default_effect_handler (effect);
|
||||
|
||||
effect_free (effect);
|
||||
}
|
||||
170
src/core/effects.h
Normal file
170
src/core/effects.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file effects.h "Special effects" other than compositor effects.
|
||||
*
|
||||
* Before we had a serious compositor, we supported swooping
|
||||
* rectangles for minimising and so on. These are still supported
|
||||
* today, even when the compositor is enabled. The file contains two
|
||||
* parts:
|
||||
*
|
||||
* 1) A set of functions, each of which implements a special effect.
|
||||
* (Only the minimize function does anything interesting; we should
|
||||
* probably get rid of the rest.)
|
||||
*
|
||||
* 2) A set of functions for moving a highlighted wireframe box around
|
||||
* the screen, optionally with height and width shown in the middle.
|
||||
* This is used for moving and resizing when reduced_resources is set.
|
||||
*
|
||||
* There was formerly a system which allowed callers to drop in their
|
||||
* own handlers for various things; it was never used (people who want
|
||||
* their own handlers can just modify this file, after all) and it added
|
||||
* a good deal of extra complexity, so it has been removed. If you want it,
|
||||
* it can be found in svn r3769.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_EFFECTS_H
|
||||
#define META_EFFECTS_H
|
||||
|
||||
#include "util.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_EFFECT_MINIMIZE,
|
||||
META_EFFECT_UNMINIMIZE,
|
||||
META_EFFECT_FOCUS,
|
||||
META_EFFECT_CLOSE,
|
||||
META_NUM_EFFECTS
|
||||
} MetaEffectType;
|
||||
|
||||
/**
|
||||
* A callback which will be called when the effect has finished.
|
||||
*/
|
||||
typedef void (* MetaEffectFinished) (gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the minimize effect.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param window_rect Its current state
|
||||
* \param target Where it should end up
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_minimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *target,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the unminimize effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param icon_rect Its current state
|
||||
* \param window_rect Where it should end up
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_unminimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the close effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_close (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the focus effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_focus (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Grabs the server and paints a wireframe rectangle on the screen.
|
||||
* Since this involves starting a grab, please be considerate of other
|
||||
* users and don't keep the grab for long. You may move the wireframe
|
||||
* around using meta_effects_update_wireframe() and remove it, and undo
|
||||
* the grab, using meta_effects_end_wireframe().
|
||||
*
|
||||
* \param screen The screen to draw the rectangle on.
|
||||
* \param rect The size of the rectangle to draw.
|
||||
* \param width The width to display in the middle (or 0 not to)
|
||||
* \param height The width to display in the middle (or 0 not to)
|
||||
*/
|
||||
void meta_effects_begin_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *rect,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
* Moves a wireframe rectangle around after its creation by
|
||||
* meta_effects_begin_wireframe(). (Perhaps we ought to remember the old
|
||||
* positions and not require people to pass them in?)
|
||||
*
|
||||
* \param old_rect Where the rectangle is now
|
||||
* \param old_width The width that was displayed on it (or 0 if there wasn't)
|
||||
* \param old_height The height that was displayed on it (or 0 if there wasn't)
|
||||
* \param new_rect Where the rectangle is going
|
||||
* \param new_width The width that will be displayed on it (or 0 not to)
|
||||
* \param new_height The height that will be displayed on it (or 0 not to)
|
||||
*/
|
||||
void meta_effects_update_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int old_width,
|
||||
int old_height,
|
||||
const MetaRectangle *new_rect,
|
||||
int new_width,
|
||||
int new_height);
|
||||
|
||||
/**
|
||||
* Removes a wireframe rectangle from the screen and ends the grab started by
|
||||
* meta_effects_begin_wireframe().
|
||||
*
|
||||
* \param old_rect Where the rectangle is now
|
||||
* \param old_width The width that was displayed on it (or 0 if there wasn't)
|
||||
* \param old_height The height that was displayed on it (or 0 if there wasn't)
|
||||
*/
|
||||
void meta_effects_end_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
#endif /* META_EFFECTS_H */
|
||||
@@ -29,38 +29,260 @@
|
||||
#include <stdlib.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
|
||||
* has some neat features (like knowing automatically if a sync is needed or not
|
||||
* and handling errors asynchronously when the error code isn't needed immediately),
|
||||
* but it's basically incompatible with the hacks we played with GTK+-2.0 to
|
||||
* use a custom error handler along with gdk_error_trap_push().
|
||||
*
|
||||
* Since the main point of our custom error trap was to get the error logged
|
||||
* to the right place, with GTK+-3.0 we simply omit our own error handler and
|
||||
* use the GTK+ handling straight-up.
|
||||
* (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
|
||||
*/
|
||||
static int x_error_handler (Display *display,
|
||||
XErrorEvent *error);
|
||||
static int x_io_error_handler (Display *display);
|
||||
|
||||
void
|
||||
meta_errors_init (void)
|
||||
{
|
||||
XSetErrorHandler (x_error_handler);
|
||||
XSetIOErrorHandler (x_io_error_handler);
|
||||
}
|
||||
|
||||
typedef struct ForeignDisplay ForeignDisplay;
|
||||
|
||||
struct ForeignDisplay
|
||||
{
|
||||
Display *dpy;
|
||||
ErrorHandler handler;
|
||||
gpointer data;
|
||||
ForeignDisplay *next;
|
||||
};
|
||||
|
||||
static ForeignDisplay *foreign_displays;
|
||||
|
||||
void
|
||||
meta_errors_register_foreign_display (Display *foreign_dpy,
|
||||
ErrorHandler handler,
|
||||
gpointer data)
|
||||
{
|
||||
ForeignDisplay *info = g_new0 (ForeignDisplay, 1);
|
||||
info->dpy = foreign_dpy;
|
||||
info->handler = handler;
|
||||
info->data = data;
|
||||
info->next = foreign_displays;
|
||||
foreign_displays = info;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_error_trap_push_internal (MetaDisplay *display,
|
||||
gboolean need_sync)
|
||||
{
|
||||
/* GDK resets the error handler on each push */
|
||||
int (* old_error_handler) (Display *,
|
||||
XErrorEvent *);
|
||||
|
||||
if (need_sync)
|
||||
{
|
||||
XSync (display->xdisplay, False);
|
||||
}
|
||||
|
||||
gdk_error_trap_push ();
|
||||
|
||||
/* old_error_handler will just be equal to x_error_handler
|
||||
* for nested traps
|
||||
*/
|
||||
old_error_handler = XSetErrorHandler (x_error_handler);
|
||||
|
||||
/* Replace GDK handler, but save it so we can chain up */
|
||||
if (display->error_trap_handler == NULL)
|
||||
{
|
||||
g_assert (display->error_traps == 0);
|
||||
display->error_trap_handler = old_error_handler;
|
||||
g_assert (display->error_trap_handler != x_error_handler);
|
||||
}
|
||||
|
||||
display->error_traps += 1;
|
||||
|
||||
meta_topic (META_DEBUG_ERRORS, "%d traps remain\n", display->error_traps);
|
||||
}
|
||||
|
||||
static int
|
||||
meta_error_trap_pop_internal (MetaDisplay *display,
|
||||
gboolean need_sync)
|
||||
{
|
||||
int result;
|
||||
|
||||
g_assert (display->error_traps > 0);
|
||||
|
||||
if (need_sync)
|
||||
{
|
||||
XSync (display->xdisplay, False);
|
||||
}
|
||||
|
||||
result = gdk_error_trap_pop ();
|
||||
|
||||
display->error_traps -= 1;
|
||||
|
||||
if (display->error_traps == 0)
|
||||
{
|
||||
/* check that GDK put our handler back; this
|
||||
* assumes that there are no pending GDK traps from GDK itself
|
||||
*/
|
||||
|
||||
int (* restored_error_handler) (Display *,
|
||||
XErrorEvent *);
|
||||
|
||||
restored_error_handler = XSetErrorHandler (x_error_handler);
|
||||
|
||||
/* remove this */
|
||||
display->error_trap_handler = NULL;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_ERRORS, "%d traps\n", display->error_traps);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_push (MetaDisplay *display)
|
||||
{
|
||||
gdk_error_trap_push ();
|
||||
meta_error_trap_push_internal (display, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_pop (MetaDisplay *display)
|
||||
meta_error_trap_pop (MetaDisplay *display,
|
||||
gboolean last_request_was_roundtrip)
|
||||
{
|
||||
gdk_error_trap_pop_ignored ();
|
||||
gboolean need_sync;
|
||||
|
||||
/* we only have to sync when popping the outermost trap */
|
||||
need_sync = (display->error_traps == 1 && !last_request_was_roundtrip);
|
||||
|
||||
if (need_sync)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n",
|
||||
display->error_traps, last_request_was_roundtrip);
|
||||
|
||||
display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip;
|
||||
|
||||
meta_error_trap_pop_internal (display, need_sync);
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_push_with_return (MetaDisplay *display)
|
||||
{
|
||||
gdk_error_trap_push ();
|
||||
gboolean need_sync;
|
||||
|
||||
/* We don't sync on push_with_return if there are no traps
|
||||
* currently, because we assume that any errors were either covered
|
||||
* by a previous pop, or were fatal.
|
||||
*
|
||||
* More generally, we don't sync if we were synchronized last time
|
||||
* we popped. This is known to be the case if there are no traps,
|
||||
* but we also keep a flag so we know whether it's the case otherwise.
|
||||
*/
|
||||
|
||||
if (!display->error_trap_synced_at_last_pop)
|
||||
need_sync = TRUE;
|
||||
else
|
||||
need_sync = FALSE;
|
||||
|
||||
if (need_sync)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_push_with_return, traps = %d\n",
|
||||
display->error_traps);
|
||||
|
||||
meta_error_trap_push_internal (display, FALSE);
|
||||
}
|
||||
|
||||
int
|
||||
meta_error_trap_pop_with_return (MetaDisplay *display)
|
||||
meta_error_trap_pop_with_return (MetaDisplay *display,
|
||||
gboolean last_request_was_roundtrip)
|
||||
{
|
||||
return gdk_error_trap_pop ();
|
||||
if (!last_request_was_roundtrip)
|
||||
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop_with_return, traps = %d, roundtrip = %d\n",
|
||||
display->error_traps, last_request_was_roundtrip);
|
||||
|
||||
display->error_trap_synced_at_last_pop = TRUE;
|
||||
|
||||
return meta_error_trap_pop_internal (display,
|
||||
!last_request_was_roundtrip);
|
||||
}
|
||||
|
||||
static int
|
||||
x_error_handler (Display *xdisplay,
|
||||
XErrorEvent *error)
|
||||
{
|
||||
int retval;
|
||||
gchar buf[64];
|
||||
MetaDisplay *display;
|
||||
ForeignDisplay *foreign;
|
||||
|
||||
for (foreign = foreign_displays; foreign != NULL; foreign = foreign->next)
|
||||
{
|
||||
if (foreign->dpy == xdisplay)
|
||||
{
|
||||
foreign->handler (xdisplay, error, foreign->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
/* Display can be NULL here because the compositing manager
|
||||
* has its own Display, but Xlib only has one global error handler
|
||||
*/
|
||||
if (display->error_traps > 0)
|
||||
{
|
||||
/* we're in an error trap, chain to the trap handler
|
||||
* saved from GDK
|
||||
*/
|
||||
meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
g_assert (display->error_trap_handler != NULL);
|
||||
g_assert (display->error_trap_handler != x_error_handler);
|
||||
|
||||
retval = (* display->error_trap_handler) (xdisplay, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
retval = 1; /* compiler warning */
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
x_io_error_handler (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
if (display == NULL)
|
||||
meta_bug ("IO error received for unknown display?\n");
|
||||
|
||||
if (errno == EPIPE)
|
||||
{
|
||||
meta_warning (_("Lost connection to the display '%s';\n"
|
||||
"most likely the X server was shut down or you killed/destroyed\n"
|
||||
"the window manager.\n"),
|
||||
display->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
|
||||
errno, g_strerror (errno),
|
||||
display->name);
|
||||
}
|
||||
|
||||
/* Xlib would force an exit anyhow */
|
||||
exit (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include "errors.h"
|
||||
#include "keybindings-private.h"
|
||||
|
||||
#ifdef HAVE_RENDER
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#endif
|
||||
|
||||
#define EVENT_MASK (SubstructureRedirectMask | \
|
||||
StructureNotifyMask | SubstructureNotifyMask | \
|
||||
@@ -153,7 +155,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
window->rect.x,
|
||||
window->rect.y);
|
||||
/* FIXME handle this error */
|
||||
meta_error_trap_pop (window->display);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
|
||||
/* stick frame to the window */
|
||||
window->frame = frame;
|
||||
@@ -217,7 +219,7 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
*/
|
||||
window->frame->rect.x,
|
||||
window->frame->rect.y);
|
||||
meta_error_trap_pop (window->display);
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
|
||||
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
|
||||
|
||||
@@ -276,7 +278,7 @@ meta_frame_get_flags (MetaFrame *frame)
|
||||
if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
|
||||
flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
|
||||
|
||||
if (meta_window_appears_focused (frame->window))
|
||||
if (frame->window->has_focus)
|
||||
flags |= META_FRAME_HAS_FOCUS;
|
||||
|
||||
if (frame->window->shaded)
|
||||
|
||||
@@ -104,10 +104,6 @@ meta_group_unref (MetaGroup *group)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_group: (skip)
|
||||
*
|
||||
*/
|
||||
MetaGroup*
|
||||
meta_window_get_group (MetaWindow *window)
|
||||
{
|
||||
@@ -202,10 +198,6 @@ meta_window_shutdown_group (MetaWindow *window)
|
||||
remove_window_from_group (window);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_lookup_group: (skip)
|
||||
*
|
||||
*/
|
||||
MetaGroup*
|
||||
meta_display_lookup_group (MetaDisplay *display,
|
||||
Window group_leader)
|
||||
@@ -221,12 +213,6 @@ meta_display_lookup_group (MetaDisplay *display,
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_group_list_windows:
|
||||
* @group: A #MetaGroup
|
||||
*
|
||||
* Returns: (transfer container) (element-type Meta.Window): List of windows
|
||||
*/
|
||||
GSList*
|
||||
meta_group_list_windows (MetaGroup *group)
|
||||
{
|
||||
@@ -277,10 +263,6 @@ meta_group_get_startup_id (MetaGroup *group)
|
||||
return group->startup_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_group_property_notify: (skip)
|
||||
*
|
||||
*/
|
||||
gboolean
|
||||
meta_group_property_notify (MetaGroup *group,
|
||||
XEvent *event)
|
||||
|
||||
@@ -241,7 +241,7 @@ read_rgb_icon (MetaDisplay *display,
|
||||
0, G_MAXLONG,
|
||||
False, XA_CARDINAL, &type, &format, &nitems,
|
||||
&bytes_after, &data);
|
||||
err = meta_error_trap_pop_with_return (display);
|
||||
err = meta_error_trap_pop_with_return (display, TRUE);
|
||||
|
||||
if (err != Success ||
|
||||
result != Success)
|
||||
@@ -394,19 +394,21 @@ try_pixmap_and_mask (MetaDisplay *display,
|
||||
|
||||
get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
|
||||
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
|
||||
0, 0,
|
||||
unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
src_pixmap,
|
||||
0, 0, 0, 0,
|
||||
w, h);
|
||||
|
||||
if (unscaled && src_mask != None)
|
||||
{
|
||||
get_pixmap_geometry (display, src_mask, &w, &h, NULL);
|
||||
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
|
||||
0, 0,
|
||||
mask = meta_gdk_pixbuf_get_from_pixmap (NULL,
|
||||
src_mask,
|
||||
0, 0, 0, 0,
|
||||
w, h);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
@@ -482,7 +484,7 @@ get_kwm_win_icon (MetaDisplay *display,
|
||||
&bytes_after, &data);
|
||||
icons = (Pixmap *)data;
|
||||
|
||||
err = meta_error_trap_pop_with_return (display);
|
||||
err = meta_error_trap_pop_with_return (display, TRUE);
|
||||
if (err != Success ||
|
||||
result != Success)
|
||||
return;
|
||||
|
||||
@@ -45,7 +45,7 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
void meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event);
|
||||
void meta_set_keybindings_disabled (gboolean setting);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "frame-private.h"
|
||||
#include "place.h"
|
||||
#include "prefs.h"
|
||||
#include "effects.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
@@ -459,7 +460,7 @@ regrab_key_bindings (MetaDisplay *display)
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
windows = meta_display_list_windows (display);
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
@@ -470,16 +471,16 @@ regrab_key_bindings (MetaDisplay *display)
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
|
||||
static MetaKeyBinding *
|
||||
display_get_keybinding (MetaDisplay *display,
|
||||
unsigned int keysym,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
static MetaKeyBindingAction
|
||||
display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned int keysym,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -490,40 +491,13 @@ display_get_keybinding (MetaDisplay *display,
|
||||
display->key_bindings[i].keycode == keycode &&
|
||||
display->key_bindings[i].mask == mask)
|
||||
{
|
||||
return &display->key_bindings[i];
|
||||
return meta_prefs_get_keybinding_action (display->key_bindings[i].name);
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_keybinding_action:
|
||||
* @display: A #MetaDisplay
|
||||
* @keycode: Raw keycode
|
||||
* @mask: Event mask
|
||||
*
|
||||
* Returns: The action that should be taken for the given key, or
|
||||
* %META_KEYBINDING_ACTION_NONE.
|
||||
*/
|
||||
MetaKeyBindingAction
|
||||
meta_display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned int keycode,
|
||||
unsigned long mask)
|
||||
{
|
||||
MetaKeyBinding *binding;
|
||||
KeySym keysym;
|
||||
|
||||
keysym = XKeycodeToKeysym (display->xdisplay, keycode, 0);
|
||||
mask = mask & 0xff & ~display->ignored_modifier_mask;
|
||||
binding = display_get_keybinding (display, keysym, keycode, mask);
|
||||
|
||||
if (binding)
|
||||
return meta_prefs_get_keybinding_action (binding->name);
|
||||
else
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -700,7 +674,7 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
result = meta_error_trap_pop_with_return (display, FALSE);
|
||||
|
||||
if (grab && result != Success)
|
||||
{
|
||||
@@ -716,7 +690,7 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
++ignored_mask;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -758,7 +732,7 @@ grab_keys (MetaKeyBinding *bindings,
|
||||
++i;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -777,14 +751,14 @@ ungrab_all_keys (MetaDisplay *display,
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
result = meta_error_trap_pop_with_return (display, FALSE);
|
||||
|
||||
if (result != Success)
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Ungrabbing all keys on 0x%lx failed\n", xwindow);
|
||||
}
|
||||
else
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -916,7 +890,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
|
||||
if (grab_status != GrabSuccess)
|
||||
{
|
||||
meta_error_trap_pop_with_return (display);
|
||||
meta_error_trap_pop_with_return (display, TRUE);
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"XGrabKeyboard() returned failure status %s time %u\n",
|
||||
grab_status_to_string (grab_status),
|
||||
@@ -925,7 +899,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
}
|
||||
else
|
||||
{
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
result = meta_error_trap_pop_with_return (display, TRUE);
|
||||
if (result != Success)
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
@@ -948,7 +922,7 @@ ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
"Ungrabbing keyboard with timestamp %u\n",
|
||||
timestamp);
|
||||
XUngrabKeyboard (display->xdisplay, timestamp);
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1224,45 +1198,6 @@ process_overlay_key (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
invoke_handler (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaKeyHandler *handler,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
MetaKeyBinding *binding)
|
||||
|
||||
{
|
||||
if (handler->func)
|
||||
(* handler->func) (display, screen,
|
||||
handler->flags & BINDING_PER_WINDOW ?
|
||||
window : NULL,
|
||||
event,
|
||||
binding,
|
||||
handler->user_data);
|
||||
else
|
||||
(* handler->default_func) (display, screen,
|
||||
handler->flags & BINDING_PER_WINDOW ?
|
||||
window: NULL,
|
||||
event,
|
||||
binding,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
invoke_handler_by_name (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
const char *handler_name,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaKeyHandler *handler;
|
||||
|
||||
handler = find_handler (key_handlers, handler_name);
|
||||
if (handler)
|
||||
invoke_handler (display, screen, handler, window, event, NULL);
|
||||
}
|
||||
|
||||
/* now called from only one place, may be worth merging */
|
||||
static gboolean
|
||||
process_event (MetaKeyBinding *bindings,
|
||||
@@ -1319,7 +1254,20 @@ process_event (MetaKeyBinding *bindings,
|
||||
*/
|
||||
display->allow_terminal_deactivation = TRUE;
|
||||
|
||||
invoke_handler (display, screen, handler, window, event, &bindings[i]);
|
||||
if (handler->func)
|
||||
(* handler->func) (display, screen,
|
||||
bindings[i].handler->flags & BINDING_PER_WINDOW ?
|
||||
window: NULL,
|
||||
event,
|
||||
&bindings[i],
|
||||
handler->user_data);
|
||||
else
|
||||
(* handler->default_func) (display, screen,
|
||||
bindings[i].handler->flags & BINDING_PER_WINDOW ?
|
||||
window: NULL,
|
||||
event,
|
||||
&bindings[i],
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1334,16 +1282,13 @@ process_event (MetaKeyBinding *bindings,
|
||||
* right. This cannot cause infinite recursion because we never call
|
||||
* ourselves when there wasn't a grab, and we always clear the grab
|
||||
* first; the invariant is enforced using an assertion. See #112560.
|
||||
*
|
||||
* The return value is whether we handled the key event.
|
||||
*
|
||||
* FIXME: We need to prove there are no race conditions here.
|
||||
* FIXME: Does it correctly handle alt-Tab being followed by another
|
||||
* grabbing keypress without letting go of alt?
|
||||
* FIXME: An iterative solution would probably be simpler to understand
|
||||
* (and help us solve the other fixmes).
|
||||
*/
|
||||
gboolean
|
||||
void
|
||||
meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
@@ -1359,7 +1304,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
all_bindings_disabled ? ReplayKeyboard : AsyncKeyboard,
|
||||
event->xkey.time);
|
||||
if (all_bindings_disabled)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
/* if key event was on root window, we have a shortcut */
|
||||
screen = meta_display_screen_for_root (display, event->xkey.window);
|
||||
@@ -1370,11 +1315,12 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
event->xany.window);
|
||||
|
||||
if (screen == NULL)
|
||||
return FALSE; /* event window is destroyed */
|
||||
return; /* event window is destroyed */
|
||||
|
||||
/* ignore key events on popup menus and such. */
|
||||
if (meta_ui_window_is_widget (screen->ui, event->xany.window))
|
||||
return FALSE;
|
||||
if (window == NULL &&
|
||||
meta_ui_window_is_widget (screen->ui, event->xany.window))
|
||||
return;
|
||||
|
||||
/* window may be NULL */
|
||||
|
||||
@@ -1394,7 +1340,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
if (all_keys_grabbed)
|
||||
{
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return TRUE;
|
||||
return;
|
||||
/* If we get here we have a global grab, because
|
||||
* we're in some special keyboard mode such as window move
|
||||
* mode.
|
||||
@@ -1471,20 +1417,18 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
"Ending grab op %u on key event sym %s\n",
|
||||
display->grab_op, XKeysymToString (keysym));
|
||||
meta_display_end_grab_op (display, event->xkey.time);
|
||||
return;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
handled = process_overlay_key (display, screen, event, keysym);
|
||||
if (handled)
|
||||
return TRUE;
|
||||
|
||||
/* Do the normal keybindings */
|
||||
return process_event (display->key_bindings,
|
||||
display->n_key_bindings,
|
||||
display, screen, window, event, keysym,
|
||||
!all_keys_grabbed && window);
|
||||
if (!handled)
|
||||
process_event (display->key_bindings,
|
||||
display->n_key_bindings,
|
||||
display, screen, window, event, keysym,
|
||||
!all_keys_grabbed && window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1503,19 +1447,23 @@ process_mouse_move_resize_grab (MetaDisplay *display,
|
||||
/* End move or resize and restore to original state. If the
|
||||
* window was a maximized window that had been "shaken loose" we
|
||||
* need to remaximize it. In normal cases, we need to do a
|
||||
* moveresize now to get the position back to the original.
|
||||
* moveresize now to get the position back to the original. In
|
||||
* wireframe mode, we just need to set grab_was_cancelled to tru
|
||||
* to avoid avoid moveresizing to the position of the wireframe.
|
||||
*/
|
||||
if (window->shaken_loose)
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL |
|
||||
META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
else if (!display->grab_wireframe_active)
|
||||
meta_window_move_resize (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
else
|
||||
display->grab_was_cancelled = TRUE;
|
||||
|
||||
/* End grab */
|
||||
return FALSE;
|
||||
@@ -1546,7 +1494,15 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return TRUE;
|
||||
|
||||
meta_window_get_position (window, &x, &y);
|
||||
if (display->grab_wireframe_active)
|
||||
{
|
||||
x = display->grab_wireframe_rect.x;
|
||||
y = display->grab_wireframe_rect.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_get_position (window, &x, &y);
|
||||
}
|
||||
|
||||
smart_snap = (event->xkey.state & ShiftMask) != 0;
|
||||
|
||||
@@ -1565,19 +1521,23 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
/* End move and restore to original state. If the window was a
|
||||
* maximized window that had been "shaken loose" we need to
|
||||
* remaximize it. In normal cases, we need to do a moveresize
|
||||
* now to get the position back to the original.
|
||||
* now to get the position back to the original. In wireframe
|
||||
* mode, we just need to set grab_was_cancelled to tru to avoid
|
||||
* avoid moveresizing to the position of the wireframe.
|
||||
*/
|
||||
if (window->shaken_loose)
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL |
|
||||
META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
else if (!display->grab_wireframe_active)
|
||||
meta_window_move_resize (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
else
|
||||
display->grab_was_cancelled = TRUE;
|
||||
}
|
||||
|
||||
/* When moving by increments, we still snap to edges if the move
|
||||
@@ -1628,7 +1588,10 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
"Computed new window location %d,%d due to keypress\n",
|
||||
x, y);
|
||||
|
||||
meta_window_get_client_root_coords (window, &old_rect);
|
||||
if (display->grab_wireframe_active)
|
||||
old_rect = display->grab_wireframe_rect;
|
||||
else
|
||||
meta_window_get_client_root_coords (window, &old_rect);
|
||||
|
||||
meta_window_edge_resistance_for_move (window,
|
||||
old_rect.x,
|
||||
@@ -1639,7 +1602,17 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
smart_snap,
|
||||
TRUE);
|
||||
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
if (display->grab_wireframe_active)
|
||||
{
|
||||
meta_window_update_wireframe (window, x, y,
|
||||
display->grab_wireframe_rect.width,
|
||||
display->grab_wireframe_rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
}
|
||||
|
||||
meta_window_update_keyboard_move (window);
|
||||
}
|
||||
|
||||
@@ -1794,13 +1767,21 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
|
||||
if (keysym == XK_Escape)
|
||||
{
|
||||
/* End resize and restore to original state. */
|
||||
meta_window_move_resize (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
/* End resize and restore to original state. If not in
|
||||
* wireframe mode, we need to do a moveresize now to get the
|
||||
* position back to the original. If we are in wireframe mode,
|
||||
* we need to avoid moveresizing to the position of the
|
||||
* wireframe.
|
||||
*/
|
||||
if (!display->grab_wireframe_active)
|
||||
meta_window_move_resize (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
else
|
||||
display->grab_was_cancelled = TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1809,8 +1790,16 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
event, keysym))
|
||||
return TRUE;
|
||||
|
||||
width = window->rect.width;
|
||||
height = window->rect.height;
|
||||
if (display->grab_wireframe_active)
|
||||
{
|
||||
width = display->grab_wireframe_rect.width;
|
||||
height = display->grab_wireframe_rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = window->rect.width;
|
||||
height = window->rect.height;
|
||||
}
|
||||
|
||||
gravity = meta_resize_gravity_from_grab_op (display->grab_op);
|
||||
|
||||
@@ -1975,7 +1964,10 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
"%dx%d, gravity %s\n",
|
||||
width, height, meta_gravity_to_string (gravity));
|
||||
|
||||
old_rect = window->rect; /* Don't actually care about x,y */
|
||||
if (display->grab_wireframe_active)
|
||||
old_rect = display->grab_wireframe_rect;
|
||||
else
|
||||
old_rect = window->rect; /* Don't actually care about x,y */
|
||||
|
||||
/* Do any edge resistance/snapping */
|
||||
meta_window_edge_resistance_for_resize (window,
|
||||
@@ -1988,16 +1980,32 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
smart_snap,
|
||||
TRUE);
|
||||
|
||||
/* We don't need to update unless the specified width and height
|
||||
* are actually different from what we had before.
|
||||
*/
|
||||
if (window->rect.width != width || window->rect.height != height)
|
||||
meta_window_resize_with_gravity (window,
|
||||
TRUE,
|
||||
width,
|
||||
height,
|
||||
gravity);
|
||||
|
||||
if (display->grab_wireframe_active)
|
||||
{
|
||||
MetaRectangle new_position;
|
||||
meta_rectangle_resize_with_gravity (&display->grab_wireframe_rect,
|
||||
&new_position,
|
||||
gravity,
|
||||
width,
|
||||
height);
|
||||
meta_window_update_wireframe (window,
|
||||
new_position.x,
|
||||
new_position.y,
|
||||
new_position.width,
|
||||
new_position.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We don't need to update unless the specified width and height
|
||||
* are actually different from what we had before.
|
||||
*/
|
||||
if (window->rect.width != width || window->rect.height != height)
|
||||
meta_window_resize_with_gravity (window,
|
||||
TRUE,
|
||||
width,
|
||||
height,
|
||||
gravity);
|
||||
}
|
||||
meta_window_update_keyboard_resize (window, FALSE);
|
||||
}
|
||||
|
||||
@@ -2037,7 +2045,6 @@ process_tab_grab (MetaDisplay *display,
|
||||
XEvent *event,
|
||||
KeySym keysym)
|
||||
{
|
||||
MetaKeyBinding *binding;
|
||||
MetaKeyBindingAction action;
|
||||
gboolean popup_not_showing;
|
||||
gboolean backward;
|
||||
@@ -2047,84 +2054,79 @@ process_tab_grab (MetaDisplay *display,
|
||||
if (screen != display->grab_screen)
|
||||
return FALSE;
|
||||
|
||||
binding = display_get_keybinding (display,
|
||||
keysym,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
if (binding)
|
||||
action = meta_prefs_get_keybinding_action (binding->name);
|
||||
else
|
||||
action = META_KEYBINDING_ACTION_NONE;
|
||||
action = display_get_keybinding_action (display,
|
||||
keysym,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
|
||||
/*
|
||||
* If there is no tab_pop up object, i.e., there is some custom handler
|
||||
* implementing Alt+Tab & Co., we call this custom handler; we do not
|
||||
* mess about with the grab, as that is up to the handler to deal with.
|
||||
*/
|
||||
if (!screen->tab_popup)
|
||||
if (!screen->tab_handler)
|
||||
{
|
||||
if (event->type == KeyRelease)
|
||||
{
|
||||
if (end_keyboard_grab (display, event->xkey.keycode))
|
||||
{
|
||||
invoke_handler_by_name (display, screen, "tab_popup_select", NULL, event);
|
||||
|
||||
/* We return FALSE to end the grab; if the handler ended the grab itself
|
||||
* that will be a noop. If the handler didn't end the grab, then it's a
|
||||
* safety measure to prevent a stuck grab.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
MetaKeyHandler *handler = NULL;
|
||||
const gchar *handler_name = NULL;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case META_KEYBINDING_ACTION_CYCLE_PANELS:
|
||||
handler_name = "cycle_group";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_CYCLE_WINDOWS:
|
||||
handler_name = "cycle_windows";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD:
|
||||
handler_name = "cycle_panels_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD:
|
||||
handler_name = "cycle_windows_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_PANELS:
|
||||
handler_name = "switch_panels";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
|
||||
handler_name = "switch_windows";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD:
|
||||
handler_name = "switch_panels_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD:
|
||||
handler_name = "switch_windows_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_CYCLE_GROUP:
|
||||
handler_name = "cycle_group";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD:
|
||||
handler_name = "cycle_group_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_GROUP:
|
||||
handler_name = "switch_group";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD:
|
||||
/* These are the tab-popup bindings. If a custom Alt-Tab implementation
|
||||
* is in effect, we expect it to want to handle all of these as a group
|
||||
*
|
||||
* If there are some of them that the custom implementation didn't
|
||||
* handle, we treat them as "unbound" for the duration - running the
|
||||
* normal handlers could get us into trouble.
|
||||
*/
|
||||
if (binding->handler &&
|
||||
binding->handler->func &&
|
||||
binding->handler->func != binding->handler->default_func)
|
||||
{
|
||||
invoke_handler (display, screen, binding->handler, NULL, event, binding);
|
||||
return TRUE;
|
||||
}
|
||||
handler_name = "switch_group_backward";
|
||||
break;
|
||||
case META_KEYBINDING_ACTION_NONE:
|
||||
{
|
||||
/*
|
||||
* If this is simply user pressing the Shift key, we do not want
|
||||
* to cancel the grab.
|
||||
*/
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
/*
|
||||
* This is the case when the Alt key is released; we preserve
|
||||
* the grab, as it is up to the custom implementaiton to free it
|
||||
* (a plugin can catch this in their xevent_filter function).
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Some unhandled key press */
|
||||
invoke_handler_by_name (display, screen, "tab_popup_cancel", NULL, event);
|
||||
return FALSE;
|
||||
/*
|
||||
* We do not want to actually call the handler, we just want to ensure
|
||||
* that if a custom handler is installed, we do not release the grab here.
|
||||
* The handler will get called as normal in the process_event() function.
|
||||
*/
|
||||
handler = find_handler (key_handlers, handler_name);
|
||||
|
||||
if (!handler || !handler->func || handler->func == handler->default_func)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (event->type == KeyRelease &&
|
||||
@@ -2569,7 +2571,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
|
||||
int new_x, new_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
@@ -2701,7 +2703,7 @@ handle_move_to_center (MetaDisplay *display,
|
||||
int orig_x, orig_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
@@ -2776,9 +2778,10 @@ process_workspace_switch_grab (MetaDisplay *display,
|
||||
MetaWorkspace *target_workspace;
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
action = meta_display_get_keybinding_action (display,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
action = display_get_keybinding_action (display,
|
||||
keysym,
|
||||
event->xkey.keycode,
|
||||
display->grab_mask);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
@@ -2898,7 +2901,7 @@ handle_panel (MetaDisplay *display,
|
||||
StructureNotifyMask,
|
||||
(XEvent*) &ev);
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
meta_error_trap_pop (display, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3105,27 +3108,6 @@ handle_cycle (MetaDisplay *display,
|
||||
backwards, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_tab_popup_select (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
/* Stub for custom handlers; no default implementation */
|
||||
}
|
||||
|
||||
static void
|
||||
handle_tab_popup_cancel (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
/* Stub for custom handlers; no default implementation */
|
||||
}
|
||||
|
||||
static void
|
||||
handle_toggle_fullscreen (MetaDisplay *display,
|
||||
@@ -3545,10 +3527,6 @@ meta_keybindings_set_custom_handler (const gchar *name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_keybindings_switch_window: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
|
||||
138
src/core/main.c
138
src/core/main.c
@@ -68,14 +68,15 @@
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INTROSPECTION
|
||||
#include <girepository.h>
|
||||
#include "compositor/meta-plugin-manager.h"
|
||||
#include "compositor/mutter/mutter-plugin-manager.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -125,13 +126,11 @@ log_handler (const gchar *log_domain,
|
||||
static void
|
||||
version (void)
|
||||
{
|
||||
const int latest_year = 2010;
|
||||
|
||||
g_print (_("mutter %s\n"
|
||||
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
"Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
|
||||
VERSION, latest_year);
|
||||
VERSION);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -179,6 +178,11 @@ meta_print_compilation_info (void)
|
||||
#else
|
||||
meta_verbose ("Compiled without startup notification\n");
|
||||
#endif
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
meta_verbose ("Compiled with composite extensions\n");
|
||||
#else
|
||||
meta_verbose ("Compiled without composite extensions\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,12 +233,16 @@ typedef struct
|
||||
gboolean sync;
|
||||
gboolean composite;
|
||||
gboolean no_composite;
|
||||
gboolean no_force_fullscreen;
|
||||
gboolean no_tab_popup;
|
||||
gchar *introspect;
|
||||
} MetaArguments;
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
#define COMPOSITE_OPTS_FLAGS 0
|
||||
#else /* HAVE_COMPOSITE_EXTENSIONS */
|
||||
/* No compositor, so don't show the arguments in --help */
|
||||
#define COMPOSITE_OPTS_FLAGS G_OPTION_FLAG_HIDDEN
|
||||
#endif /* HAVE_COMPOSITE_EXTENSIONS */
|
||||
|
||||
/**
|
||||
* Parses argc and argv and returns the
|
||||
@@ -308,18 +316,14 @@ meta_parse_options (int *argc, char ***argv,
|
||||
N_("Turn compositing off"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
|
||||
&my_args.no_force_fullscreen,
|
||||
N_("Don't make fullscreen windows that are maximized and have no decorations"),
|
||||
NULL
|
||||
},
|
||||
#ifdef WITH_CLUTTER
|
||||
{
|
||||
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
|
||||
&my_args.mutter_plugins,
|
||||
N_("Comma-separated list of compositor plugins"),
|
||||
"PLUGINS"
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"no-tab-popup", 0, 0, G_OPTION_ARG_NONE,
|
||||
&my_args.no_tab_popup,
|
||||
@@ -340,8 +344,15 @@ meta_parse_options (int *argc, char ***argv,
|
||||
|
||||
ctx = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (ctx, options, "mutter");
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
/*
|
||||
* This function is only available in clutter >= 0.8.2
|
||||
*/
|
||||
#if CLUTTER_CHECK_VERSION(0,8,2)
|
||||
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
|
||||
g_option_context_add_group (ctx, cogl_get_option_group ());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!g_option_context_parse (ctx, argc, argv, &error))
|
||||
{
|
||||
@@ -354,6 +365,8 @@ meta_parse_options (int *argc, char ***argv,
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
||||
* doesn't need (and shouldn't) run its normal event source which polls
|
||||
* the X fd, but we do have to deal with dispatching events that accumulate
|
||||
@@ -401,20 +414,24 @@ static GSourceFuncs event_funcs = {
|
||||
static void
|
||||
meta_clutter_init (GOptionContext *ctx, int *argc, char ***argv)
|
||||
{
|
||||
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
clutter_x11_set_display (gdk_display);
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
|
||||
if (CLUTTER_INIT_SUCCESS == clutter_init (argc, argv))
|
||||
{
|
||||
meta_compositor_can_use_clutter__ = 1;
|
||||
|
||||
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_fatal ("Unable to initialize Clutter.\n");
|
||||
g_message ("Unable to initialize Clutter.\n");
|
||||
meta_compositor_can_use_clutter__ = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Selects which display Mutter should use. It first tries to use
|
||||
@@ -438,37 +455,43 @@ meta_select_display (gchar *display_name)
|
||||
static void
|
||||
meta_finalize (void)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (display)
|
||||
meta_display_close (display,
|
||||
CurrentTime); /* I doubt correct timestamps matter here */
|
||||
meta_display_close (meta_get_display (),
|
||||
CurrentTime); /* I doubt correct timestamps matter here */
|
||||
|
||||
meta_session_shutdown ();
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void
|
||||
sigterm_handler (int signum)
|
||||
{
|
||||
if (sigterm_pipe_fds[1] >= 0)
|
||||
{
|
||||
int dummy;
|
||||
meta_finalize ();
|
||||
|
||||
dummy = write (sigterm_pipe_fds[1], "", 1);
|
||||
close (sigterm_pipe_fds[1]);
|
||||
sigterm_pipe_fds[1] = -1;
|
||||
}
|
||||
exit (meta_exit_code);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (void)
|
||||
static guint sigchld_signal_id = 0;
|
||||
|
||||
static void
|
||||
sigchld_handler (int signum, siginfo_t *info, void *context)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
}
|
||||
int stat;
|
||||
|
||||
if (info->si_code == CLD_EXITED)
|
||||
{
|
||||
g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
|
||||
info->si_status,
|
||||
GINT_TO_POINTER (info->si_pid));
|
||||
}
|
||||
|
||||
g_signal_handlers_disconnect_matched (sigchld_nexus,
|
||||
G_SIGNAL_MATCH_DATA,
|
||||
sigchld_signal_id,
|
||||
0, NULL, NULL,
|
||||
GINT_TO_POINTER (info->si_pid));
|
||||
|
||||
waitpid (info->si_pid, &stat, WNOHANG);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where the story begins. It parses commandline options and
|
||||
* environment variables, sets up the screen, hands control off to
|
||||
@@ -491,9 +514,8 @@ main (int argc, char **argv)
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
GIOChannel *channel;
|
||||
GOptionContext *ctx;
|
||||
|
||||
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
|
||||
@@ -515,21 +537,29 @@ main (int argc, char **argv)
|
||||
g_strerror (errno));
|
||||
#endif
|
||||
|
||||
if (pipe (sigterm_pipe_fds) != 0)
|
||||
g_printerr ("Failed to create SIGTERM pipe: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
|
||||
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
|
||||
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
|
||||
g_io_channel_set_close_on_unref (channel, TRUE);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
act.sa_handler = &sigterm_handler;
|
||||
if (sigaction (SIGTERM, &act, NULL) < 0)
|
||||
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
sigchld_nexus = g_object_new (META_TYPE_NEXUS, NULL);
|
||||
|
||||
sigchld_signal_id =
|
||||
g_signal_new ("sigchld", META_TYPE_NEXUS,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT_POINTER,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
G_TYPE_UINT, G_TYPE_POINTER);
|
||||
|
||||
act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
act.sa_handler = SIG_DFL;
|
||||
act.sa_sigaction = &sigchld_handler;
|
||||
if (sigaction (SIGCHLD, &act, NULL) < 0)
|
||||
g_printerr ("Failed to register SIGCHLD handler: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
meta_set_verbose (TRUE);
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
@@ -551,6 +581,7 @@ main (int argc, char **argv)
|
||||
/* Parse command line arguments.*/
|
||||
ctx = meta_parse_options (&argc, &argv, &meta_args);
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
/* This must come before the introspect below, so we load all the plugins
|
||||
* in order to get their get_type functions.
|
||||
*/
|
||||
@@ -572,6 +603,7 @@ main (int argc, char **argv)
|
||||
g_slist_free(plugins_list);
|
||||
g_strfreev (plugins);
|
||||
}
|
||||
#endif /* WITH_CLUTTER */
|
||||
|
||||
#ifdef HAVE_INTROSPECTION
|
||||
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
||||
@@ -586,8 +618,8 @@ main (int argc, char **argv)
|
||||
* is initialized at this point, and we don't plan to run any real
|
||||
* plugin code.
|
||||
*/
|
||||
MetaPluginManager *mgr = meta_plugin_manager_get_default ();
|
||||
if (!meta_plugin_manager_load (mgr))
|
||||
MutterPluginManager *mgr = mutter_plugin_manager_new (NULL);
|
||||
if (!mutter_plugin_manager_load (mgr))
|
||||
g_critical ("failed to load plugins");
|
||||
}
|
||||
if (!g_irepository_dump (meta_args.introspect, &error))
|
||||
@@ -616,13 +648,18 @@ main (int argc, char **argv)
|
||||
|
||||
meta_ui_init (&argc, &argv);
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
/*
|
||||
* Clutter can only be initialized after the UI.
|
||||
*/
|
||||
meta_clutter_init (ctx, &argc, &argv);
|
||||
#endif
|
||||
|
||||
g_option_context_free (ctx);
|
||||
|
||||
/* must be after UI init so we can override GDK handlers */
|
||||
meta_errors_init ();
|
||||
|
||||
/* Load prefs */
|
||||
meta_prefs_init ();
|
||||
meta_prefs_add_listener (prefs_changed_callback, NULL);
|
||||
@@ -708,9 +745,6 @@ main (int argc, char **argv)
|
||||
if (meta_args.composite || meta_args.no_composite)
|
||||
meta_prefs_set_compositing_manager (meta_args.composite);
|
||||
|
||||
if (meta_args.no_force_fullscreen)
|
||||
meta_prefs_set_force_fullscreen (FALSE);
|
||||
|
||||
if (meta_args.no_tab_popup)
|
||||
{
|
||||
meta_prefs_override_no_tab_popup (TRUE);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "boxes-private.h"
|
||||
#include "place.h"
|
||||
#include "workspace.h"
|
||||
#include "prefs.h"
|
||||
@@ -105,7 +104,7 @@ find_next_cascade (MetaWindow *window,
|
||||
int window_width, window_height;
|
||||
int cascade_stage;
|
||||
MetaRectangle work_area;
|
||||
const MetaMonitorInfo* current;
|
||||
const MetaXineramaScreenInfo* current;
|
||||
|
||||
sorted = g_list_copy (windows);
|
||||
sorted = g_list_sort (sorted, northwestcmp);
|
||||
@@ -136,8 +135,8 @@ find_next_cascade (MetaWindow *window,
|
||||
* of NW corner of window frame.
|
||||
*/
|
||||
|
||||
current = meta_screen_get_current_monitor (window->screen);
|
||||
meta_window_get_work_area_for_monitor (window, current->number, &work_area);
|
||||
current = meta_screen_get_current_xinerama (window->screen);
|
||||
meta_window_get_work_area_for_xinerama (window, current->number, &work_area);
|
||||
|
||||
cascade_x = MAX (0, work_area.x);
|
||||
cascade_y = MAX (0, work_area.y);
|
||||
@@ -258,7 +257,7 @@ find_most_freespace (MetaWindow *window,
|
||||
frame_size_left = fgeom ? fgeom->left_width : 0;
|
||||
frame_size_top = fgeom ? fgeom->top_height : 0;
|
||||
|
||||
meta_window_get_work_area_current_monitor (focus_window, &work_area);
|
||||
meta_window_get_work_area_current_xinerama (focus_window, &work_area);
|
||||
meta_window_get_outer_rect (focus_window, &avoid);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
@@ -509,7 +508,7 @@ find_first_fit (MetaWindow *window,
|
||||
MetaFrameGeometry *fgeom,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
int monitor,
|
||||
int xinerama,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
@@ -552,16 +551,16 @@ find_first_fit (MetaWindow *window,
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
{
|
||||
char monitor_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
|
||||
monitor_location_string);
|
||||
char xinerama_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->xinerama_infos[xinerama].rect,
|
||||
xinerama_location_string);
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Natural monitor is %s\n",
|
||||
monitor_location_string);
|
||||
"Natural xinerama is %s\n",
|
||||
xinerama_location_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
|
||||
meta_window_get_work_area_for_xinerama (window, xinerama, &work_area);
|
||||
|
||||
center_tile_rect_in_area (&rect, &work_area);
|
||||
|
||||
@@ -659,7 +658,7 @@ meta_window_place (MetaWindow *window,
|
||||
int *new_y)
|
||||
{
|
||||
GList *windows;
|
||||
const MetaMonitorInfo *xi;
|
||||
const MetaXineramaScreenInfo *xi;
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameGeometry. But remember fgeom == NULL
|
||||
@@ -811,11 +810,11 @@ meta_window_place (MetaWindow *window,
|
||||
window->type == META_WINDOW_MODAL_DIALOG ||
|
||||
window->type == META_WINDOW_SPLASHSCREEN)
|
||||
{
|
||||
/* Center on current monitor */
|
||||
/* Center on current xinerama (i.e. on current monitor) */
|
||||
int w, h;
|
||||
|
||||
/* Warning, this function is a round trip! */
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
|
||||
w = xi->rect.width;
|
||||
h = xi->rect.height;
|
||||
@@ -826,7 +825,7 @@ meta_window_place (MetaWindow *window,
|
||||
x += xi->rect.x;
|
||||
y += xi->rect.y;
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n",
|
||||
window->desc, window->screen->number, xi->number);
|
||||
|
||||
goto done_check_denied_focus;
|
||||
@@ -840,7 +839,7 @@ meta_window_place (MetaWindow *window,
|
||||
GSList *all_windows;
|
||||
GSList *tmp;
|
||||
|
||||
all_windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
||||
all_windows = meta_display_list_windows (window->display);
|
||||
|
||||
tmp = all_windows;
|
||||
while (tmp != NULL)
|
||||
@@ -860,7 +859,7 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Warning, this is a round trip! */
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
@@ -881,9 +880,9 @@ meta_window_place (MetaWindow *window,
|
||||
MetaRectangle workarea;
|
||||
MetaRectangle outer;
|
||||
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
/* If the window is bigger than the screen, then automaximize. Do NOT
|
||||
|
||||
653
src/core/prefs.c
653
src/core/prefs.c
@@ -27,7 +27,6 @@
|
||||
#include "prefs.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "compositor/meta-plugin-manager.h"
|
||||
#ifdef HAVE_GCONF
|
||||
#include <gconf/gconf-client.h>
|
||||
#endif
|
||||
@@ -53,7 +52,6 @@
|
||||
#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager"
|
||||
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
|
||||
|
||||
#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
|
||||
#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
|
||||
|
||||
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
|
||||
@@ -64,10 +62,12 @@
|
||||
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
|
||||
#define KEY_LIST_BINDINGS_SUFFIX "_list"
|
||||
|
||||
#define KEY_WORKSPACE_NAME_DIRECTORY "/apps/metacity/workspace_names"
|
||||
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
#define KEY_CLUTTER_DISABLED "/apps/mutter/general/clutter_disabled"
|
||||
#define KEY_CLUTTER_PLUGINS "/apps/mutter/general/clutter_plugins"
|
||||
#endif
|
||||
|
||||
#define KEY_LIVE_HIDDEN_WINDOWS "/apps/mutter/general/live_hidden_windows"
|
||||
|
||||
@@ -86,7 +86,6 @@ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
|
||||
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
|
||||
static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
|
||||
static gboolean raise_on_click = TRUE;
|
||||
static gboolean attach_modal_dialogs = FALSE;
|
||||
static char* current_theme = NULL;
|
||||
static int num_workspaces = 4;
|
||||
static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
|
||||
@@ -98,14 +97,13 @@ static gboolean auto_raise = FALSE;
|
||||
static gboolean auto_raise_delay = 500;
|
||||
static gboolean provide_visual_bell = FALSE;
|
||||
static gboolean bell_is_audible = TRUE;
|
||||
static gboolean reduced_resources = FALSE;
|
||||
static gboolean gnome_accessibility = FALSE;
|
||||
static gboolean gnome_animations = TRUE;
|
||||
static char *cursor_theme = NULL;
|
||||
static int cursor_size = 24;
|
||||
static gboolean compositing_manager = FALSE;
|
||||
static gboolean resize_with_right_button = FALSE;
|
||||
static gboolean side_by_side_tiling = FALSE;
|
||||
static gboolean force_fullscreen = TRUE;
|
||||
|
||||
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
|
||||
static MetaButtonLayout button_layout;
|
||||
@@ -117,8 +115,11 @@ static char *terminal_command = NULL;
|
||||
|
||||
static char *workspace_names[MAX_REASONABLE_WORKSPACES] = { NULL, };
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
static gboolean clutter_disabled = FALSE;
|
||||
static gboolean clutter_plugins_overridden = FALSE;
|
||||
static GSList *clutter_plugins = NULL;
|
||||
#endif
|
||||
|
||||
static gboolean live_hidden_windows = FALSE;
|
||||
|
||||
@@ -127,30 +128,18 @@ static gboolean no_tab_popup = FALSE;
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
|
||||
|
||||
static char *binding_name (const char *gconf_key);
|
||||
|
||||
static gboolean update_key_binding (const char *key,
|
||||
static gboolean update_key_binding (const char *name,
|
||||
const char *value);
|
||||
typedef enum
|
||||
{
|
||||
META_LIST_OF_STRINGS,
|
||||
META_LIST_OF_GCONFVALUE_STRINGS
|
||||
} MetaStringListType;
|
||||
|
||||
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
static gboolean update_key_list_binding (const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
GSList *value);
|
||||
static gboolean update_key_list_binding (const char *name,
|
||||
GSList *value);
|
||||
static gboolean update_command (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_workspace_name (const char *name,
|
||||
const char *value);
|
||||
|
||||
static void notify_new_value (const char *key,
|
||||
GConfValue *value);
|
||||
static void change_notify (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
GConfEntry *entry,
|
||||
@@ -160,8 +149,14 @@ static char* gconf_key_for_workspace_name (int i);
|
||||
|
||||
static void queue_changed (MetaPreference pref);
|
||||
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
typedef enum
|
||||
{
|
||||
META_LIST_OF_STRINGS,
|
||||
META_LIST_OF_GCONFVALUE_STRINGS
|
||||
} MetaStringListType;
|
||||
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
|
||||
static void cleanup_error (GError **error);
|
||||
@@ -233,12 +228,7 @@ static GConfEnumStringPair symtab_titlebar_action[] =
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that 'gchar *key' is the first element of all these structures;
|
||||
* we count on that below in key_is_used and do_override.
|
||||
*/
|
||||
|
||||
/*
|
||||
/**
|
||||
* The details of one preference which is constrained to be
|
||||
* one of a small number of string values-- in other words,
|
||||
* an enumeration.
|
||||
@@ -251,6 +241,21 @@ static GConfEnumStringPair symtab_titlebar_action[] =
|
||||
* been outweighed by the bugs caused when the ordering of the enum
|
||||
* strings got out of sync with the actual enum statement. Also,
|
||||
* there is existing library code to use this kind of symbol tables.
|
||||
*
|
||||
* Other things we might consider doing to clean this up in the
|
||||
* future include:
|
||||
*
|
||||
* - most of the keys begin with the same prefix, and perhaps we
|
||||
* could assume it if they don't start with a slash
|
||||
*
|
||||
* - there are several cases where a single identifier could be used
|
||||
* to generate an entire entry, and perhaps this could be done
|
||||
* with a macro. (This would reduce clarity, however, and is
|
||||
* probably a bad thing.)
|
||||
*
|
||||
* - these types all begin with a gchar* (and contain a MetaPreference)
|
||||
* and we can factor out the repeated code in the handlers by taking
|
||||
* advantage of this using some kind of union arrangement.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -363,11 +368,6 @@ static MetaEnumPreference preferences_enum[] =
|
||||
|
||||
static MetaBoolPreference preferences_bool[] =
|
||||
{
|
||||
{ "/apps/mutter/general/attach_modal_dialogs",
|
||||
META_PREF_ATTACH_MODAL_DIALOGS,
|
||||
&attach_modal_dialogs,
|
||||
TRUE,
|
||||
},
|
||||
{ "/apps/metacity/general/raise_on_click",
|
||||
META_PREF_RAISE_ON_CLICK,
|
||||
&raise_on_click,
|
||||
@@ -403,6 +403,11 @@ static MetaBoolPreference preferences_bool[] =
|
||||
&bell_is_audible, /* FIXME: change the name: it's confusing */
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/reduced_resources",
|
||||
META_PREF_REDUCED_RESOURCES,
|
||||
&reduced_resources,
|
||||
FALSE,
|
||||
},
|
||||
{ "/desktop/gnome/interface/accessibility",
|
||||
META_PREF_GNOME_ACCESSIBILITY,
|
||||
&gnome_accessibility,
|
||||
@@ -423,11 +428,13 @@ static MetaBoolPreference preferences_bool[] =
|
||||
&resize_with_right_button,
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/side_by_side_tiling",
|
||||
META_PREF_SIDE_BY_SIDE_TILING,
|
||||
&side_by_side_tiling,
|
||||
#ifdef WITH_CLUTTER
|
||||
{ "/apps/mutter/general/clutter_disabled",
|
||||
META_PREF_CLUTTER_DISABLED,
|
||||
&clutter_disabled,
|
||||
FALSE,
|
||||
},
|
||||
#endif
|
||||
{ "/apps/mutter/general/live_hidden_windows",
|
||||
META_PREF_LIVE_HIDDEN_WINDOWS,
|
||||
&live_hidden_windows,
|
||||
@@ -501,20 +508,6 @@ static MetaIntPreference preferences_int[] =
|
||||
{ NULL, 0, NULL, 0, 0, 0, },
|
||||
};
|
||||
|
||||
/*
|
||||
* This is used to keep track of preferences that have been
|
||||
* repointed to a different GConf key location; we modify the
|
||||
* preferences arrays directly, but we also need to remember
|
||||
* what we have done to handle subsequent overrides correctly.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
gchar *original_key;
|
||||
gchar *new_key;
|
||||
} MetaPrefsOverriddenKey;
|
||||
|
||||
static GSList *overridden_keys;
|
||||
|
||||
static void
|
||||
handle_preference_init_enum (void)
|
||||
{
|
||||
@@ -898,10 +891,6 @@ handle_preference_update_int (const gchar *key, GConfValue *value)
|
||||
/* Listeners. */
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* meta_prefs_add_listener: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||||
gpointer data)
|
||||
@@ -915,10 +904,6 @@ meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||||
listeners = g_list_prepend (listeners, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_remove_listener: (skip)
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_prefs_remove_listener (MetaPrefsChangedFunc func,
|
||||
gpointer data)
|
||||
@@ -1058,7 +1043,6 @@ meta_prefs_init (void)
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
gchar **gconf_dir_cursor;
|
||||
MetaPluginManager *plugin_manager;
|
||||
|
||||
if (default_client != NULL)
|
||||
return;
|
||||
@@ -1077,19 +1061,6 @@ meta_prefs_init (void)
|
||||
cleanup_error (&err);
|
||||
}
|
||||
|
||||
/* The plugin list is special and needs to be handled first */
|
||||
|
||||
if (!clutter_plugins_overridden)
|
||||
clutter_plugins = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
|
||||
GCONF_VALUE_STRING, &err);
|
||||
|
||||
cleanup_error (&err);
|
||||
|
||||
/* We now initialize plugins so that they can override any preference locations */
|
||||
|
||||
plugin_manager = meta_plugin_manager_get_default ();
|
||||
meta_plugin_manager_load (plugin_manager);
|
||||
|
||||
/* Pick up initial values. */
|
||||
|
||||
handle_preference_init_enum ();
|
||||
@@ -1097,6 +1068,14 @@ meta_prefs_init (void)
|
||||
handle_preference_init_string ();
|
||||
handle_preference_init_int ();
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
if (!clutter_plugins_overridden)
|
||||
clutter_plugins = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
|
||||
GCONF_VALUE_STRING, &err);
|
||||
|
||||
cleanup_error (&err);
|
||||
#endif
|
||||
|
||||
/* @@@ Is there any reason we don't do the add_dir here? */
|
||||
for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
|
||||
*gconf_dir_cursor!=NULL;
|
||||
@@ -1129,160 +1108,6 @@ meta_prefs_init (void)
|
||||
init_workspace_names ();
|
||||
}
|
||||
|
||||
/* This count on the key being the first element of the
|
||||
* preference structure */
|
||||
static gboolean
|
||||
key_is_used (void *prefs,
|
||||
size_t pref_size,
|
||||
const char *new_key)
|
||||
{
|
||||
void *p = prefs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char **key = p;
|
||||
if (*key == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp (*key, new_key) == 0)
|
||||
return TRUE;
|
||||
|
||||
p = (guchar *)p + pref_size;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_override (void *prefs,
|
||||
size_t pref_size,
|
||||
const char *search_key,
|
||||
char *new_key)
|
||||
{
|
||||
void *p = prefs;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char **key = p;
|
||||
if (*key == NULL)
|
||||
break;
|
||||
|
||||
if (strcmp (*key, search_key) == 0)
|
||||
{
|
||||
*key = new_key;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
p = (guchar *)p + pref_size;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_override_preference_location
|
||||
* @original_key: the normal Metacity preference location
|
||||
* @new_key: the Metacity preference location to use instead.
|
||||
*
|
||||
* Substitute a different location to use instead of a standard Metacity
|
||||
* GConf key location. This might be used if a plugin expected a different
|
||||
* value for some preference than the Metacity default. While this function
|
||||
* can be called at any point, this function should generally be called
|
||||
* in a plugin's constructor, rather than in its start() method so the
|
||||
* preference isn't first loaded with one value then changed to another
|
||||
* value.
|
||||
*/
|
||||
void
|
||||
meta_prefs_override_preference_location (const char *original_key,
|
||||
const char *new_key)
|
||||
{
|
||||
const char *search_key;
|
||||
char *new_key_copy;
|
||||
gboolean found;
|
||||
MetaPrefsOverriddenKey *overridden;
|
||||
GSList *tmp;
|
||||
|
||||
/* Merge identical overrides, this isn't an error */
|
||||
for (tmp = overridden_keys; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
|
||||
if (strcmp (tmp_overridden->original_key, original_key) == 0 &&
|
||||
strcmp (tmp_overridden->new_key, new_key) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We depend on a unique mapping from GConf key to preference, so
|
||||
* enforce this */
|
||||
|
||||
if (key_is_used (preferences_enum, sizeof(MetaEnumPreference), new_key) ||
|
||||
key_is_used (preferences_bool, sizeof(MetaBoolPreference), new_key) ||
|
||||
key_is_used (preferences_string, sizeof(MetaStringPreference), new_key) ||
|
||||
key_is_used (preferences_int, sizeof(MetaIntPreference), new_key))
|
||||
{
|
||||
meta_warning (_("GConf key %s is already in use and can't be used to override %s\n"),
|
||||
new_key, original_key);
|
||||
|
||||
}
|
||||
|
||||
new_key_copy = g_strdup (new_key);
|
||||
|
||||
search_key = original_key;
|
||||
overridden = NULL;
|
||||
|
||||
for (tmp = overridden_keys; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
|
||||
if (strcmp (overridden->original_key, original_key) == 0)
|
||||
{
|
||||
overridden = tmp_overridden;
|
||||
search_key = tmp_overridden->new_key;
|
||||
}
|
||||
}
|
||||
|
||||
found =
|
||||
do_override (preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
|
||||
do_override (preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
|
||||
if (found)
|
||||
{
|
||||
if (overridden)
|
||||
{
|
||||
g_free (overridden->new_key);
|
||||
overridden->new_key = new_key_copy;
|
||||
}
|
||||
else
|
||||
{
|
||||
overridden = g_slice_new (MetaPrefsOverriddenKey);
|
||||
overridden->original_key = g_strdup (original_key);
|
||||
overridden->new_key = new_key_copy;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
if (default_client != NULL)
|
||||
{
|
||||
/* We're already initialized, so notify of a change */
|
||||
|
||||
GConfValue *value;
|
||||
GError *err = NULL;
|
||||
|
||||
value = gconf_client_get (default_client, new_key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
notify_new_value (new_key, value);
|
||||
|
||||
if (value)
|
||||
gconf_value_free (value);
|
||||
}
|
||||
#endif /* HAVE_GCONF */
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Can't override GConf key, %s not found\n"), original_key);
|
||||
g_free (new_key_copy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Updates. */
|
||||
@@ -1298,23 +1123,6 @@ gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
notify_new_value (const char *key,
|
||||
GConfValue *value)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* FIXME: Use MetaGenericPreference and save a bit of code duplication */
|
||||
|
||||
while (preference_update_handler[i] != NULL)
|
||||
{
|
||||
if (preference_update_handler[i] (key, value))
|
||||
return;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
change_notify (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
@@ -1323,13 +1131,25 @@ change_notify (GConfClient *client,
|
||||
{
|
||||
const char *key;
|
||||
GConfValue *value;
|
||||
gint i=0;
|
||||
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
|
||||
/* First, search for a handler that might know what to do. */
|
||||
|
||||
notify_new_value (key, value);
|
||||
/* FIXME: When this is all working, since the first item in every
|
||||
* array is the gchar* of the key, there's no reason we can't
|
||||
* find the correct record for that key here and save code duplication.
|
||||
*/
|
||||
|
||||
while (preference_update_handler[i]!=NULL)
|
||||
{
|
||||
if (preference_update_handler[i] (key, value))
|
||||
goto out; /* Get rid of this eventually */
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX) ||
|
||||
g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
|
||||
@@ -1347,7 +1167,7 @@ change_notify (GConfClient *client,
|
||||
|
||||
list = value ? gconf_value_get_list (value) : NULL;
|
||||
|
||||
if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
|
||||
if (update_key_list_binding (key, list))
|
||||
queue_changed (META_PREF_KEYBINDINGS);
|
||||
}
|
||||
else
|
||||
@@ -1403,6 +1223,7 @@ change_notify (GConfClient *client,
|
||||
{
|
||||
queue_changed (META_PREF_KEYBINDINGS);
|
||||
}
|
||||
#ifdef WITH_CLUTTER
|
||||
else if (g_str_equal (key, KEY_CLUTTER_PLUGINS) && !clutter_plugins_overridden)
|
||||
{
|
||||
GError *err = NULL;
|
||||
@@ -1420,6 +1241,7 @@ change_notify (GConfClient *client,
|
||||
clutter_plugins = l;
|
||||
queue_changed (META_PREF_CLUTTER_PLUGINS);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Mutter\n",
|
||||
@@ -1505,12 +1327,6 @@ meta_prefs_get_focus_new_windows (void)
|
||||
return focus_new_windows;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_attach_modal_dialogs (void)
|
||||
{
|
||||
return attach_modal_dialogs;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_raise_on_click (void)
|
||||
{
|
||||
@@ -1932,9 +1748,6 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_FOCUS_NEW_WINDOWS:
|
||||
return "FOCUS_NEW_WINDOWS";
|
||||
|
||||
case META_PREF_ATTACH_MODAL_DIALOGS:
|
||||
return "ATTACH_MODAL_DIALOGS";
|
||||
|
||||
case META_PREF_RAISE_ON_CLICK:
|
||||
return "RAISE_ON_CLICK";
|
||||
|
||||
@@ -1992,6 +1805,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_VISUAL_BELL_TYPE:
|
||||
return "VISUAL_BELL_TYPE";
|
||||
|
||||
case META_PREF_REDUCED_RESOURCES:
|
||||
return "REDUCED_RESOURCES";
|
||||
|
||||
case META_PREF_GNOME_ACCESSIBILITY:
|
||||
return "GNOME_ACCESSIBILTY";
|
||||
|
||||
@@ -2009,19 +1825,14 @@ meta_preference_to_string (MetaPreference pref)
|
||||
|
||||
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
|
||||
return "RESIZE_WITH_RIGHT_BUTTON";
|
||||
|
||||
case META_PREF_SIDE_BY_SIDE_TILING:
|
||||
return "SIDE_BY_SIDE_TILING";
|
||||
|
||||
case META_PREF_FORCE_FULLSCREEN:
|
||||
return "FORCE_FULLSCREEN";
|
||||
|
||||
#ifdef WITH_CLUTTER
|
||||
case META_PREF_CLUTTER_DISABLED:
|
||||
return "CLUTTER_DISABLED";
|
||||
case META_PREF_CLUTTER_PLUGINS:
|
||||
return "CLUTTER_PLUGINS";
|
||||
|
||||
#endif
|
||||
case META_PREF_LIVE_HIDDEN_WINDOWS:
|
||||
return "LIVE_HIDDEN_WINDOWS";
|
||||
|
||||
case META_PREF_NO_TAB_POPUP:
|
||||
return "NO_TAB_POPUP";
|
||||
}
|
||||
@@ -2104,66 +1915,57 @@ init_special_bindings (void)
|
||||
static void
|
||||
init_bindings (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
const char *prefix[] = {
|
||||
KEY_WINDOW_BINDINGS_PREFIX,
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
GSList *list, *l, *list_val;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
GHashTable *to_update;
|
||||
#ifdef HAVE_GCONF
|
||||
int i = 0;
|
||||
GError *err;
|
||||
|
||||
g_assert (G_N_ELEMENTS (key_bindings) == META_KEYBINDING_ACTION_LAST + 1);
|
||||
|
||||
to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
|
||||
for (i = 0; prefix[i]; i++)
|
||||
{
|
||||
list = gconf_client_all_entries (default_client, prefix[i], NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
|
||||
{
|
||||
/* List bindings are used in addition to the normal bindings and never
|
||||
* have defaults, so we just go ahead and set them immediately; there
|
||||
* will be only a few of them, so don't worry about the linear scan
|
||||
* in find_and_update_list_binding.
|
||||
*/
|
||||
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, NULL);
|
||||
|
||||
update_key_list_binding (key, list_val, META_LIST_OF_STRINGS);
|
||||
g_slist_foreach (list_val, (GFunc)g_free, NULL);
|
||||
g_slist_free (list_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
str_val = gconf_value_get_string (value);
|
||||
g_hash_table_insert (to_update, binding_name (key), g_strdup (str_val));
|
||||
}
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (key_bindings[i].name)
|
||||
{
|
||||
update_binding (&key_bindings[i],
|
||||
g_hash_table_lookup (to_update, key_bindings[i].name));
|
||||
GSList *list_val, *tmp;
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = g_strconcat (key_bindings[i].per_window?
|
||||
KEY_WINDOW_BINDINGS_PREFIX:
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
"/",
|
||||
key_bindings[i].name, NULL);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_binding (&key_bindings[i], str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
key = g_strconcat (key_bindings[i].per_window?
|
||||
KEY_WINDOW_BINDINGS_PREFIX:
|
||||
KEY_SCREEN_BINDINGS_PREFIX,
|
||||
"/",
|
||||
key_bindings[i].name,
|
||||
KEY_LIST_BINDINGS_SUFFIX, NULL);
|
||||
|
||||
err = NULL;
|
||||
|
||||
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_list_binding (&key_bindings[i], list_val, META_LIST_OF_STRINGS);
|
||||
|
||||
tmp = list_val;
|
||||
while (tmp)
|
||||
{
|
||||
g_free (tmp->data);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
g_slist_free (list_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
g_hash_table_destroy (to_update);
|
||||
|
||||
#else /* HAVE_GCONF */
|
||||
int i = 0;
|
||||
while (key_bindings[i].name)
|
||||
@@ -2185,23 +1987,28 @@ static void
|
||||
init_commands (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GSList *list, *l;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
|
||||
list = gconf_client_all_entries (default_client, KEY_COMMAND_DIRECTORY, NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_COMMANDS)
|
||||
{
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
str_val = gconf_value_get_string (value);
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = meta_prefs_get_gconf_key_for_command (i);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_command (key, str_val);
|
||||
gconf_entry_free (entry);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
}
|
||||
g_slist_free (list);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_COMMANDS; i++)
|
||||
@@ -2212,34 +2019,39 @@ init_commands (void)
|
||||
static void
|
||||
init_workspace_names (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
GSList *list, *l;
|
||||
const char *str_val;
|
||||
const char *key;
|
||||
GConfEntry *entry;
|
||||
GConfValue *value;
|
||||
|
||||
list = gconf_client_all_entries (default_client, KEY_WORKSPACE_NAME_DIRECTORY, NULL);
|
||||
for (l = list; l; l = l->next)
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_REASONABLE_WORKSPACES)
|
||||
{
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
str_val = gconf_value_get_string (value);
|
||||
update_workspace_name (key, str_val);
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
#endif /* HAVE_GCONF */
|
||||
char *str_val;
|
||||
char *key;
|
||||
|
||||
key = gconf_key_for_workspace_name (i);
|
||||
|
||||
err = NULL;
|
||||
str_val = gconf_client_get_string (default_client, key, &err);
|
||||
cleanup_error (&err);
|
||||
|
||||
update_workspace_name (key, str_val);
|
||||
|
||||
g_assert (workspace_names[i] != NULL);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
|
||||
if (workspace_names[i] == NULL)
|
||||
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
|
||||
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
|
||||
|
||||
meta_topic (META_DEBUG_PREFS,
|
||||
"Initialized workspace names\n");
|
||||
#endif /* HAVE_GCONF */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2490,22 +2302,16 @@ update_list_binding (MetaKeyPref *binding,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static char *
|
||||
binding_name (const char *gconf_key)
|
||||
static const gchar*
|
||||
relative_key (const gchar* key)
|
||||
{
|
||||
const char *start, *end;
|
||||
const gchar* end;
|
||||
|
||||
end = strrchr (key, '/');
|
||||
|
||||
if (*gconf_key == '/')
|
||||
start = strrchr (gconf_key, '/') + 1;
|
||||
else
|
||||
start = gconf_key;
|
||||
++end;
|
||||
|
||||
if (g_str_has_suffix (gconf_key, KEY_LIST_BINDINGS_SUFFIX))
|
||||
end = gconf_key + strlen(gconf_key) - strlen (KEY_LIST_BINDINGS_SUFFIX);
|
||||
else
|
||||
end = gconf_key + strlen(gconf_key);
|
||||
|
||||
return g_strndup (start, end - start);
|
||||
return end;
|
||||
}
|
||||
|
||||
/* Return value is TRUE if a preference changed and we need to
|
||||
@@ -2513,19 +2319,22 @@ binding_name (const char *gconf_key)
|
||||
*/
|
||||
static gboolean
|
||||
find_and_update_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
const char *name,
|
||||
const char *value)
|
||||
{
|
||||
char *name = binding_name (key);
|
||||
const char *key;
|
||||
int i;
|
||||
|
||||
if (*name == '/')
|
||||
key = relative_key (name);
|
||||
else
|
||||
key = name;
|
||||
|
||||
i = 0;
|
||||
while (bindings[i].name &&
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
strcmp (key, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_binding (&bindings[i], value);
|
||||
else
|
||||
@@ -2533,40 +2342,46 @@ find_and_update_binding (MetaKeyPref *bindings,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_binding (const char *key,
|
||||
const char *value)
|
||||
update_key_binding (const char *name,
|
||||
const char *value)
|
||||
{
|
||||
return find_and_update_binding (key_bindings, key, value);
|
||||
return find_and_update_binding (key_bindings, name, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
GSList *value)
|
||||
{
|
||||
char *name = binding_name (key);
|
||||
const char *key;
|
||||
int i;
|
||||
gchar *name_without_suffix = g_strdup(name);
|
||||
|
||||
name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
|
||||
|
||||
if (*name_without_suffix == '/')
|
||||
key = relative_key (name_without_suffix);
|
||||
else
|
||||
key = name_without_suffix;
|
||||
|
||||
i = 0;
|
||||
while (bindings[i].name &&
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
strcmp (key, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name);
|
||||
g_free (name_without_suffix);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_list_binding (&bindings[i], value, type_of_value);
|
||||
return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_list_binding (const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
update_key_list_binding (const char *name,
|
||||
GSList *value)
|
||||
{
|
||||
return find_and_update_list_binding (key_bindings, key, value, type_of_value);
|
||||
return find_and_update_list_binding (key_bindings, name, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -2913,6 +2728,12 @@ meta_prefs_get_auto_raise_delay (void)
|
||||
return auto_raise_delay;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_reduced_resources (void)
|
||||
{
|
||||
return reduced_resources;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_gnome_accessibility ()
|
||||
{
|
||||
@@ -2925,12 +2746,6 @@ meta_prefs_get_gnome_animations ()
|
||||
return gnome_animations;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_side_by_side_tiling ()
|
||||
{
|
||||
return side_by_side_tiling;
|
||||
}
|
||||
|
||||
MetaKeyBindingAction
|
||||
meta_prefs_get_keybinding_action (const char *name)
|
||||
{
|
||||
@@ -3010,12 +2825,6 @@ meta_prefs_get_mouse_button_menu (void)
|
||||
return resize_with_right_button ? 2: 3;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_force_fullscreen (void)
|
||||
{
|
||||
return force_fullscreen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_compositing_manager (gboolean whether)
|
||||
{
|
||||
@@ -3038,11 +2847,35 @@ meta_prefs_set_compositing_manager (gboolean whether)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_clutter_plugins:
|
||||
*
|
||||
* Returns: (transfer none) (element-type utf8): Plugin names to load
|
||||
*/
|
||||
#ifdef WITH_CLUTTER
|
||||
gboolean
|
||||
meta_prefs_get_clutter_disabled (void)
|
||||
{
|
||||
return clutter_disabled;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_clutter_disabled (gboolean whether)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
|
||||
gconf_client_set_bool (default_client,
|
||||
KEY_CLUTTER_DISABLED,
|
||||
whether,
|
||||
&err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
meta_warning (_("Error setting clutter status status: %s\n"),
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
#else
|
||||
clutter_disabled = whether;
|
||||
#endif
|
||||
}
|
||||
|
||||
GSList *
|
||||
meta_prefs_get_clutter_plugins (void)
|
||||
{
|
||||
@@ -3052,7 +2885,6 @@ meta_prefs_get_clutter_plugins (void)
|
||||
void
|
||||
meta_prefs_set_clutter_plugins (GSList *list)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
|
||||
gconf_client_set_list (default_client,
|
||||
@@ -3067,7 +2899,6 @@ meta_prefs_set_clutter_plugins (GSList *list)
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3083,6 +2914,7 @@ meta_prefs_override_clutter_plugins (GSList *list)
|
||||
|
||||
clutter_plugins = g_slist_reverse (clutter_plugins);
|
||||
}
|
||||
#endif
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_live_hidden_windows (void)
|
||||
@@ -3188,10 +3020,3 @@ init_button_layout(void)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_prefs_set_force_fullscreen (gboolean whether)
|
||||
{
|
||||
force_fullscreen = whether;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,12 @@
|
||||
#include "screen.h"
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "alttabhandler.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo;
|
||||
|
||||
struct _MetaMonitorInfo
|
||||
struct _MetaXineramaScreenInfo
|
||||
{
|
||||
int number;
|
||||
MetaRectangle rect;
|
||||
@@ -81,11 +82,9 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
MetaTilePreview *tile_preview;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
MetaAltTabHandler *tab_handler;
|
||||
MetaTabPopup *ws_popup;
|
||||
|
||||
MetaWorkspace *active_workspace;
|
||||
|
||||
/* This window holds the focus when we don't want to focus
|
||||
@@ -106,11 +105,11 @@ struct _MetaScreen
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int n_monitor_infos;
|
||||
MetaXineramaScreenInfo *xinerama_infos;
|
||||
int n_xinerama_infos;
|
||||
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
/* Cache the current Xinerama */
|
||||
int last_xinerama_index;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
SnMonitorContext *sn_context;
|
||||
@@ -118,10 +117,11 @@ struct _MetaScreen
|
||||
guint startup_sequence_timeout;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
Window wm_cm_selection_window;
|
||||
guint32 wm_cm_timestamp;
|
||||
#endif
|
||||
|
||||
guint work_area_later;
|
||||
guint work_area_idle;
|
||||
|
||||
int rows_of_workspaces;
|
||||
int columns_of_workspaces;
|
||||
@@ -133,6 +133,9 @@ struct _MetaScreen
|
||||
|
||||
int closing;
|
||||
|
||||
/* gc for XOR on root window */
|
||||
GC root_xor_gc;
|
||||
|
||||
/* Managed by compositor.c */
|
||||
gpointer compositor_data;
|
||||
|
||||
@@ -146,8 +149,7 @@ struct _MetaScreenClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*restacked) (MetaScreen *);
|
||||
void (*workareas_changed) (MetaScreen *);
|
||||
void (*restacked) (MetaScreen *);
|
||||
};
|
||||
|
||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||
@@ -182,25 +184,22 @@ void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor (MetaScreen *screen);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
MetaWindow *window);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen,
|
||||
MetaWindow *window);
|
||||
|
||||
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,
|
||||
int which_monitor,
|
||||
MetaScreenDirection dir);
|
||||
void meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
int** monitors_list,
|
||||
int* n_monitors);
|
||||
const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen,
|
||||
int which_xinerama,
|
||||
MetaScreenDirection dir);
|
||||
void meta_screen_get_natural_xinerama_list (MetaScreen *screen,
|
||||
int** xineramas_list,
|
||||
int* n_xineramas);
|
||||
|
||||
void meta_screen_update_workspace_layout (MetaScreen *screen);
|
||||
void meta_screen_update_workspace_names (MetaScreen *screen);
|
||||
@@ -249,9 +248,4 @@ void meta_screen_composite_all_windows (MetaScreen *screen);
|
||||
|
||||
void meta_screen_restacked (MetaScreen *screen);
|
||||
|
||||
void meta_screen_workspace_switched (MetaScreen *screen,
|
||||
int from,
|
||||
int to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,6 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifndef HAVE_SM
|
||||
void
|
||||
@@ -84,7 +83,6 @@ static char* load_state (const char *previous_save_file);
|
||||
static void regenerate_save_file (void);
|
||||
static const char* full_save_file (void);
|
||||
static void warn_about_lame_clients_and_finish_interact (gboolean shutdown);
|
||||
static void disconnect (void);
|
||||
|
||||
/* This is called when data is available on an ICE connection. */
|
||||
static gboolean
|
||||
@@ -107,12 +105,9 @@ process_ice_messages (GIOChannel *channel,
|
||||
IcePointer context = IceGetConnectionContext (connection);
|
||||
#endif
|
||||
|
||||
/* We were disconnected; close our connection to the
|
||||
* session manager, this will result in the ICE connection
|
||||
* being cleaned up, since it is owned by libSM.
|
||||
*/
|
||||
disconnect ();
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
/* We were disconnected */
|
||||
IceSetShutdownNegotiation (connection, False);
|
||||
IceCloseConnection (connection);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -894,7 +889,7 @@ save_state (void)
|
||||
fprintf (outfile, "<mutter_session id=\"%s\">\n",
|
||||
client_id);
|
||||
|
||||
windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT);
|
||||
windows = meta_display_list_windows (meta_get_display ());
|
||||
stack_position = 0;
|
||||
|
||||
windows = g_slist_sort (windows, meta_display_stack_cmp);
|
||||
@@ -1109,6 +1104,8 @@ load_state (const char *previous_save_file)
|
||||
{
|
||||
/* oh, just give up */
|
||||
|
||||
meta_warning (_("Failed to read saved session file %s: %s\n"),
|
||||
canonical_session_file, error->message);
|
||||
g_error_free (error);
|
||||
g_free (session_file);
|
||||
g_free (canonical_session_file);
|
||||
@@ -1752,11 +1749,11 @@ finish_interact (gboolean shutdown)
|
||||
}
|
||||
|
||||
static void
|
||||
dialog_closed (GPid pid, int status, gpointer user_data)
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
{
|
||||
gboolean shutdown = GPOINTER_TO_INT (user_data);
|
||||
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 0) /* pressed "OK" */
|
||||
if (arg1 == 0) /* pressed "OK" */
|
||||
{
|
||||
finish_interact (shutdown);
|
||||
}
|
||||
@@ -1770,9 +1767,8 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||
GSList *lame_details = NULL;
|
||||
GSList *tmp;
|
||||
GSList *columns = NULL;
|
||||
GPid pid;
|
||||
|
||||
windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT);
|
||||
windows = meta_display_list_windows (meta_get_display ());
|
||||
tmp = windows;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
@@ -1818,20 +1814,23 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||
}
|
||||
g_slist_free (lame);
|
||||
|
||||
pid = meta_show_dialog("--list",
|
||||
_("These windows do not support "save current setup" "
|
||||
"and will have to be restarted manually next time "
|
||||
"you log in."),
|
||||
"240",
|
||||
meta_screen_get_screen_number (meta_get_display()->active_screen),
|
||||
NULL, NULL,
|
||||
None,
|
||||
columns,
|
||||
lame_details);
|
||||
meta_show_dialog("--list",
|
||||
_("These windows do not support "save current setup" "
|
||||
"and will have to be restarted manually next time "
|
||||
"you log in."),
|
||||
"240",
|
||||
meta_screen_get_screen_number (meta_get_display()->active_screen),
|
||||
NULL, NULL,
|
||||
None,
|
||||
columns,
|
||||
lame_details);
|
||||
|
||||
g_slist_free (lame_details);
|
||||
|
||||
g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown));
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
GINT_TO_POINTER (shutdown));
|
||||
|
||||
}
|
||||
|
||||
#endif /* HAVE_SM */
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "frame-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "stack-tracker.h"
|
||||
#include "util.h"
|
||||
@@ -135,7 +134,7 @@ struct _MetaStackTracker
|
||||
/* Idle function used to sync the compositor's view of the window
|
||||
* stack up with our best guess before a frame is drawn.
|
||||
*/
|
||||
guint sync_stack_later;
|
||||
guint sync_stack_idle;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -384,8 +383,8 @@ meta_stack_tracker_new (MetaScreen *screen)
|
||||
void
|
||||
meta_stack_tracker_free (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_later)
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
if (tracker->sync_stack_idle)
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
|
||||
g_array_free (tracker->server_stack, TRUE);
|
||||
if (tracker->predicted_stack)
|
||||
@@ -668,10 +667,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
if (tracker->sync_stack_later)
|
||||
if (tracker->sync_stack_idle)
|
||||
{
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
tracker->sync_stack_later = 0;
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
tracker->sync_stack_idle = 0;
|
||||
}
|
||||
|
||||
meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
|
||||
@@ -683,29 +682,20 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
|
||||
meta_window = meta_display_lookup_x_window (tracker->screen->display,
|
||||
windows[i]);
|
||||
/* When mapping back from xwindow to MetaWindow we have to be a bit careful;
|
||||
* children of the root could include unmapped windows created by toolkits
|
||||
* for internal purposes, including ones that we have registered in our
|
||||
* XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
|
||||
* see window-prop.c:reload_net_wm_user_time_window() for registration.)
|
||||
*/
|
||||
if (meta_window &&
|
||||
(windows[i] == meta_window->xwindow ||
|
||||
(meta_window->frame && windows[i] == meta_window->frame->xwindow)))
|
||||
if (meta_window)
|
||||
meta_windows = g_list_prepend (meta_windows, meta_window);
|
||||
}
|
||||
|
||||
if (tracker->screen->display->compositor)
|
||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||
tracker->screen,
|
||||
meta_windows);
|
||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||
tracker->screen,
|
||||
meta_windows);
|
||||
g_list_free (meta_windows);
|
||||
|
||||
meta_screen_restacked (tracker->screen);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stack_tracker_sync_stack_later (gpointer data)
|
||||
stack_tracker_sync_stack_idle (gpointer data)
|
||||
{
|
||||
meta_stack_tracker_sync_stack (data);
|
||||
|
||||
@@ -728,10 +718,10 @@ stack_tracker_sync_stack_later (gpointer data)
|
||||
void
|
||||
meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_later == 0)
|
||||
if (tracker->sync_stack_idle == 0)
|
||||
{
|
||||
tracker->sync_stack_later = meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_later,
|
||||
tracker->sync_stack_idle = g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_idle,
|
||||
tracker, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,14 +224,14 @@ is_focused_foreach (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
windows_on_different_monitor (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
windows_on_different_xinerama (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
{
|
||||
if (a->screen != b->screen)
|
||||
return TRUE;
|
||||
|
||||
return meta_screen_get_monitor_for_window (a->screen, a) !=
|
||||
meta_screen_get_monitor_for_window (b->screen, b);
|
||||
return meta_screen_get_xinerama_for_window (a->screen, a) !=
|
||||
meta_screen_get_xinerama_for_window (b->screen, b);
|
||||
}
|
||||
|
||||
/* Get layer ignoring any transient or group relationships */
|
||||
@@ -241,6 +241,12 @@ get_standalone_layer (MetaWindow *window)
|
||||
MetaStackLayer layer;
|
||||
gboolean focused_transient = FALSE;
|
||||
|
||||
if (window->hidden)
|
||||
{
|
||||
layer = META_LAYER_DESKTOP;
|
||||
return layer;
|
||||
}
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
case META_WINDOW_DESKTOP:
|
||||
@@ -275,8 +281,8 @@ get_standalone_layer (MetaWindow *window)
|
||||
window == window->display->expected_focus_window ||
|
||||
window->display->expected_focus_window == NULL ||
|
||||
(window->display->expected_focus_window != NULL &&
|
||||
windows_on_different_monitor (window,
|
||||
window->display->expected_focus_window))))
|
||||
windows_on_different_xinerama (window,
|
||||
window->display->expected_focus_window))))
|
||||
layer = META_LAYER_FULLSCREEN;
|
||||
else if (window->wm_state_above)
|
||||
layer = META_LAYER_TOP;
|
||||
@@ -1026,7 +1032,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (screen->display);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1046,7 +1052,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
XLowerWindow (screen->display->xdisplay,
|
||||
xwindow);
|
||||
meta_error_trap_pop (screen->display);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,7 +1273,7 @@ stack_sync_to_server (MetaStack *stack)
|
||||
all_hidden->len);
|
||||
g_array_free (all_hidden, TRUE);
|
||||
|
||||
meta_error_trap_pop (stack->screen->display);
|
||||
meta_error_trap_pop (stack->screen->display, FALSE);
|
||||
/* on error, a window was destroyed; it should eventually
|
||||
* get removed from the stacking list when we unmanage it
|
||||
* and we'll fix stacking at that time.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user