Compare commits
319 Commits
Author | SHA1 | Date | |
---|---|---|---|
2d57904bf4 | |||
8fa83e1be7 | |||
8875e73765 | |||
65766fcaac | |||
4cd4010a70 | |||
d21da5643b | |||
ba700e6387 | |||
bd90fd7033 | |||
fb3d352d3a | |||
690852e157 | |||
aa84d21bcf | |||
4d62977c7b | |||
cbac2e7bbb | |||
88ee4c5b30 | |||
12c46c5d8b | |||
ab7d4e0e60 | |||
708c6162c4 | |||
7834bba6f7 | |||
857c8aaaa2 | |||
1253e6c64e | |||
b610b2ecc7 | |||
11addbe9c8 | |||
709ef05714 | |||
c51767eef1 | |||
5aab9e878f | |||
e7751e170e | |||
776d345bc3 | |||
a8fc30a13f | |||
2d57b1b470 | |||
90f21fa5db | |||
6638d0e507 | |||
c6793d477a | |||
11e01ec074 | |||
1d827caaaf | |||
ba4db78ed9 | |||
a321f4c842 | |||
b1c465eab0 | |||
5134b05af9 | |||
dc3a93be99 | |||
49aabfec02 | |||
11d0d207fd | |||
eed3245b1b | |||
a7bbde1699 | |||
bacccafe3c | |||
3a80bd47cc | |||
152917d5e1 | |||
c588e173f8 | |||
c0d2ead351 | |||
6ffe5f8343 | |||
2a823ef3e4 | |||
5159c3f3ca | |||
d092924961 | |||
e14132b826 | |||
df36ff638e | |||
ad1fee8233 | |||
3883d511a9 | |||
10803b0d25 | |||
a570a57863 | |||
a7590f9717 | |||
35224ca8d4 | |||
40563e4f84 | |||
c30901e9be | |||
4fc0a91b31 | |||
576417648a | |||
0aace5230f | |||
8d5ba7a6d7 | |||
f8153b84de | |||
fac5b0c9e7 | |||
eb06413188 | |||
066c870271 | |||
1a92fa788d | |||
3a0ab1cc0c | |||
8a7d588bb0 | |||
4943d79d68 | |||
5de10c34b7 | |||
2fbe4c2388 | |||
767cb27f78 | |||
b8c75c3fc0 | |||
edeadf62ef | |||
5ac80057c4 | |||
210e30556e | |||
0487b4213f | |||
8f29c14ac4 | |||
9543d8be10 | |||
43e0003e79 | |||
30e63a7244 | |||
575f520461 | |||
df618c9e91 | |||
ebd13a4bae | |||
7aa54b5a23 | |||
b20cb36f5d | |||
86f8c1863e | |||
19d85c8566 | |||
4241f91a0a | |||
05624f099a | |||
920f4099b6 | |||
aa26750e01 | |||
bdb3be7084 | |||
14987f2b21 | |||
47af6a0bbf | |||
1487578ff4 | |||
5a03a5d578 | |||
2dd137329d | |||
db37deb589 | |||
ec7a3c516d | |||
988d2ffab6 | |||
5e2c66e241 | |||
0ccfb0d781 | |||
01ce961c00 | |||
7579b691df | |||
2a14deab0c | |||
1acefb9eac | |||
fb45b8f45c | |||
d59a9c2e8a | |||
a1c3d8723d | |||
c4bd65e97c | |||
eac3a2d7ac | |||
55bb584778 | |||
4584943531 | |||
55d2bc0e0b | |||
c0cc2fa1b8 | |||
c1ecbd4de1 | |||
0fb6b8a8ff | |||
78ba9adfed | |||
3f642ea34f | |||
1a3927b40c | |||
b09d73ab68 | |||
9311addca3 | |||
3c76478510 | |||
545551e2bc | |||
d5e0a95ff1 | |||
e811109566 | |||
0f805bfdfb | |||
200cd629df | |||
e8a29c1e82 | |||
8589e4f3d3 | |||
948e54772d | |||
2d4b05a71b | |||
a6433e84f5 | |||
083854e2de | |||
3508c4aa87 | |||
d04b15ee25 | |||
d6143e4c73 | |||
d8ffc3c187 | |||
2af788956e | |||
d399141d13 | |||
f6f899f103 | |||
5b8919a246 | |||
fe1989979c | |||
0895fa9331 | |||
b90fe0c52a | |||
ab0e22159c | |||
6ac0afbce0 | |||
9532527e52 | |||
defdf9f34c | |||
a7dce2dc4e | |||
ea8c51f8f3 | |||
1e66878447 | |||
6cfbdebf6a | |||
a4469dcc14 | |||
ac3eac7154 | |||
65ac9065fa | |||
5143e6763b | |||
5660a8e9f5 | |||
bc2b17df0b | |||
f9e7c95348 | |||
c6afec4759 | |||
eb13498fff | |||
163057f521 | |||
d8ff1f9873 | |||
97b7760de8 | |||
acca0f6946 | |||
f3f6d67d46 | |||
63773d5226 | |||
4e4559fc8c | |||
44d540d36c | |||
c6253a6515 | |||
65a5ec2ef3 | |||
70e8b35944 | |||
ddba25a674 | |||
14e6cb6a8f | |||
d4619150f3 | |||
5c1a1a2dd5 | |||
7cfa690aaf | |||
8d663ff055 | |||
0b86343dd0 | |||
e127898312 | |||
51f83f25e6 | |||
8f3da9f68a | |||
4c1998f137 | |||
84dc1c1b85 | |||
326110e38d | |||
f63b81c52a | |||
bd2e221da3 | |||
1fe673703f | |||
c10467d22e | |||
e21ec0a271 | |||
3a1e492afc | |||
e83c24c91b | |||
81183c71c1 | |||
979298ce57 | |||
66e727e1b2 | |||
35b1dda3a3 | |||
6925779f59 | |||
125d7daf4a | |||
57c5ea4bd5 | |||
e75fbdb136 | |||
cb1020b26d | |||
e1945506f3 | |||
3a798112f2 | |||
c5dd3e5542 | |||
2fa9cbfd9e | |||
23af4ee93e | |||
0317562605 | |||
1861e0b2cc | |||
e5974809e8 | |||
abfae17b9a | |||
84b1a62ad2 | |||
b6bcaec9bc | |||
f19ed84cc4 | |||
6c5a946fda | |||
c6ffc9427e | |||
0f1e64f3b2 | |||
1ce5ad3003 | |||
64694955c0 | |||
97a90d8122 | |||
3cd2c08277 | |||
c37a2ca1c8 | |||
80b38210b2 | |||
e5dffb0097 | |||
deaa897928 | |||
3f9758e706 | |||
3c25c265df | |||
a8529bd8d1 | |||
ba03ca76c4 | |||
71fd54ec9e | |||
a03343827e | |||
4fb7c642d5 | |||
8a892d47e5 | |||
73abacc20b | |||
aea24279ba | |||
5c5968e742 | |||
3813ed9c2e | |||
594897e9a5 | |||
40e9f6fa2c | |||
35afd2a8fb | |||
d9be1d7e32 | |||
b625ec30d9 | |||
f5313268d7 | |||
07dedee37b | |||
75f3127ba5 | |||
b13fae2556 | |||
2e9838699b | |||
ba9c3f41c9 | |||
e35fae8f32 | |||
b0d5f3bd64 | |||
ed640bb181 | |||
a3511ba9e2 | |||
4c9c903648 | |||
d12aaddc34 | |||
28955bb449 | |||
dcd7cae7cf | |||
c954bb9456 | |||
be0b298d81 | |||
409026044b | |||
0c311bdcf9 | |||
e81775e63d | |||
209d7ef613 | |||
a6c76a85ce | |||
265f9e5433 | |||
b86d988b3c | |||
c4148cec33 | |||
aa57becc41 | |||
7269c37c8f | |||
3093d7e95a | |||
4e0d8a0cbb | |||
523151ddf0 | |||
0a7cb94ea8 | |||
d4b7c0e633 | |||
3f76affbd2 | |||
a8f8970601 | |||
178b5ff626 | |||
c47f7c2806 | |||
ab6aa5463f | |||
42387bff6f | |||
3afd25691a | |||
a6a963bec1 | |||
d6ac4dc22a | |||
0b3f45bb1b | |||
24f2df926a | |||
f00e8655ac | |||
41395d9e00 | |||
3e00bcbf9f | |||
0b402b23f7 | |||
691fcaeee7 | |||
9f30910653 | |||
41a6c2e501 | |||
fbc7fc6645 | |||
573dbb431e | |||
7b2cba7a6c | |||
91ff5617ef | |||
f1782868f9 | |||
66ee22c3e6 | |||
2db1222e45 | |||
abbd057eb9 | |||
6da5b8ccc5 | |||
128e2b917d | |||
2f4173b267 | |||
3fea1e4df5 | |||
13d2552274 | |||
3d0bfbb4f4 | |||
b893e88e8b | |||
f2be9e4381 | |||
53b5d6d167 | |||
92bfe34716 | |||
5df096baf3 | |||
45cbaa2d13 | |||
720a17acd7 | |||
dab00ab036 |
31
.gitignore
vendored
31
.gitignore
vendored
@ -13,17 +13,22 @@ config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/metacity-wm.desktop
|
||||
src/mutter-wm.desktop
|
||||
src/mutter.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
.libs
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
@ -38,19 +43,18 @@ POTFILES
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmetacity-private.pc
|
||||
metacity
|
||||
metacity-dialog
|
||||
metacity-theme-viewer
|
||||
metacity.desktop
|
||||
metacity.schemas
|
||||
libmutter-private.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
mutter.desktop
|
||||
mutter.schemas
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
metacity-grayscale
|
||||
metacity-mag
|
||||
metacity-message
|
||||
metacity-window-demo
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
@ -58,3 +62,8 @@ 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
|
||||
|
32
configure.in
32
configure.in
@ -1,10 +1,8 @@
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_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], [3])
|
||||
m4_define([mutter_minor_version], [29])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -162,6 +160,11 @@ AC_ARG_WITH(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]),,
|
||||
@ -214,6 +217,24 @@ 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 libcanberra-gtk; then
|
||||
have_libcanberra=yes
|
||||
AC_MSG_RESULT(yes)
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libcanberra-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
|
||||
|
||||
XCOMPOSITE_VERSION=0.2
|
||||
|
||||
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
|
||||
@ -416,7 +437,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"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
found_sm=no
|
||||
@ -534,6 +555,7 @@ mutter-$VERSION:
|
||||
XFree86 Xinerama: ${use_xfree_xinerama}
|
||||
Solaris Xinerama: ${use_solaris_xinerama}
|
||||
Startup notification: ${have_startup_notification}
|
||||
libcanberra: ${have_libcanberra}
|
||||
Introspection: ${have_introspection}
|
||||
Session management: ${found_sm}
|
||||
Shape extension: ${found_shape}
|
||||
|
@ -10,6 +10,7 @@ be@latin
|
||||
bg
|
||||
bn
|
||||
bn_IN
|
||||
br
|
||||
bs
|
||||
ca
|
||||
ca@valencia
|
||||
@ -56,6 +57,7 @@ mn
|
||||
mr
|
||||
ms
|
||||
nb
|
||||
nds
|
||||
ne
|
||||
nl
|
||||
nn
|
||||
|
@ -1,5 +1,6 @@
|
||||
# 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
|
||||
|
1541
po/pt_BR.po
1541
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,6 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter-private.la
|
||||
|
||||
SUBDIRS=wm-tester tools compositor/plugins
|
||||
@ -13,10 +16,6 @@ mutter_built_sources = \
|
||||
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 \
|
||||
@ -29,6 +28,8 @@ mutter_SOURCES= \
|
||||
compositor/mutter-plugin-manager.c \
|
||||
compositor/mutter-plugin-manager.h \
|
||||
compositor/mutter-shaped-texture.c \
|
||||
compositor/mutter-texture-tower.c \
|
||||
compositor/mutter-texture-tower.h \
|
||||
compositor/mutter-window.c \
|
||||
compositor/mutter-window-private.h \
|
||||
compositor/mutter-window-group.c \
|
||||
@ -150,7 +151,6 @@ libmutterincludedir = $(includedir)/mutter/mutter-private
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
include/alttabhandler.h \
|
||||
include/boxes.h \
|
||||
ui/gradient.h \
|
||||
include/main.h \
|
||||
@ -214,6 +214,7 @@ Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mu
|
||||
--include=Clutter-1.0 \
|
||||
--pkg=clutter-1.0 \
|
||||
--pkg=gtk+-2.0 \
|
||||
--include=xlib-2.0 \
|
||||
--include=xfixes-4.0 \
|
||||
--program=$$pwd/mutter \
|
||||
$(filter %.c,$(mutter_SOURCES)) \
|
||||
@ -328,7 +329,7 @@ mutter-marshal.c: Makefile mutter-marshal.list
|
||||
|
||||
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
|
||||
@true
|
||||
stamp-mutter-enum-types.h: $(mutter_source_h) mutter-enum-types.h.in
|
||||
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 \
|
||||
|
@ -390,10 +390,10 @@ mutter_begin_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
XGrabKeyboard (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
timestamp);
|
||||
result = XGrabKeyboard (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
timestamp);
|
||||
|
||||
if (result != Success)
|
||||
goto fail;
|
||||
|
@ -459,6 +459,18 @@ mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
|
||||
mutter_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_plugin_get_windows:
|
||||
* @plugin: A #MutterPlugin
|
||||
*
|
||||
* This function returns all of the #MutterWindow 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 MutterWindow): Windows in stacking order, topmost last
|
||||
*/
|
||||
GList *
|
||||
mutter_plugin_get_windows (MutterPlugin *plugin)
|
||||
{
|
||||
|
@ -26,19 +26,27 @@
|
||||
#include <config.h>
|
||||
|
||||
#include "mutter-shaped-texture.h"
|
||||
#include "mutter-texture-tower.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_notify (GObject *object,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void mutter_shaped_texture_paint (ClutterActor *actor);
|
||||
static void mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
|
||||
|
||||
#ifdef HAVE_GLX_TEXTURE_PIXMAP
|
||||
@ -55,6 +63,7 @@ G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
|
||||
|
||||
struct _MutterShapedTexturePrivate
|
||||
{
|
||||
MutterTextureTower *paint_tower;
|
||||
CoglHandle mask_texture;
|
||||
CoglHandle material;
|
||||
CoglHandle material_unshaped;
|
||||
@ -74,13 +83,17 @@ mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
|
||||
|
||||
gobject_class->dispose = mutter_shaped_texture_dispose;
|
||||
gobject_class->finalize = mutter_shaped_texture_finalize;
|
||||
gobject_class->notify = mutter_shaped_texture_notify;
|
||||
|
||||
actor_class->paint = mutter_shaped_texture_paint;
|
||||
actor_class->pick = mutter_shaped_texture_pick;
|
||||
|
||||
x11_texture_class->update_area = mutter_shaped_texture_update_area;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
|
||||
}
|
||||
|
||||
@ -93,6 +106,7 @@ mutter_shaped_texture_init (MutterShapedTexture *self)
|
||||
|
||||
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
|
||||
|
||||
priv->paint_tower = mutter_texture_tower_new ();
|
||||
priv->mask_texture = COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
@ -102,6 +116,10 @@ mutter_shaped_texture_dispose (GObject *object)
|
||||
MutterShapedTexture *self = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->paint_tower)
|
||||
mutter_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
|
||||
mutter_shaped_texture_dirty_mask (self);
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
@ -138,6 +156,28 @@ mutter_shaped_texture_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_notify (GObject *object,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
if (G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->notify)
|
||||
G_OBJECT_CLASS (mutter_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)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) object;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
mutter_texture_tower_set_base_texture (priv->paint_tower,
|
||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
|
||||
{
|
||||
@ -151,7 +191,7 @@ mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
|
||||
cogl_texture_get_gl_texture (priv->mask_texture,
|
||||
&mask_gl_tex, &mask_gl_target);
|
||||
|
||||
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
glDeleteTextures (1, &mask_gl_tex);
|
||||
|
||||
cogl_texture_unref (priv->mask_texture);
|
||||
@ -214,23 +254,23 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
|
||||
|
||||
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
|
||||
|
||||
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
GLuint tex;
|
||||
|
||||
glGenTextures (1, &tex);
|
||||
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, 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 (CGL_TEXTURE_RECTANGLE_ARB, 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,
|
||||
CGL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
tex_width, tex_height,
|
||||
0, 0,
|
||||
COGL_PIXEL_FORMAT_A_8);
|
||||
@ -269,7 +309,30 @@ mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
/* If mipmaps are supported, then the texture filter quality will
|
||||
* still be HIGH here. In that case we just want to use the base
|
||||
* texture. If mipmaps are not support then
|
||||
* on_glx_texture_pixmap_pre_paint() will have reset the texture
|
||||
* filter quality to MEDIUM, and we should use the MutterTextureTower
|
||||
* mipmap emulation.
|
||||
*
|
||||
* http://bugzilla.openedhand.com/show_bug.cgi?id=1877 is an RFE
|
||||
* for a better way of handling this.
|
||||
*
|
||||
* While it would be nice to have direct access to the 'can_mipmap'
|
||||
* boolean in ClutterGLXTexturePixmap, since since MutterTextureTower
|
||||
* creates the scaled down images on demand there is no substantial
|
||||
* overhead from doing the work to create and update the tower and
|
||||
* not using it, other than the memory allocated for the MutterTextureTower
|
||||
* structure itself.
|
||||
*/
|
||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (stex)) == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
|
||||
else
|
||||
paint_tex = mutter_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
@ -277,9 +340,6 @@ mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
if (paint_tex == COGL_INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
if (priv->rectangles->len < 1)
|
||||
{
|
||||
/* If there are no rectangles use a single-layer texture */
|
||||
@ -367,24 +427,34 @@ mutter_shaped_texture_paint (ClutterActor *actor)
|
||||
}
|
||||
else
|
||||
{
|
||||
float coords[MAX_RECTS * 8];
|
||||
float coords[8];
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
GdkRectangle *rect = &rects[i];
|
||||
|
||||
coords[i * 8 + 0] = rect->x;
|
||||
coords[i * 8 + 1] = rect->y;
|
||||
coords[i * 8 + 2] = rect->x + rect->width;
|
||||
coords[i * 8 + 3] = rect->y + rect->height;
|
||||
coords[i * 8 + 4] = rect->x / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 5] = rect->y / (alloc.y2 - alloc.y1);
|
||||
coords[i * 8 + 6] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
|
||||
coords[i * 8 + 7] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
g_free (rects);
|
||||
|
||||
cogl_rectangles_with_texture_coords (coords, n_rects);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -438,6 +508,22 @@ mutter_shaped_texture_pick (ClutterActor *actor,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MutterShapedTexture *stex = (MutterShapedTexture *) texture;
|
||||
MutterShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (mutter_shaped_texture_parent_class)->update_area (texture,
|
||||
x, y, width, height);
|
||||
|
||||
mutter_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
mutter_shaped_texture_new (void)
|
||||
{
|
||||
|
837
src/compositor/mutter-texture-tower.c
Normal file
837
src/compositor/mutter-texture-tower.c
Normal file
@ -0,0 +1,837 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MutterTextureTower
|
||||
*
|
||||
* 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 "mutter-texture-tower.h"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
|
||||
#if !CLUTTER_CHECK_VERSION(1,1,3)
|
||||
static PFNGLACTIVETEXTUREARBPROC activeTexture;
|
||||
static PFNGLGENFRAMEBUFFERSPROC genFramebuffers;
|
||||
static PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers;
|
||||
static PFNGLBINDFRAMEBUFFERPROC bindFramebuffer;
|
||||
static PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D;
|
||||
#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 _MutterTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglHandle textures[MAX_TEXTURE_LEVELS];
|
||||
#if CLUTTER_CHECK_VERSION(1,1,3)
|
||||
CoglHandle fbos[MAX_TEXTURE_LEVELS];
|
||||
#else
|
||||
GLuint fbos[MAX_TEXTURE_LEVELS];
|
||||
#endif
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* mutter_texture_tower_new:
|
||||
*
|
||||
* Creates a new texture tower. The base texture has to be set with
|
||||
* mutter_texture_tower_set_base_texture() before use.
|
||||
*
|
||||
* Return value: the new texture tower. Free with mutter_texture_tower_free()
|
||||
*/
|
||||
MutterTextureTower *
|
||||
mutter_texture_tower_new (void)
|
||||
{
|
||||
MutterTextureTower *tower;
|
||||
|
||||
tower = g_slice_new0 (MutterTextureTower);
|
||||
|
||||
return tower;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_texture_tower_free:
|
||||
* @tower: a #MutterTextureTower
|
||||
*
|
||||
* Frees a texture tower created with mutter_texture_tower_new().
|
||||
*/
|
||||
void
|
||||
mutter_texture_tower_free (MutterTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
mutter_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
|
||||
|
||||
g_slice_free (MutterTextureTower, 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_texture_unref (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_texture_tower_update_area:
|
||||
* @tower: a MutterTextureTower
|
||||
* @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
|
||||
mutter_texture_tower_set_base_texture (MutterTextureTower *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 CLUTTER_CHECK_VERSION(1,1,3)
|
||||
if (tower->fbos[i] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_handle_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = COGL_INVALID_HANDLE;
|
||||
}
|
||||
#else
|
||||
if (tower->fbos[i] != 0)
|
||||
{
|
||||
(*deleteFramebuffers) (1, &tower->fbos[i]);
|
||||
tower->fbos[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cogl_texture_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
|
||||
if (tower->textures[0] != COGL_INVALID_HANDLE)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_texture_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);
|
||||
|
||||
mutter_texture_tower_update_area (tower, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->n_levels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_texture_tower_update_area:
|
||||
* @tower: a MutterTextureTower
|
||||
* @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
|
||||
mutter_texture_tower_update_area (MutterTextureTower *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
|
||||
* Mutter.
|
||||
*/
|
||||
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 (MutterTextureTower *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;
|
||||
}
|
||||
|
||||
/* The COGL fbo (render-to-texture) support is pretty hard to use in
|
||||
* Clutter 1.0; there's no way to save and restore the old projection
|
||||
* matrix and viewport without ugly workarounds that require explicit
|
||||
* access to the ClutterStage. In Clutter 1.2, the save/restore is
|
||||
* automatic. For now, until we depend on Clutter 1.2, we use GL
|
||||
* directly for render-to-texture. The main downside (other than
|
||||
* a lot of verbosity) is that we have to save the state, reset anything
|
||||
* that we think COGL might have left in a way we don't want it, then
|
||||
* restore the old state.
|
||||
*/
|
||||
#if CLUTTER_CHECK_VERSION(1,1,3)
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MutterTextureTower *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)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
initialize_gl_functions (void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = TRUE;
|
||||
|
||||
activeTexture = (PFNGLACTIVETEXTUREARBPROC) cogl_get_proc_address ("glActiveTextureARB");
|
||||
genFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) cogl_get_proc_address ("glGenFramebuffersEXT");
|
||||
deleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT");
|
||||
bindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) cogl_get_proc_address ("glBindFramebufferEXT");
|
||||
framebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) cogl_get_proc_address ("glFramebufferTexture2D");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MutterTextureTower *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);
|
||||
ClutterActorBox source_box;
|
||||
Box *dest_box;
|
||||
|
||||
GLuint source_gl_tex;
|
||||
GLenum source_gl_target;
|
||||
|
||||
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
return FALSE;
|
||||
|
||||
initialize_gl_functions ();
|
||||
|
||||
/* Create the frame-buffer object that renders to the texture, if
|
||||
* it doesn't exist; just bind it for rendering if it does */
|
||||
if (tower->fbos[level] == 0)
|
||||
{
|
||||
GLuint dest_gl_tex;
|
||||
GLenum dest_gl_target;
|
||||
|
||||
cogl_texture_get_gl_texture (dest_texture, &dest_gl_tex, &dest_gl_target);
|
||||
|
||||
(*genFramebuffers) (1, &tower->fbos[level]);
|
||||
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
|
||||
(*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
dest_gl_target, dest_gl_tex, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
|
||||
}
|
||||
|
||||
/* Save the old state (other than the transformation matrices) */
|
||||
glPushAttrib (GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
|
||||
|
||||
/* And set up the state we need */
|
||||
glDisable (GL_BLEND);
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
glDisable (GL_STENCIL_TEST);
|
||||
|
||||
glDisable (GL_CLIP_PLANE3);
|
||||
glDisable (GL_CLIP_PLANE2);
|
||||
glDisable (GL_CLIP_PLANE1);
|
||||
glDisable (GL_CLIP_PLANE0);
|
||||
|
||||
cogl_texture_get_gl_texture (source_texture, &source_gl_tex, &source_gl_target);
|
||||
|
||||
(*activeTexture) (GL_TEXTURE0_ARB);
|
||||
if (source_gl_target == GL_TEXTURE_2D)
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
else
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glEnable (source_gl_target);
|
||||
glBindTexture (source_gl_target, source_gl_tex);
|
||||
glTexParameteri (source_gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
|
||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
/* In theory, we should loop over all the texture units supported
|
||||
* by the GL implementation, but here we just assume that no more
|
||||
* than three are used by Mutter and all GL implementations we care
|
||||
* about will support at least 3.
|
||||
*/
|
||||
(*activeTexture) (GL_TEXTURE1_ARB);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
(*activeTexture) (GL_TEXTURE2_ARB);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
glViewport (0, 0, dest_texture_width, dest_texture_height);
|
||||
|
||||
/* Save the transformation matrices and set up new ones that map
|
||||
* coordinates directly onto the destination texture */
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity ();
|
||||
glOrtho (0, dest_texture_width, 0, dest_texture_height, -1., 1.);
|
||||
|
||||
/* Draw */
|
||||
|
||||
dest_box = &tower->invalid[level];
|
||||
if (texture_is_rectangle (source_texture))
|
||||
{
|
||||
source_box.x1 = 2 * dest_box->x1;
|
||||
source_box.y1 = 2 * dest_box->y1;
|
||||
source_box.x2 = 2 * dest_box->x2;
|
||||
source_box.y2 = 2 * dest_box->y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
source_box.x1 = (2. * dest_box->x1) / source_texture_width;
|
||||
source_box.y1 = (2. * dest_box->y1) / source_texture_height;
|
||||
source_box.x2 = (2. * dest_box->x2) / source_texture_width;
|
||||
source_box.y2 = (2. * dest_box->y2) / source_texture_height;
|
||||
}
|
||||
|
||||
glColor3f (0., 1., 1.);
|
||||
|
||||
glBegin (GL_QUADS);
|
||||
glTexCoord2f (source_box.x1, source_box.y1);
|
||||
glVertex2f (dest_box->x1, dest_box->y1);
|
||||
glTexCoord2f (source_box.x2, source_box.y1);
|
||||
glVertex2f (dest_box->x2, dest_box->y1);
|
||||
glTexCoord2f (source_box.x2, source_box.y2);
|
||||
glVertex2f (dest_box->x2, dest_box->y2);
|
||||
glTexCoord2f (source_box.x1, source_box.y2);
|
||||
glVertex2f (dest_box->x1, dest_box->y2);
|
||||
glEnd ();
|
||||
|
||||
/* And restore everything back the way we found it */
|
||||
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glPopMatrix ();
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glPopMatrix ();
|
||||
|
||||
glPopAttrib ();
|
||||
|
||||
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 (MutterTextureTower *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 (MutterTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_texture_tower_get_paint_texture:
|
||||
* @tower: a MutterTextureTower
|
||||
*
|
||||
* 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
|
||||
mutter_texture_tower_get_paint_texture (MutterTextureTower *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];
|
||||
}
|
69
src/compositor/mutter-texture-tower.h
Normal file
69
src/compositor/mutter-texture-tower.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MutterTextureTower
|
||||
*
|
||||
* 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 __MUTTER_TEXTURE_TOWER_H__
|
||||
#define __MUTTER_TEXTURE_TOWER_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:MutterTextureTower
|
||||
* @short_description: mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* A #MutterTextureTower 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 _MutterTextureTower MutterTextureTower;
|
||||
|
||||
MutterTextureTower *mutter_texture_tower_new (void);
|
||||
void mutter_texture_tower_free (MutterTextureTower *tower);
|
||||
void mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
|
||||
CoglHandle texture);
|
||||
void mutter_texture_tower_update_area (MutterTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglHandle mutter_texture_tower_get_paint_texture (MutterTextureTower *tower);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#endif /* __MUTTER_TEXTURE_TOWER_H__ */
|
@ -722,6 +722,18 @@ const char *mutter_window_get_description (MutterWindow *self)
|
||||
return self->priv->desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutter_window_get_workspace:
|
||||
* @self: #MutterWindow
|
||||
*
|
||||
* Returns the index of workspace on which this window is located; if the
|
||||
* window is sticky, or is not currently located on any workspace, returns -1.
|
||||
* This function is deprecated and should not be used in newly written code;
|
||||
* meta_window_get_workspace() instead.
|
||||
*
|
||||
* Return value: (transfer none): index of workspace on which this window is
|
||||
* located.
|
||||
*/
|
||||
gint
|
||||
mutter_window_get_workspace (MutterWindow *self)
|
||||
{
|
||||
@ -738,6 +750,9 @@ mutter_window_get_workspace (MutterWindow *self)
|
||||
|
||||
workspace = meta_window_get_workspace (priv->window);
|
||||
|
||||
if (!workspace)
|
||||
return -1;
|
||||
|
||||
return meta_workspace_index (workspace);
|
||||
}
|
||||
|
||||
|
@ -1,138 +0,0 @@
|
||||
/* -*- 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);
|
||||
}
|
@ -1,223 +0,0 @@
|
||||
/* -*- 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,6 +52,9 @@
|
||||
#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
|
||||
@ -228,18 +231,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) && (display->focus_window->frame))
|
||||
if (!window && (display->focus_window))
|
||||
{
|
||||
window = display->focus_window;
|
||||
}
|
||||
if (window)
|
||||
if (window && window->frame)
|
||||
{
|
||||
bell_flash_window_frame (window);
|
||||
}
|
||||
@ -285,6 +288,48 @@ 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 */
|
||||
|
||||
@ -292,11 +337,19 @@ 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,
|
||||
audible ? XkbAudibleBellMask : 0);
|
||||
#endif
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
enable_system_bell ? XkbAudibleBellMask : 0);
|
||||
#endif /* HAVE_XKB */
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -323,11 +376,7 @@ meta_bell_init (MetaDisplay *display)
|
||||
XkbUseCoreKbd,
|
||||
XkbBellNotifyMask,
|
||||
XkbBellNotifyMask);
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
meta_prefs_bell_is_audible ()
|
||||
? XkbAudibleBellMask : 0);
|
||||
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
|
||||
if (visual_bell_auto_reset) {
|
||||
XkbSetAutoResetControls (display->xdisplay,
|
||||
XkbAudibleBellMask,
|
||||
|
@ -535,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 xinerama size changes. If it ever
|
||||
* strut list changes or the screen or monitor 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:
|
||||
@ -1792,14 +1792,14 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
}
|
||||
|
||||
GList*
|
||||
meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
const GList *xinerama_rects,
|
||||
meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_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"; xinerama edges are different.
|
||||
* immediately on the other side"; monitor edges are different.
|
||||
*/
|
||||
GList *ret;
|
||||
const GList *cur;
|
||||
@ -1808,14 +1808,14 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* Initialize the return list to be empty */
|
||||
ret = NULL;
|
||||
|
||||
/* start of ret with all the edges of xineramas that are adjacent to
|
||||
* another xinerama.
|
||||
/* start of ret with all the edges of monitors that are adjacent to
|
||||
* another monitor.
|
||||
*/
|
||||
cur = xinerama_rects;
|
||||
cur = monitor_rects;
|
||||
while (cur)
|
||||
{
|
||||
MetaRectangle *cur_rect = cur->data;
|
||||
const GList *compare = xinerama_rects;
|
||||
const GList *compare = monitor_rects;
|
||||
while (compare)
|
||||
{
|
||||
MetaRectangle *compare_rect = compare->data;
|
||||
@ -1849,15 +1849,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (x != INT_MIN)
|
||||
{
|
||||
/* We need a left edge for the xinerama on the right, and
|
||||
* a right edge for the xinerama on the left. Just fill
|
||||
/* We need a left edge for the monitor on the right, and
|
||||
* a right edge for the monitor 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_XINERAMA;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
@ -1892,15 +1892,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
/* If the rectangles really are adjacent */
|
||||
if (y != INT_MIN)
|
||||
{
|
||||
/* We need a top edge for the xinerama on the bottom, and
|
||||
* a bottom edge for the xinerama on the top. Just fill
|
||||
/* We need a top edge for the monitor on the bottom, and
|
||||
* a bottom edge for the monitor 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_XINERAMA;
|
||||
new_edge->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
ret = g_list_prepend (ret, new_edge);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "constraints.h"
|
||||
#include "workspace-private.h"
|
||||
#include "place.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
@ -93,7 +94,7 @@ typedef enum
|
||||
{
|
||||
PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
|
||||
PRIORITY_ASPECT_RATIO = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
|
||||
PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
|
||||
PRIORITY_SIZE_HINTS_INCREMENTS = 1,
|
||||
PRIORITY_MAXIMIZATION = 2,
|
||||
@ -127,17 +128,17 @@ typedef struct
|
||||
int resize_gravity;
|
||||
FixedDirections fixed_directions;
|
||||
|
||||
/* work_area_xinerama - current xinerama region minus struts
|
||||
* entire_xinerama - current xienrama, including strut regions
|
||||
/* work_area_monitor - current monitor region minus struts
|
||||
* entire_monitor - current monitor, including strut regions
|
||||
*/
|
||||
MetaRectangle work_area_xinerama;
|
||||
MetaRectangle entire_xinerama;
|
||||
MetaRectangle work_area_monitor;
|
||||
MetaRectangle entire_monitor;
|
||||
|
||||
/* Spanning rectangles for the non-covered (by struts) region of the
|
||||
* screen and also for just the current xinerama
|
||||
* screen and also for just the current monitor
|
||||
*/
|
||||
GList *usable_screen_region;
|
||||
GList *usable_xinerama_region;
|
||||
GList *usable_monitor_region;
|
||||
} ConstraintInfo;
|
||||
|
||||
static gboolean constrain_maximization (MetaWindow *window,
|
||||
@ -160,7 +161,7 @@ static gboolean constrain_aspect_ratio (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
static gboolean constrain_to_single_xinerama (MetaWindow *window,
|
||||
static gboolean constrain_to_single_monitor (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only);
|
||||
@ -214,7 +215,7 @@ static const Constraint all_constraints[] = {
|
||||
{constrain_size_increments, "constrain_size_increments"},
|
||||
{constrain_size_limits, "constrain_size_limits"},
|
||||
{constrain_aspect_ratio, "constrain_aspect_ratio"},
|
||||
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
|
||||
{constrain_to_single_monitor, "constrain_to_single_monitor"},
|
||||
{constrain_fully_onscreen, "constrain_fully_onscreen"},
|
||||
{constrain_titlebar_visible, "constrain_titlebar_visible"},
|
||||
{constrain_partially_onscreen, "constrain_partially_onscreen"},
|
||||
@ -311,7 +312,7 @@ meta_window_constrain (MetaWindow *window,
|
||||
*new = info.current;
|
||||
|
||||
/* We may need to update window->require_fully_onscreen,
|
||||
* window->require_on_single_xinerama, and perhaps other quantities
|
||||
* window->require_on_single_monitor, and perhaps other quantities
|
||||
* if this was a user move or user move-and-resize operation.
|
||||
*/
|
||||
update_onscreen_requirements (window, &info);
|
||||
@ -333,7 +334,7 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
const MetaRectangle *orig,
|
||||
MetaRectangle *new)
|
||||
{
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
MetaWorkspace *cur_workspace;
|
||||
|
||||
info->orig = *orig;
|
||||
@ -387,15 +388,15 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
if (!info->is_user_action)
|
||||
info->fixed_directions = FIXED_DIRECTION_NONE;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
if (!window->fullscreen || window->fullscreen_monitors[0] == -1)
|
||||
{
|
||||
info->entire_xinerama = xinerama_info->rect;
|
||||
info->entire_monitor = monitor_info->rect;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -403,28 +404,29 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
long monitor;
|
||||
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
info->entire_xinerama =
|
||||
window->screen->xinerama_infos[monitor].rect;
|
||||
info->entire_monitor =
|
||||
window->screen->monitor_infos[monitor].rect;
|
||||
for (i = 1; i <= 3; i++)
|
||||
{
|
||||
monitor = window->fullscreen_monitors[i];
|
||||
meta_rectangle_union (&info->entire_xinerama,
|
||||
&window->screen->xinerama_infos[monitor].rect,
|
||||
&info->entire_xinerama);
|
||||
meta_rectangle_union (&info->entire_monitor,
|
||||
&window->screen->monitor_infos[monitor].rect,
|
||||
&info->entire_monitor);
|
||||
}
|
||||
}
|
||||
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_screen_region =
|
||||
meta_workspace_get_onscreen_region (cur_workspace);
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly.
|
||||
*/
|
||||
if (meta_rectangle_equal (new, &xinerama_info->rect) &&
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
@ -448,8 +450,8 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
" is_user_action : %s\n"
|
||||
" resize_gravity : %s\n"
|
||||
" fixed_directions: %s\n"
|
||||
" work_area_xinerama: %d,%d +%d,%d\n"
|
||||
" entire_xinerama : %d,%d +%d,%d\n",
|
||||
" work_area_monitor: %d,%d +%d,%d\n"
|
||||
" entire_monitor : %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,
|
||||
@ -465,11 +467,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_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);
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -493,25 +495,25 @@ place_window_if_needed(MetaWindow *window,
|
||||
{
|
||||
MetaRectangle placed_rect = info->orig;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaXineramaScreenInfo *xinerama_info;
|
||||
const MetaMonitorInfo *monitor_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 xinerama. Find the
|
||||
* new xinerama and update the ConstraintInfo
|
||||
/* placing the window may have changed the monitor. Find the
|
||||
* new monitor and update the ConstraintInfo
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
cur_workspace = window->screen->active_workspace;
|
||||
info->usable_xinerama_region =
|
||||
meta_workspace_get_onxinerama_region (cur_workspace,
|
||||
xinerama_info->number);
|
||||
info->usable_monitor_region =
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
|
||||
info->current.x = placed_rect.x;
|
||||
@ -526,22 +528,23 @@ place_window_if_needed(MetaWindow *window,
|
||||
if (window->placed || did_placement)
|
||||
{
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
window->maximize_vertically_after_placement)
|
||||
window->maximize_vertically_after_placement ||
|
||||
window->fullscreen_after_placement)
|
||||
{
|
||||
/* define a sane saved_rect so that the user can unmaximize to
|
||||
* something reasonable.
|
||||
/* define a sane saved_rect so that the user can unmaximize or
|
||||
* make unfullscreen to something reasonable.
|
||||
*/
|
||||
if (info->current.width >= info->work_area_xinerama.width)
|
||||
if (info->current.width >= 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;
|
||||
info->current.width = .75 * info->work_area_monitor.width;
|
||||
info->current.x = info->work_area_monitor.x +
|
||||
.125 * info->work_area_monitor.width;
|
||||
}
|
||||
if (info->current.height >= info->work_area_xinerama.height)
|
||||
if (info->current.height >= 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;
|
||||
info->current.height = .75 * info->work_area_monitor.height;
|
||||
info->current.y = info->work_area_monitor.y +
|
||||
.083 * info->work_area_monitor.height;
|
||||
}
|
||||
|
||||
if (window->maximize_horizontally_after_placement ||
|
||||
@ -556,6 +559,15 @@ 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;
|
||||
}
|
||||
@ -589,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
return;
|
||||
|
||||
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
|
||||
* require_on_single_xinerama, and require_titlebar_visible flags to
|
||||
* require_on_single_monitor, 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
|
||||
@ -603,7 +615,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
* problematic case but this may need to be revisited.
|
||||
*/
|
||||
|
||||
/* The require onscreen/on-single-xinerama and titlebar_visible
|
||||
/* The require onscreen/on-single-monitor and titlebar_visible
|
||||
* stuff is relative to the outer window, not the inner
|
||||
*/
|
||||
extend_by_frame (&info->current, info->fgeom);
|
||||
@ -622,17 +634,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 xinerama.
|
||||
* window to be on a single monitor.
|
||||
*/
|
||||
old = window->require_on_single_xinerama;
|
||||
window->require_on_single_xinerama =
|
||||
meta_rectangle_contained_in_region (info->usable_xinerama_region,
|
||||
old = window->require_on_single_monitor;
|
||||
window->require_on_single_monitor =
|
||||
meta_rectangle_contained_in_region (info->usable_monitor_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_on_single_xinerama)
|
||||
if (old ^ window->require_on_single_monitor)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_on_single_xinerama for %s toggled to %s\n",
|
||||
"require_on_single_monitor for %s toggled to %s\n",
|
||||
window->desc,
|
||||
window->require_on_single_xinerama ? "TRUE" : "FALSE");
|
||||
window->require_on_single_monitor ? "TRUE" : "FALSE");
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* titlebar to be visible.
|
||||
@ -735,7 +747,7 @@ constrain_maximization (MetaWindow *window,
|
||||
|
||||
/* Calculate target_size = maximized size of (window + frame) */
|
||||
if (window->maximized_horizontally && window->maximized_vertically)
|
||||
target_size = info->work_area_xinerama;
|
||||
target_size = info->work_area_monitor;
|
||||
else
|
||||
{
|
||||
/* Amount of maximization possible in a single direction depends
|
||||
@ -757,7 +769,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_xinerama,
|
||||
&info->entire_monitor,
|
||||
direction,
|
||||
active_workspace_struts);
|
||||
}
|
||||
@ -804,7 +816,7 @@ constrain_fullscreen (MetaWindow *window,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
MetaRectangle min_size, max_size, xinerama;
|
||||
MetaRectangle min_size, max_size, monitor;
|
||||
gboolean too_big, too_small, constraint_already_satisfied;
|
||||
|
||||
if (priority > PRIORITY_FULLSCREEN)
|
||||
@ -814,22 +826,22 @@ constrain_fullscreen (MetaWindow *window,
|
||||
if (!window->fullscreen)
|
||||
return TRUE;
|
||||
|
||||
xinerama = info->entire_xinerama;
|
||||
monitor = info->entire_monitor;
|
||||
|
||||
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
|
||||
too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama);
|
||||
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
||||
if (too_big || too_small)
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
constraint_already_satisfied =
|
||||
meta_rectangle_equal (&info->current, &xinerama);
|
||||
meta_rectangle_equal (&info->current, &monitor);
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
info->current = xinerama;
|
||||
info->current = monitor;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1091,7 +1103,7 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_screen_and_xinerama_relative_constraints (
|
||||
do_screen_and_monitor_relative_constraints (
|
||||
MetaWindow *window,
|
||||
GList *region_spanning_rectangles,
|
||||
ConstraintInfo *info,
|
||||
@ -1107,7 +1119,7 @@ do_screen_and_xinerama_relative_constraints (
|
||||
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
|
||||
"screen/monitor constraint; region_spanning_rectangles: %s\n",
|
||||
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
|
||||
spanning_region));
|
||||
}
|
||||
@ -1165,32 +1177,32 @@ do_screen_and_xinerama_relative_constraints (
|
||||
}
|
||||
|
||||
static gboolean
|
||||
constrain_to_single_xinerama (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
constrain_to_single_monitor (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
ConstraintPriority priority,
|
||||
gboolean check_only)
|
||||
{
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA)
|
||||
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
|
||||
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 xineramas.
|
||||
* or else users will be unable to move windows such as XMMS across monitors.
|
||||
*/
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
window->type == META_WINDOW_DOCK ||
|
||||
window->screen->n_xinerama_infos == 1 ||
|
||||
!window->require_on_single_xinerama ||
|
||||
window->screen->n_monitor_infos == 1 ||
|
||||
!window->require_on_single_monitor ||
|
||||
!window->frame ||
|
||||
info->is_user_action)
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_xinerama_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_monitor_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1214,10 +1226,10 @@ constrain_fully_onscreen (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Have a helper function handle the constraint for us */
|
||||
return do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
return do_screen_and_monitor_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1290,10 +1302,10 @@ constrain_titlebar_visible (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_monitor_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,
|
||||
@ -1365,10 +1377,10 @@ constrain_partially_onscreen (MetaWindow *window,
|
||||
horiz_amount_onscreen,
|
||||
vert_amount_onscreen);
|
||||
retval =
|
||||
do_screen_and_xinerama_relative_constraints (window,
|
||||
info->usable_screen_region,
|
||||
info,
|
||||
check_only);
|
||||
do_screen_and_monitor_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,
|
||||
|
@ -55,27 +55,16 @@ 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
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
MetaWindow *ours = (MetaWindow*) user_data;
|
||||
|
||||
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);
|
||||
ours->dialog_pid = -1;
|
||||
|
||||
ours->dialog_pid = -1; /* forget it anyway */
|
||||
}
|
||||
/* exit status of 1 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||
meta_window_kill (ours);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -86,7 +75,7 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
{
|
||||
MetaWindow *window = user_data;
|
||||
char *window_title;
|
||||
gchar *window_content;
|
||||
gchar *window_content, *tmp;
|
||||
GPid dialog_pid;
|
||||
|
||||
meta_topic (META_DEBUG_PING,
|
||||
@ -101,11 +90,14 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
|
||||
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
|
||||
|
||||
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);
|
||||
/* 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."));
|
||||
|
||||
g_free (window_title);
|
||||
|
||||
@ -117,13 +109,10 @@ delete_ping_timeout_func (MetaDisplay *display,
|
||||
NULL, NULL);
|
||||
|
||||
g_free (window_content);
|
||||
g_free (tmp);
|
||||
|
||||
window->dialog_pid = dialog_pid;
|
||||
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
window);
|
||||
|
||||
g_child_watch_add (dialog_pid, dialog_exited, window);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -150,6 +150,15 @@ 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;
|
||||
|
||||
@ -217,8 +226,8 @@ struct _MetaDisplay
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
|
||||
/* Xinerama cache */
|
||||
unsigned int xinerama_cache_invalidated : 1;
|
||||
/* Monitor cache */
|
||||
unsigned int monitor_cache_invalidated : 1;
|
||||
|
||||
/* Opening the display */
|
||||
unsigned int display_opening : 1;
|
||||
@ -349,6 +358,9 @@ void meta_display_register_x_window (MetaDisplay *display,
|
||||
void meta_display_unregister_x_window (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
void meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
GSList* meta_display_list_windows (MetaDisplay *display,
|
||||
MetaListWindowsFlags flags);
|
||||
|
||||
@ -378,9 +390,8 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
/* 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);
|
||||
/* Next function is defined in edge-resistance.c */
|
||||
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);
|
||||
|
@ -129,6 +129,9 @@ enum
|
||||
{
|
||||
OVERLAY_KEY,
|
||||
FOCUS_WINDOW,
|
||||
WINDOW_CREATED,
|
||||
WINDOW_DEMANDS_ATTENTION,
|
||||
WINDOW_MARKED_URGENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -148,8 +151,10 @@ static guint display_signals [LAST_SIGNAL] = { 0 };
|
||||
*/
|
||||
static MetaDisplay *the_display = NULL;
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void meta_spew_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
#endif
|
||||
|
||||
static gboolean event_callback (XEvent *event,
|
||||
gpointer data);
|
||||
@ -226,6 +231,34 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
display_signals[WINDOW_CREATED] =
|
||||
g_signal_new ("window-created",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
|
||||
display_signals[WINDOW_DEMANDS_ATTENTION] =
|
||||
g_signal_new ("window-demands-attention",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
|
||||
display_signals[WINDOW_MARKED_URGENT] =
|
||||
g_signal_new ("window-marked-urgent",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
META_TYPE_WINDOW);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOCUS_WINDOW,
|
||||
g_param_spec_object ("focus-window",
|
||||
@ -483,7 +516,7 @@ meta_display_open (void)
|
||||
the_display->leader_window = None;
|
||||
the_display->timestamp_pinging_window = None;
|
||||
|
||||
the_display->xinerama_cache_invalidated = TRUE;
|
||||
the_display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
the_display->groups_by_leader = NULL;
|
||||
|
||||
@ -722,6 +755,13 @@ meta_display_open (void)
|
||||
the_display->leader_window,
|
||||
the_display->atom__NET_WM_NAME,
|
||||
"Mutter");
|
||||
|
||||
/* The GNOME keybindings capplet should include both the Mutter and Metacity
|
||||
* keybindings */
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
the_display->atom__GNOME_WM_KEYBINDINGS,
|
||||
"Mutter,Metacity");
|
||||
|
||||
meta_prop_set_utf8_string_hint (the_display,
|
||||
the_display->leader_window,
|
||||
@ -1528,7 +1568,7 @@ event_callback (XEvent *event,
|
||||
bypass_compositor = FALSE;
|
||||
filter_out_event = FALSE;
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->xinerama_cache_invalidated = TRUE;
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
modified = event_get_modified_window (display, event);
|
||||
|
||||
@ -2549,7 +2589,7 @@ event_callback (XEvent *event,
|
||||
{
|
||||
case XkbBellNotify:
|
||||
if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
|
||||
xkb_ev->time - 1000))
|
||||
xkb_ev->time - 100))
|
||||
{
|
||||
display->last_bell_time = xkb_ev->time;
|
||||
meta_bell_notify (display, xkb_ev);
|
||||
@ -3203,6 +3243,13 @@ meta_display_unregister_x_window (MetaDisplay *display,
|
||||
remove_pending_pings_for_window (display, xwindow);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_xwindow_is_a_no_focus_window:
|
||||
* @display: A #MetaDisplay
|
||||
@ -3591,18 +3638,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
/* If this is a move or resize, cache the window edges for
|
||||
* resistance/snapping
|
||||
*/
|
||||
if (meta_grab_op_is_resizing (display->grab_op) ||
|
||||
meta_grab_op_is_moving (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Computing edges to resist-movement or snap-to for %s.\n",
|
||||
window->desc);
|
||||
meta_display_compute_resistance_and_snapping_edges (display);
|
||||
}
|
||||
|
||||
/* Save the old stacking */
|
||||
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
|
||||
{
|
||||
@ -4106,7 +4141,7 @@ meta_set_syncing (gboolean setting)
|
||||
* How long, in milliseconds, we should wait after pinging a window
|
||||
* before deciding it's not going to get back to us.
|
||||
*/
|
||||
#define PING_TIMEOUT_DELAY 2250
|
||||
#define PING_TIMEOUT_DELAY 5000
|
||||
|
||||
/**
|
||||
* Does whatever it is we decided to do when a window didn't respond
|
||||
@ -4531,7 +4566,8 @@ meta_display_get_tab_list (MetaDisplay *display,
|
||||
|
||||
/* Check to see if it demands attention */
|
||||
if (l_window->wm_state_demands_attention &&
|
||||
l_window->workspace!=workspace)
|
||||
l_window->workspace!=workspace &&
|
||||
IN_TAB_CHAIN (l_window, type))
|
||||
{
|
||||
/* if it does, add it to the popup */
|
||||
tab_list = g_list_prepend (tab_list, l_window);
|
||||
@ -5111,9 +5147,9 @@ sanity_check_timestamps (MetaDisplay *display,
|
||||
meta_warning ("%s appears to be one of the offending windows "
|
||||
"with a timestamp of %u. Working around...\n",
|
||||
window->desc, window->net_wm_user_time);
|
||||
window->net_wm_user_time = timestamp;
|
||||
meta_window_set_user_time (window, timestamp);
|
||||
}
|
||||
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@ 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.
|
||||
*/
|
||||
@ -340,12 +342,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_XINERAMA = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
|
||||
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 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_XINERAMA = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
|
||||
const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
|
||||
|
||||
/* Quit if no movement was specified */
|
||||
@ -423,8 +425,8 @@ apply_edge_resistance (MetaWindow *window,
|
||||
case META_EDGE_WINDOW:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
|
||||
break;
|
||||
case META_EDGE_XINERAMA:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA;
|
||||
case META_EDGE_MONITOR:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
|
||||
@ -468,11 +470,11 @@ apply_edge_resistance (MetaWindow *window,
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
|
||||
break;
|
||||
case META_EDGE_XINERAMA:
|
||||
case META_EDGE_MONITOR:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
|
||||
else
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA;
|
||||
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
|
||||
break;
|
||||
case META_EDGE_SCREEN:
|
||||
if (movement_towards_edge (edge->side_type, increment))
|
||||
@ -550,7 +552,9 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
gboolean modified;
|
||||
int new_left, new_right, new_top, new_bottom;
|
||||
|
||||
g_assert (display->grab_edge_resistance_data != NULL);
|
||||
if (display->grab_edge_resistance_data == NULL)
|
||||
compute_resistance_and_snapping_edges (display);
|
||||
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
|
||||
if (auto_snap)
|
||||
@ -671,7 +675,8 @@ meta_display_cleanup_edges (MetaDisplay *display)
|
||||
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
|
||||
GHashTable *edges_to_be_freed;
|
||||
|
||||
g_assert (edge_data != NULL);
|
||||
if (edge_data == NULL) /* Not currently cached */
|
||||
return;
|
||||
|
||||
/* We first need to clean out any window edges */
|
||||
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
@ -761,7 +766,7 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
|
||||
static void
|
||||
cache_edges (MetaDisplay *display,
|
||||
GList *window_edges,
|
||||
GList *xinerama_edges,
|
||||
GList *monitor_edges,
|
||||
GList *screen_edges)
|
||||
{
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
@ -776,7 +781,7 @@ cache_edges (MetaDisplay *display,
|
||||
if (meta_is_verbose())
|
||||
{
|
||||
int max_edges = MAX (MAX( g_list_length (window_edges),
|
||||
g_list_length (xinerama_edges)),
|
||||
g_list_length (monitor_edges)),
|
||||
g_list_length (screen_edges));
|
||||
char big_buffer[(EDGE_LENGTH+2)*max_edges];
|
||||
|
||||
@ -784,9 +789,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 (xinerama_edges, ", ", big_buffer);
|
||||
meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
"Xinerama edges for resistance: %s\n", big_buffer);
|
||||
"Monitor edges for resistance: %s\n", big_buffer);
|
||||
|
||||
meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
|
||||
meta_topic (META_DEBUG_EDGE_RESISTANCE,
|
||||
@ -807,7 +812,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = xinerama_edges;
|
||||
tmp = monitor_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@ -875,7 +880,7 @@ cache_edges (MetaDisplay *display,
|
||||
tmp = window_edges;
|
||||
break;
|
||||
case 1:
|
||||
tmp = xinerama_edges;
|
||||
tmp = monitor_edges;
|
||||
break;
|
||||
case 2:
|
||||
tmp = screen_edges;
|
||||
@ -938,8 +943,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
edge_data->bottom_data.keyboard_buildup = 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
static void
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
{
|
||||
GList *stacked_windows;
|
||||
GList *cur_window_iter;
|
||||
@ -952,6 +957,11 @@ meta_display_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
|
||||
*/
|
||||
@ -1110,12 +1120,12 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
|
||||
/*
|
||||
* 5th: Cache the combination of these edges with the onscreen and
|
||||
* xinerama edges in an array for quick access. Free the edges since
|
||||
* monitor 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->xinerama_edges,
|
||||
display->grab_screen->active_workspace->monitor_edges,
|
||||
display->grab_screen->active_workspace->screen_edges);
|
||||
g_list_free (edges);
|
||||
|
||||
|
@ -186,10 +186,10 @@ x_error_handler (Display *xdisplay,
|
||||
|
||||
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
|
||||
/* Display can be NULL here Xlib only has one global error handler; and
|
||||
* there might be other displays open in the process.
|
||||
*/
|
||||
if (display->error_traps > 0)
|
||||
if (display && display->error_traps > 0)
|
||||
{
|
||||
/* we're in an error trap, chain to the trap handler
|
||||
* saved from GDK
|
||||
@ -228,21 +228,18 @@ x_io_error_handler (Display *xdisplay)
|
||||
|
||||
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);
|
||||
display ? display->name : DisplayString (xdisplay));
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
|
||||
errno, g_strerror (errno),
|
||||
display->name);
|
||||
display ? display->name : DisplayString (xdisplay));
|
||||
}
|
||||
|
||||
/* Xlib would force an exit anyhow */
|
||||
|
@ -2047,15 +2047,11 @@ process_tab_grab (MetaDisplay *display,
|
||||
action = META_KEYBINDING_ACTION_NONE;
|
||||
|
||||
/*
|
||||
* There are currently two different ways of customizing Alt-Tab, you can either
|
||||
* provide a replacement AltTabHandler object, or you can hook into the keybindings
|
||||
* meta_keybindings_set_custom_handler() and call meta_display_begin_grab_op()
|
||||
* yourself with one of the "tabbing" grab ops META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
|
||||
* etc. See meta_display_process_key_event() for the complete list. If screen->tab_handler
|
||||
* is NULL, the latter mechanism is being used. We skip most of our normal
|
||||
* processing and just make sure that the right custom handlers get called.
|
||||
* 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_handler)
|
||||
if (!screen->tab_popup)
|
||||
{
|
||||
if (event->type == KeyRelease)
|
||||
{
|
||||
@ -2553,7 +2549,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
|
||||
int new_x, new_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
@ -2685,7 +2681,7 @@ handle_move_to_center (MetaDisplay *display,
|
||||
int orig_x, orig_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_xineramas (window, &work_area);
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
@ -124,11 +125,13 @@ log_handler (const gchar *log_domain,
|
||||
static void
|
||||
version (void)
|
||||
{
|
||||
const int latest_year = 2010;
|
||||
|
||||
g_print (_("mutter %s\n"
|
||||
"Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
"Copyright (C) 2001-%d 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);
|
||||
VERSION, latest_year);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@ -226,6 +229,7 @@ typedef struct
|
||||
gboolean sync;
|
||||
gboolean composite;
|
||||
gboolean no_composite;
|
||||
gboolean no_force_fullscreen;
|
||||
gboolean no_tab_popup;
|
||||
gchar *introspect;
|
||||
} MetaArguments;
|
||||
@ -304,6 +308,12 @@ 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
|
||||
},
|
||||
{
|
||||
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
|
||||
&my_args.mutter_plugins,
|
||||
@ -331,6 +341,7 @@ meta_parse_options (int *argc, char ***argv,
|
||||
ctx = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (ctx, options, "mutter");
|
||||
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
|
||||
g_option_context_add_group (ctx, cogl_get_option_group ());
|
||||
|
||||
if (!g_option_context_parse (ctx, argc, argv, &error))
|
||||
{
|
||||
@ -436,37 +447,28 @@ meta_finalize (void)
|
||||
meta_session_shutdown ();
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void
|
||||
sigterm_handler (int signum)
|
||||
{
|
||||
meta_finalize ();
|
||||
|
||||
exit (meta_exit_code);
|
||||
}
|
||||
|
||||
static guint sigchld_signal_id = 0;
|
||||
|
||||
static void
|
||||
sigchld_handler (int signum, siginfo_t *info, void *context)
|
||||
{
|
||||
int stat;
|
||||
|
||||
if (info->si_code == CLD_EXITED)
|
||||
if (sigterm_pipe_fds[1] >= 0)
|
||||
{
|
||||
g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
|
||||
info->si_status,
|
||||
GINT_TO_POINTER (info->si_pid));
|
||||
int dummy;
|
||||
|
||||
dummy = write (sigterm_pipe_fds[1], "", 1);
|
||||
close (sigterm_pipe_fds[1]);
|
||||
sigterm_pipe_fds[1] = -1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
on_sigterm (void)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where the story begins. It parses commandline options and
|
||||
* environment variables, sets up the screen, hands control off to
|
||||
@ -489,8 +491,9 @@ main (int argc, char **argv)
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
GIOChannel *channel;
|
||||
GOptionContext *ctx;
|
||||
|
||||
|
||||
if (!g_thread_supported ())
|
||||
g_thread_init (NULL);
|
||||
|
||||
@ -512,29 +515,21 @@ 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"))
|
||||
@ -716,6 +711,9 @@ 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);
|
||||
|
@ -104,7 +104,7 @@ find_next_cascade (MetaWindow *window,
|
||||
int window_width, window_height;
|
||||
int cascade_stage;
|
||||
MetaRectangle work_area;
|
||||
const MetaXineramaScreenInfo* current;
|
||||
const MetaMonitorInfo* current;
|
||||
|
||||
sorted = g_list_copy (windows);
|
||||
sorted = g_list_sort (sorted, northwestcmp);
|
||||
@ -135,8 +135,8 @@ find_next_cascade (MetaWindow *window,
|
||||
* of NW corner of window frame.
|
||||
*/
|
||||
|
||||
current = meta_screen_get_current_xinerama (window->screen);
|
||||
meta_window_get_work_area_for_xinerama (window, current->number, &work_area);
|
||||
current = meta_screen_get_current_monitor (window->screen);
|
||||
meta_window_get_work_area_for_monitor (window, current->number, &work_area);
|
||||
|
||||
cascade_x = MAX (0, work_area.x);
|
||||
cascade_y = MAX (0, work_area.y);
|
||||
@ -257,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_xinerama (focus_window, &work_area);
|
||||
meta_window_get_work_area_current_monitor (focus_window, &work_area);
|
||||
meta_window_get_outer_rect (focus_window, &avoid);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
@ -508,7 +508,7 @@ find_first_fit (MetaWindow *window,
|
||||
MetaFrameGeometry *fgeom,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
int xinerama,
|
||||
int monitor,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
@ -551,16 +551,16 @@ find_first_fit (MetaWindow *window,
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
{
|
||||
char xinerama_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->xinerama_infos[xinerama].rect,
|
||||
xinerama_location_string);
|
||||
char monitor_location_string[RECT_LENGTH];
|
||||
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
|
||||
monitor_location_string);
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Natural xinerama is %s\n",
|
||||
xinerama_location_string);
|
||||
"Natural monitor is %s\n",
|
||||
monitor_location_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
meta_window_get_work_area_for_xinerama (window, xinerama, &work_area);
|
||||
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
|
||||
|
||||
center_tile_rect_in_area (&rect, &work_area);
|
||||
|
||||
@ -658,7 +658,7 @@ meta_window_place (MetaWindow *window,
|
||||
int *new_y)
|
||||
{
|
||||
GList *windows;
|
||||
const MetaXineramaScreenInfo *xi;
|
||||
const MetaMonitorInfo *xi;
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameGeometry. But remember fgeom == NULL
|
||||
@ -810,11 +810,11 @@ meta_window_place (MetaWindow *window,
|
||||
window->type == META_WINDOW_MODAL_DIALOG ||
|
||||
window->type == META_WINDOW_SPLASHSCREEN)
|
||||
{
|
||||
/* Center on current xinerama (i.e. on current monitor) */
|
||||
/* Center on current monitor */
|
||||
int w, h;
|
||||
|
||||
/* Warning, this function is a round trip! */
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
|
||||
w = xi->rect.width;
|
||||
h = xi->rect.height;
|
||||
@ -825,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 xinerama %d\n",
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
|
||||
window->desc, window->screen->number, xi->number);
|
||||
|
||||
goto done_check_denied_focus;
|
||||
@ -859,7 +859,7 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Warning, this is a round trip! */
|
||||
xi = meta_screen_get_current_xinerama (window->screen);
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
@ -880,9 +880,9 @@ meta_window_place (MetaWindow *window,
|
||||
MetaRectangle workarea;
|
||||
MetaRectangle outer;
|
||||
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
/* If the window is bigger than the screen, then automaximize. Do NOT
|
||||
|
287
src/core/prefs.c
287
src/core/prefs.c
@ -52,6 +52,7 @@
|
||||
#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"
|
||||
@ -62,6 +63,7 @@
|
||||
#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_"
|
||||
|
||||
#define KEY_CLUTTER_PLUGINS "/apps/mutter/general/clutter_plugins"
|
||||
@ -100,6 +102,7 @@ static char *cursor_theme = NULL;
|
||||
static int cursor_size = 24;
|
||||
static gboolean compositing_manager = FALSE;
|
||||
static gboolean resize_with_right_button = FALSE;
|
||||
static gboolean force_fullscreen = TRUE;
|
||||
|
||||
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
|
||||
static MetaButtonLayout button_layout;
|
||||
@ -121,13 +124,23 @@ static gboolean no_tab_popup = FALSE;
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
|
||||
|
||||
static gboolean update_key_binding (const char *name,
|
||||
static char *binding_name (const char *gconf_key);
|
||||
|
||||
static gboolean update_key_binding (const char *key,
|
||||
const char *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);
|
||||
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 update_command (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_workspace_name (const char *name,
|
||||
@ -142,14 +155,8 @@ static char* gconf_key_for_workspace_name (int i);
|
||||
|
||||
static void queue_changed (MetaPreference pref);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_LIST_OF_STRINGS,
|
||||
META_LIST_OF_GCONFVALUE_STRINGS
|
||||
} MetaStringListType;
|
||||
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
static gboolean update_list_binding (MetaKeyPref *binding,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value);
|
||||
|
||||
static void cleanup_error (GError **error);
|
||||
@ -1146,7 +1153,7 @@ change_notify (GConfClient *client,
|
||||
|
||||
list = value ? gconf_value_get_list (value) : NULL;
|
||||
|
||||
if (update_key_list_binding (key, list))
|
||||
if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
|
||||
queue_changed (META_PREF_KEYBINDINGS);
|
||||
}
|
||||
else
|
||||
@ -1800,6 +1807,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
|
||||
return "RESIZE_WITH_RIGHT_BUTTON";
|
||||
|
||||
case META_PREF_FORCE_FULLSCREEN:
|
||||
return "FORCE_FULLSCREEN";
|
||||
|
||||
case META_PREF_CLUTTER_PLUGINS:
|
||||
return "CLUTTER_PLUGINS";
|
||||
|
||||
@ -1888,57 +1898,64 @@ init_special_bindings (void)
|
||||
static void
|
||||
init_bindings (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
int i = 0;
|
||||
GError *err;
|
||||
#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;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
update_binding (&key_bindings[i],
|
||||
g_hash_table_lookup (to_update, key_bindings[i].name));
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
g_hash_table_destroy (to_update);
|
||||
|
||||
#else /* HAVE_GCONF */
|
||||
int i = 0;
|
||||
while (key_bindings[i].name)
|
||||
@ -1960,28 +1977,23 @@ static void
|
||||
init_commands (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_COMMANDS)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
entry = l->data;
|
||||
key = gconf_entry_get_key (entry);
|
||||
value = gconf_entry_get_value (entry);
|
||||
str_val = gconf_value_get_string (value);
|
||||
update_command (key, str_val);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_COMMANDS; i++)
|
||||
@ -1993,30 +2005,23 @@ static void
|
||||
init_workspace_names (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
int i;
|
||||
GError *err;
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_REASONABLE_WORKSPACES)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
g_assert (workspace_names[i] != NULL);
|
||||
|
||||
g_free (str_val);
|
||||
g_free (key);
|
||||
|
||||
++i;
|
||||
gconf_entry_free (entry);
|
||||
}
|
||||
g_slist_free (list);
|
||||
#else
|
||||
int i;
|
||||
for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
|
||||
@ -2275,16 +2280,22 @@ update_list_binding (MetaKeyPref *binding,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
relative_key (const gchar* key)
|
||||
static char *
|
||||
binding_name (const char *gconf_key)
|
||||
{
|
||||
const gchar* end;
|
||||
|
||||
end = strrchr (key, '/');
|
||||
const char *start, *end;
|
||||
|
||||
++end;
|
||||
if (*gconf_key == '/')
|
||||
start = strrchr (gconf_key, '/') + 1;
|
||||
else
|
||||
start = gconf_key;
|
||||
|
||||
return 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 value is TRUE if a preference changed and we need to
|
||||
@ -2292,22 +2303,19 @@ relative_key (const gchar* key)
|
||||
*/
|
||||
static gboolean
|
||||
find_and_update_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
const char *key;
|
||||
char *name = binding_name (key);
|
||||
int i;
|
||||
|
||||
if (*name == '/')
|
||||
key = relative_key (name);
|
||||
else
|
||||
key = name;
|
||||
|
||||
i = 0;
|
||||
while (bindings[i].name &&
|
||||
strcmp (key, bindings[i].name) != 0)
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_binding (&bindings[i], value);
|
||||
else
|
||||
@ -2315,46 +2323,40 @@ find_and_update_binding (MetaKeyPref *bindings,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_binding (const char *name,
|
||||
const char *value)
|
||||
update_key_binding (const char *key,
|
||||
const char *value)
|
||||
{
|
||||
return find_and_update_binding (key_bindings, name, value);
|
||||
return find_and_update_binding (key_bindings, key, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *name,
|
||||
GSList *value)
|
||||
find_and_update_list_binding (MetaKeyPref *bindings,
|
||||
const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
{
|
||||
const char *key;
|
||||
char *name = binding_name (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 (key, bindings[i].name) != 0)
|
||||
strcmp (name, bindings[i].name) != 0)
|
||||
++i;
|
||||
|
||||
g_free (name_without_suffix);
|
||||
g_free (name);
|
||||
|
||||
if (bindings[i].name)
|
||||
return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
|
||||
return update_list_binding (&bindings[i], value, type_of_value);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_key_list_binding (const char *name,
|
||||
GSList *value)
|
||||
update_key_list_binding (const char *key,
|
||||
GSList *value,
|
||||
MetaStringListType type_of_value)
|
||||
{
|
||||
return find_and_update_list_binding (key_bindings, name, value);
|
||||
return find_and_update_list_binding (key_bindings, key, value, type_of_value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -2792,6 +2794,12 @@ 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)
|
||||
{
|
||||
@ -2823,6 +2831,7 @@ 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,
|
||||
@ -2837,6 +2846,7 @@ meta_prefs_set_clutter_plugins (GSList *list)
|
||||
err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -2957,3 +2967,10 @@ init_button_layout(void)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_prefs_set_force_fullscreen (gboolean whether)
|
||||
{
|
||||
force_fullscreen = whether;
|
||||
}
|
||||
|
||||
|
@ -37,12 +37,11 @@
|
||||
#include "screen.h"
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "alttabhandler.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
|
||||
struct _MetaXineramaScreenInfo
|
||||
struct _MetaMonitorInfo
|
||||
{
|
||||
int number;
|
||||
MetaRectangle rect;
|
||||
@ -82,9 +81,8 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaAltTabHandler *tab_handler;
|
||||
MetaTabPopup *ws_popup;
|
||||
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
|
||||
MetaWorkspace *active_workspace;
|
||||
|
||||
/* This window holds the focus when we don't want to focus
|
||||
@ -105,11 +103,11 @@ struct _MetaScreen
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
MetaXineramaScreenInfo *xinerama_infos;
|
||||
int n_xinerama_infos;
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int n_monitor_infos;
|
||||
|
||||
/* Cache the current Xinerama */
|
||||
int last_xinerama_index;
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
SnMonitorContext *sn_context;
|
||||
@ -118,8 +116,9 @@ struct _MetaScreen
|
||||
#endif
|
||||
|
||||
Window wm_cm_selection_window;
|
||||
guint32 wm_cm_timestamp;
|
||||
|
||||
guint work_area_idle;
|
||||
guint work_area_later;
|
||||
|
||||
int rows_of_workspaces;
|
||||
int columns_of_workspaces;
|
||||
@ -131,9 +130,6 @@ struct _MetaScreen
|
||||
|
||||
int closing;
|
||||
|
||||
/* gc for XOR on root window */
|
||||
GC root_xor_gc;
|
||||
|
||||
/* Managed by compositor.c */
|
||||
gpointer compositor_data;
|
||||
|
||||
@ -147,7 +143,8 @@ struct _MetaScreenClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*restacked) (MetaScreen *);
|
||||
void (*restacked) (MetaScreen *);
|
||||
void (*workareas_changed) (MetaScreen *);
|
||||
};
|
||||
|
||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||
@ -185,19 +182,19 @@ void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
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_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_xinerama_neighbor (MetaScreen *screen,
|
||||
int which_xinerama,
|
||||
MetaScreenDirection dir);
|
||||
void meta_screen_get_natural_xinerama_list (MetaScreen *screen,
|
||||
int** xineramas_list,
|
||||
int* n_xineramas);
|
||||
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);
|
||||
|
||||
void meta_screen_update_workspace_layout (MetaScreen *screen);
|
||||
void meta_screen_update_workspace_names (MetaScreen *screen);
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "stack.h"
|
||||
#include "xprops.h"
|
||||
#include "compositor.h"
|
||||
#include "alttabhandlerdefault.h"
|
||||
#include "mutter-marshal.h"
|
||||
#include "mutter-enum-types.h"
|
||||
|
||||
@ -86,6 +85,7 @@ enum
|
||||
WORKSPACE_REMOVED,
|
||||
WORKSPACE_SWITCHED,
|
||||
STARTUP_SEQUENCE_CHANGED,
|
||||
WORKAREAS_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
@ -218,6 +218,15 @@ meta_screen_class_init (MetaScreenClass *klass)
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
screen_signals[WORKAREAS_CHANGED] =
|
||||
g_signal_new ("workareas-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (MetaScreenClass, workareas_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_N_WORKSPACES,
|
||||
pspec);
|
||||
@ -255,6 +264,13 @@ set_wm_check_hint (MetaScreen *screen)
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void
|
||||
unset_wm_check_hint (MetaScreen *screen)
|
||||
{
|
||||
XDeleteProperty (screen->display->xdisplay, screen->xroot,
|
||||
screen->display->atom__NET_SUPPORTING_WM_CHECK);
|
||||
}
|
||||
|
||||
static int
|
||||
set_supported_hint (MetaScreen *screen)
|
||||
{
|
||||
@ -299,7 +315,7 @@ set_wm_icon_size_hint (MetaScreen *screen)
|
||||
}
|
||||
|
||||
static void
|
||||
reload_xinerama_infos (MetaScreen *screen)
|
||||
reload_monitor_infos (MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
@ -319,35 +335,35 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
|
||||
display = screen->display;
|
||||
|
||||
if (screen->xinerama_infos)
|
||||
g_free (screen->xinerama_infos);
|
||||
if (screen->monitor_infos)
|
||||
g_free (screen->monitor_infos);
|
||||
|
||||
screen->xinerama_infos = NULL;
|
||||
screen->n_xinerama_infos = 0;
|
||||
screen->last_xinerama_index = 0;
|
||||
screen->monitor_infos = NULL;
|
||||
screen->n_monitor_infos = 0;
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
screen->display->xinerama_cache_invalidated = TRUE;
|
||||
screen->display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Pretending a single monitor has two Xinerama screens\n");
|
||||
|
||||
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 2);
|
||||
screen->n_xinerama_infos = 2;
|
||||
screen->monitor_infos = g_new (MetaMonitorInfo, 2);
|
||||
screen->n_monitor_infos = 2;
|
||||
|
||||
screen->xinerama_infos[0].number = 0;
|
||||
screen->xinerama_infos[0].rect = screen->rect;
|
||||
screen->xinerama_infos[0].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
|
||||
|
||||
screen->xinerama_infos[1].number = 1;
|
||||
screen->xinerama_infos[1].rect = screen->rect;
|
||||
screen->xinerama_infos[1].rect.x = screen->rect.width / 2;
|
||||
screen->xinerama_infos[1].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[1].number = 1;
|
||||
screen->monitor_infos[1].rect = screen->rect;
|
||||
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
|
||||
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XFREE_XINERAMA
|
||||
if (screen->n_xinerama_infos == 0 &&
|
||||
if (screen->n_monitor_infos == 0 &&
|
||||
XineramaIsActive (display->xdisplay))
|
||||
{
|
||||
XineramaScreenInfo *infos;
|
||||
@ -363,25 +379,25 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
|
||||
if (n_infos > 0)
|
||||
{
|
||||
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_infos);
|
||||
screen->n_xinerama_infos = n_infos;
|
||||
screen->monitor_infos = g_new (MetaMonitorInfo, n_infos);
|
||||
screen->n_monitor_infos = n_infos;
|
||||
|
||||
i = 0;
|
||||
while (i < n_infos)
|
||||
{
|
||||
screen->xinerama_infos[i].number = infos[i].screen_number;
|
||||
screen->xinerama_infos[i].rect.x = infos[i].x_org;
|
||||
screen->xinerama_infos[i].rect.y = infos[i].y_org;
|
||||
screen->xinerama_infos[i].rect.width = infos[i].width;
|
||||
screen->xinerama_infos[i].rect.height = infos[i].height;
|
||||
screen->monitor_infos[i].number = infos[i].screen_number;
|
||||
screen->monitor_infos[i].rect.x = infos[i].x_org;
|
||||
screen->monitor_infos[i].rect.y = infos[i].y_org;
|
||||
screen->monitor_infos[i].rect.width = infos[i].width;
|
||||
screen->monitor_infos[i].rect.height = infos[i].height;
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Xinerama %d is %d,%d %d x %d\n",
|
||||
screen->xinerama_infos[i].number,
|
||||
screen->xinerama_infos[i].rect.x,
|
||||
screen->xinerama_infos[i].rect.y,
|
||||
screen->xinerama_infos[i].rect.width,
|
||||
screen->xinerama_infos[i].rect.height);
|
||||
"Monitor %d is %d,%d %d x %d\n",
|
||||
screen->monitor_infos[i].number,
|
||||
screen->monitor_infos[i].rect.x,
|
||||
screen->monitor_infos[i].rect.y,
|
||||
screen->monitor_infos[i].rect.width,
|
||||
screen->monitor_infos[i].rect.height);
|
||||
|
||||
++i;
|
||||
}
|
||||
@ -389,7 +405,7 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
|
||||
meta_XFree (infos);
|
||||
}
|
||||
else if (screen->n_xinerama_infos > 0)
|
||||
else if (screen->n_monitor_infos > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No XFree86 Xinerama extension or XFree86 Xinerama inactive on display %s\n",
|
||||
@ -402,7 +418,7 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
|
||||
#ifdef HAVE_SOLARIS_XINERAMA
|
||||
/* This code from GDK, Copyright (C) 2002 Sun Microsystems */
|
||||
if (screen->n_xinerama_infos == 0 &&
|
||||
if (screen->n_monitor_infos == 0 &&
|
||||
XineramaGetState (screen->display->xdisplay,
|
||||
screen->number))
|
||||
{
|
||||
@ -424,31 +440,31 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
{
|
||||
g_assert (n_monitors > 0);
|
||||
|
||||
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_monitors);
|
||||
screen->n_xinerama_infos = n_monitors;
|
||||
screen->monitor_infos = g_new (MetaMonitorInfo, n_monitors);
|
||||
screen->n_monitor_infos = n_monitors;
|
||||
|
||||
i = 0;
|
||||
while (i < n_monitors)
|
||||
{
|
||||
screen->xinerama_infos[i].number = i;
|
||||
screen->xinerama_infos[i].rect.x = monitors[i].x;
|
||||
screen->xinerama_infos[i].rect.y = monitors[i].y;
|
||||
screen->xinerama_infos[i].rect.width = monitors[i].width;
|
||||
screen->xinerama_infos[i].rect.height = monitors[i].height;
|
||||
screen->monitor_infos[i].number = i;
|
||||
screen->monitor_infos[i].rect.x = monitors[i].x;
|
||||
screen->monitor_infos[i].rect.y = monitors[i].y;
|
||||
screen->monitor_infos[i].rect.width = monitors[i].width;
|
||||
screen->monitor_infos[i].rect.height = monitors[i].height;
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Xinerama %d is %d,%d %d x %d\n",
|
||||
screen->xinerama_infos[i].number,
|
||||
screen->xinerama_infos[i].rect.x,
|
||||
screen->xinerama_infos[i].rect.y,
|
||||
screen->xinerama_infos[i].rect.width,
|
||||
screen->xinerama_infos[i].rect.height);
|
||||
"Monitor %d is %d,%d %d x %d\n",
|
||||
screen->monitor_infos[i].number,
|
||||
screen->monitor_infos[i].rect.x,
|
||||
screen->monitor_infos[i].rect.y,
|
||||
screen->monitor_infos[i].rect.width,
|
||||
screen->monitor_infos[i].rect.height);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (screen->n_xinerama_infos == 0)
|
||||
else if (screen->n_monitor_infos == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Solaris Xinerama extension or Solaris Xinerama inactive on display %s\n",
|
||||
@ -463,20 +479,20 @@ reload_xinerama_infos (MetaScreen *screen)
|
||||
/* If no Xinerama, fill in the single screen info so
|
||||
* we can use the field unconditionally
|
||||
*/
|
||||
if (screen->n_xinerama_infos == 0)
|
||||
if (screen->n_monitor_infos == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Xinerama screens, using default screen info\n");
|
||||
|
||||
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 1);
|
||||
screen->n_xinerama_infos = 1;
|
||||
screen->monitor_infos = g_new (MetaMonitorInfo, 1);
|
||||
screen->n_monitor_infos = 1;
|
||||
|
||||
screen->xinerama_infos[0].number = 0;
|
||||
screen->xinerama_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
}
|
||||
|
||||
g_assert (screen->n_xinerama_infos > 0);
|
||||
g_assert (screen->xinerama_infos != NULL);
|
||||
g_assert (screen->n_monitor_infos > 0);
|
||||
g_assert (screen->monitor_infos != NULL);
|
||||
}
|
||||
|
||||
/* The guard window allows us to leave minimized windows mapped so
|
||||
@ -687,7 +703,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay,
|
||||
xroot,
|
||||
NoEventMask);
|
||||
screen->work_area_idle = 0;
|
||||
screen->work_area_later = 0;
|
||||
|
||||
screen->active_workspace = NULL;
|
||||
screen->workspaces = NULL;
|
||||
@ -698,40 +714,11 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->compositor_data = NULL;
|
||||
screen->guard_window = None;
|
||||
|
||||
{
|
||||
XFontStruct *font_info;
|
||||
XGCValues gc_values;
|
||||
gulong value_mask = 0;
|
||||
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
value_mask |= GCSubwindowMode;
|
||||
gc_values.function = GXinvert;
|
||||
value_mask |= GCFunction;
|
||||
gc_values.line_width = META_WIREFRAME_XOR_LINE_WIDTH;
|
||||
value_mask |= GCLineWidth;
|
||||
|
||||
font_info = XLoadQueryFont (screen->display->xdisplay, "fixed");
|
||||
|
||||
if (font_info != NULL)
|
||||
{
|
||||
gc_values.font = font_info->fid;
|
||||
value_mask |= GCFont;
|
||||
XFreeFontInfo (NULL, font_info, 1);
|
||||
}
|
||||
else
|
||||
meta_warning ("xserver doesn't have 'fixed' font.\n");
|
||||
|
||||
screen->root_xor_gc = XCreateGC (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
value_mask,
|
||||
&gc_values);
|
||||
}
|
||||
screen->monitor_infos = NULL;
|
||||
screen->n_monitor_infos = 0;
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
screen->xinerama_infos = NULL;
|
||||
screen->n_xinerama_infos = 0;
|
||||
screen->last_xinerama_index = 0;
|
||||
|
||||
reload_xinerama_infos (screen);
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
|
||||
@ -781,9 +768,9 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_handler = NULL;
|
||||
screen->tab_popup = NULL;
|
||||
screen->ws_popup = NULL;
|
||||
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
screen->stack_tracker = meta_stack_tracker_new (screen);
|
||||
|
||||
@ -822,7 +809,6 @@ meta_screen_free (MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
XGCValues gc_values = { 0 };
|
||||
|
||||
display = screen->display;
|
||||
|
||||
@ -871,27 +857,16 @@ meta_screen_free (MetaScreen *screen,
|
||||
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
|
||||
screen->number, screen->display->name);
|
||||
|
||||
unset_wm_check_hint (screen);
|
||||
|
||||
XDestroyWindow (screen->display->xdisplay,
|
||||
screen->wm_sn_selection_window);
|
||||
|
||||
if (screen->work_area_idle != 0)
|
||||
g_source_remove (screen->work_area_idle);
|
||||
if (screen->work_area_later != 0)
|
||||
g_source_remove (screen->work_area_later);
|
||||
|
||||
|
||||
if (XGetGCValues (screen->display->xdisplay,
|
||||
screen->root_xor_gc,
|
||||
GCFont,
|
||||
&gc_values))
|
||||
{
|
||||
XUnloadFont (screen->display->xdisplay,
|
||||
gc_values.font);
|
||||
}
|
||||
|
||||
XFreeGC (screen->display->xdisplay,
|
||||
screen->root_xor_gc);
|
||||
|
||||
if (screen->xinerama_infos)
|
||||
g_free (screen->xinerama_infos);
|
||||
if (screen->monitor_infos)
|
||||
g_free (screen->monitor_infos);
|
||||
|
||||
g_free (screen->screen_name);
|
||||
|
||||
@ -1516,58 +1491,146 @@ meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GList *tab_list;
|
||||
GList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (screen->tab_handler == NULL);
|
||||
|
||||
screen->tab_handler = meta_alt_tab_handler_new (screen,
|
||||
show_type == META_TAB_SHOW_INSTANTLY);
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_display_get_tab_list (screen->display,
|
||||
list_type,
|
||||
screen,
|
||||
screen->active_workspace);
|
||||
|
||||
for (tmp = tab_list; tmp; tmp = tmp->next)
|
||||
meta_alt_tab_handler_add_window (screen->tab_handler, tmp->data);
|
||||
|
||||
meta_alt_tab_handler_show (screen->tab_handler, initial_selection);
|
||||
|
||||
len = g_list_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) window;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = g_object_ref (window->icon);
|
||||
entries[i].blank = FALSE;
|
||||
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_outer_rect (window, &r);
|
||||
|
||||
entries[i].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 (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entries[i].inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
|
||||
entries[i].inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entries[i].inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
++i;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (!meta_prefs_get_no_tab_popup ())
|
||||
screen->tab_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
g_object_unref (entries[i].icon);
|
||||
|
||||
g_free (entries);
|
||||
|
||||
g_list_free (tab_list);
|
||||
|
||||
meta_ui_tab_popup_select (screen->tab_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
|
||||
if (show_type != META_TAB_SHOW_INSTANTLY)
|
||||
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_forward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_handler != NULL);
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_alt_tab_handler_forward (screen->tab_handler);
|
||||
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_backward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_handler != NULL);
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_alt_tab_handler_backward (screen->tab_handler);
|
||||
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_screen_tab_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->tab_handler != NULL, NULL);
|
||||
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
|
||||
|
||||
return meta_alt_tab_handler_get_selected (screen->tab_handler);
|
||||
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (!screen->tab_handler)
|
||||
return;
|
||||
|
||||
meta_alt_tab_handler_destroy (screen->tab_handler);
|
||||
g_object_unref (screen->tab_handler);
|
||||
screen->tab_handler = NULL;
|
||||
if (screen->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->tab_popup);
|
||||
screen->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1580,8 +1643,9 @@ meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspaceLayout layout;
|
||||
int n_workspaces;
|
||||
int current_workspace;
|
||||
|
||||
g_return_if_fail (screen->ws_popup == NULL);
|
||||
|
||||
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
|
||||
return;
|
||||
|
||||
current_workspace = meta_workspace_index (screen->active_workspace);
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
@ -1703,61 +1767,61 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
return window;
|
||||
}
|
||||
|
||||
const MetaXineramaScreenInfo*
|
||||
meta_screen_get_xinerama_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect)
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_monitor_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
int i;
|
||||
int best_xinerama, xinerama_score;
|
||||
int best_monitor, monitor_score;
|
||||
|
||||
if (screen->n_xinerama_infos == 1)
|
||||
return &screen->xinerama_infos[0];
|
||||
if (screen->n_monitor_infos == 1)
|
||||
return &screen->monitor_infos[0];
|
||||
|
||||
best_xinerama = 0;
|
||||
xinerama_score = 0;
|
||||
best_monitor = 0;
|
||||
monitor_score = 0;
|
||||
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
MetaRectangle dest;
|
||||
if (meta_rectangle_intersect (&screen->xinerama_infos[i].rect,
|
||||
if (meta_rectangle_intersect (&screen->monitor_infos[i].rect,
|
||||
rect,
|
||||
&dest))
|
||||
{
|
||||
int cur = meta_rectangle_area (&dest);
|
||||
if (cur > xinerama_score)
|
||||
if (cur > monitor_score)
|
||||
{
|
||||
xinerama_score = cur;
|
||||
best_xinerama = i;
|
||||
monitor_score = cur;
|
||||
best_monitor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &screen->xinerama_infos[best_xinerama];
|
||||
return &screen->monitor_infos[best_monitor];
|
||||
}
|
||||
|
||||
const MetaXineramaScreenInfo*
|
||||
meta_screen_get_xinerama_for_window (MetaScreen *screen,
|
||||
MetaWindow *window)
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
|
||||
return meta_screen_get_xinerama_for_rect (screen, &window_rect);
|
||||
return meta_screen_get_monitor_for_rect (screen, &window_rect);
|
||||
}
|
||||
|
||||
const MetaXineramaScreenInfo*
|
||||
meta_screen_get_xinerama_neighbor (MetaScreen *screen,
|
||||
int which_xinerama,
|
||||
MetaScreenDirection direction)
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_monitor_neighbor (MetaScreen *screen,
|
||||
int which_monitor,
|
||||
MetaScreenDirection direction)
|
||||
{
|
||||
MetaXineramaScreenInfo* input = screen->xinerama_infos + which_xinerama;
|
||||
MetaXineramaScreenInfo* current;
|
||||
MetaMonitorInfo* input = screen->monitor_infos + which_monitor;
|
||||
MetaMonitorInfo* current;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
current = screen->xinerama_infos + i;
|
||||
current = screen->monitor_infos + i;
|
||||
|
||||
if ((direction == META_SCREEN_RIGHT &&
|
||||
current->rect.x == input->rect.x + input->rect.width &&
|
||||
@ -1780,110 +1844,110 @@ meta_screen_get_xinerama_neighbor (MetaScreen *screen,
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_get_natural_xinerama_list (MetaScreen *screen,
|
||||
int** xineramas_list,
|
||||
int* n_xineramas)
|
||||
meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
int** monitors_list,
|
||||
int* n_monitors)
|
||||
{
|
||||
const MetaXineramaScreenInfo* current;
|
||||
const MetaXineramaScreenInfo* tmp;
|
||||
GQueue* xinerama_queue;
|
||||
const MetaMonitorInfo* current;
|
||||
const MetaMonitorInfo* tmp;
|
||||
GQueue* monitor_queue;
|
||||
int* visited;
|
||||
int cur = 0;
|
||||
int i;
|
||||
|
||||
*n_xineramas = screen->n_xinerama_infos;
|
||||
*xineramas_list = g_new (int, screen->n_xinerama_infos);
|
||||
*n_monitors = screen->n_monitor_infos;
|
||||
*monitors_list = g_new (int, screen->n_monitor_infos);
|
||||
|
||||
/* we calculate a natural ordering by which to choose xineramas for
|
||||
* window placement. We start at the current xinerama, and perform
|
||||
* a breadth-first search of the xineramas starting from that
|
||||
* xinerama. We choose preferentially left, then right, then down,
|
||||
/* we calculate a natural ordering by which to choose monitors for
|
||||
* window placement. We start at the current monitor, and perform
|
||||
* a breadth-first search of the monitors starting from that
|
||||
* monitor. We choose preferentially left, then right, then down,
|
||||
* then up. The visitation order produced by this traversal is the
|
||||
* natural xinerama ordering.
|
||||
* natural monitor ordering.
|
||||
*/
|
||||
|
||||
visited = g_new (int, screen->n_xinerama_infos);
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
visited = g_new (int, screen->n_monitor_infos);
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
visited[i] = FALSE;
|
||||
}
|
||||
|
||||
current = meta_screen_get_current_xinerama (screen);
|
||||
xinerama_queue = g_queue_new ();
|
||||
g_queue_push_tail (xinerama_queue, (gpointer) current);
|
||||
current = meta_screen_get_current_monitor (screen);
|
||||
monitor_queue = g_queue_new ();
|
||||
g_queue_push_tail (monitor_queue, (gpointer) current);
|
||||
visited[current->number] = TRUE;
|
||||
|
||||
while (!g_queue_is_empty (xinerama_queue))
|
||||
while (!g_queue_is_empty (monitor_queue))
|
||||
{
|
||||
current = (const MetaXineramaScreenInfo*)
|
||||
g_queue_pop_head (xinerama_queue);
|
||||
current = (const MetaMonitorInfo*)
|
||||
g_queue_pop_head (monitor_queue);
|
||||
|
||||
(*xineramas_list)[cur++] = current->number;
|
||||
(*monitors_list)[cur++] = current->number;
|
||||
|
||||
/* enqueue each of the directions */
|
||||
tmp = meta_screen_get_xinerama_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_LEFT);
|
||||
tmp = meta_screen_get_monitor_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_LEFT);
|
||||
if (tmp && !visited[tmp->number])
|
||||
{
|
||||
g_queue_push_tail (xinerama_queue,
|
||||
(MetaXineramaScreenInfo*) tmp);
|
||||
g_queue_push_tail (monitor_queue,
|
||||
(MetaMonitorInfo*) tmp);
|
||||
visited[tmp->number] = TRUE;
|
||||
}
|
||||
tmp = meta_screen_get_xinerama_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_RIGHT);
|
||||
tmp = meta_screen_get_monitor_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_RIGHT);
|
||||
if (tmp && !visited[tmp->number])
|
||||
{
|
||||
g_queue_push_tail (xinerama_queue,
|
||||
(MetaXineramaScreenInfo*) tmp);
|
||||
g_queue_push_tail (monitor_queue,
|
||||
(MetaMonitorInfo*) tmp);
|
||||
visited[tmp->number] = TRUE;
|
||||
}
|
||||
tmp = meta_screen_get_xinerama_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_UP);
|
||||
tmp = meta_screen_get_monitor_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_UP);
|
||||
if (tmp && !visited[tmp->number])
|
||||
{
|
||||
g_queue_push_tail (xinerama_queue,
|
||||
(MetaXineramaScreenInfo*) tmp);
|
||||
g_queue_push_tail (monitor_queue,
|
||||
(MetaMonitorInfo*) tmp);
|
||||
visited[tmp->number] = TRUE;
|
||||
}
|
||||
tmp = meta_screen_get_xinerama_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_DOWN);
|
||||
tmp = meta_screen_get_monitor_neighbor (screen,
|
||||
current->number,
|
||||
META_SCREEN_DOWN);
|
||||
if (tmp && !visited[tmp->number])
|
||||
{
|
||||
g_queue_push_tail (xinerama_queue,
|
||||
(MetaXineramaScreenInfo*) tmp);
|
||||
g_queue_push_tail (monitor_queue,
|
||||
(MetaMonitorInfo*) tmp);
|
||||
visited[tmp->number] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* in case we somehow missed some set of xineramas, go through the
|
||||
* visited list and add in any xineramas that were missed
|
||||
/* in case we somehow missed some set of monitors, go through the
|
||||
* visited list and add in any monitors that were missed
|
||||
*/
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
if (visited[i] == FALSE)
|
||||
{
|
||||
(*xineramas_list)[cur++] = i;
|
||||
(*monitors_list)[cur++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (visited);
|
||||
g_queue_free (xinerama_queue);
|
||||
g_queue_free (monitor_queue);
|
||||
}
|
||||
|
||||
const MetaXineramaScreenInfo*
|
||||
meta_screen_get_current_xinerama (MetaScreen *screen)
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
{
|
||||
if (screen->n_xinerama_infos == 1)
|
||||
return &screen->xinerama_infos[0];
|
||||
if (screen->n_monitor_infos == 1)
|
||||
return &screen->monitor_infos[0];
|
||||
|
||||
/* Sadly, we have to do it this way. Yuck.
|
||||
*/
|
||||
|
||||
if (screen->display->xinerama_cache_invalidated)
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
Window root_return, child_return;
|
||||
int win_x_return, win_y_return;
|
||||
@ -1891,7 +1955,7 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
|
||||
int i;
|
||||
MetaRectangle pointer_position;
|
||||
|
||||
screen->display->xinerama_cache_invalidated = FALSE;
|
||||
screen->display->monitor_cache_invalidated = FALSE;
|
||||
|
||||
pointer_position.width = pointer_position.height = 1;
|
||||
XQueryPointer (screen->display->xdisplay,
|
||||
@ -1904,23 +1968,59 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
|
||||
&win_y_return,
|
||||
&mask_return);
|
||||
|
||||
screen->last_xinerama_index = 0;
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
screen->last_monitor_index = 0;
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
if (meta_rectangle_contains_rect (&screen->xinerama_infos[i].rect,
|
||||
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
|
||||
&pointer_position))
|
||||
{
|
||||
screen->last_xinerama_index = i;
|
||||
screen->last_monitor_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Rechecked current Xinerama, now %d\n",
|
||||
screen->last_xinerama_index);
|
||||
"Rechecked current monitor, now %d\n",
|
||||
screen->last_monitor_index);
|
||||
}
|
||||
|
||||
return &screen->xinerama_infos[screen->last_xinerama_index];
|
||||
return &screen->monitor_infos[screen->last_monitor_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_screen_get_n_monitors:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Gets the number of monitors that are joined together to form @screen.
|
||||
*
|
||||
* Return value: the number of monitors
|
||||
*/
|
||||
int
|
||||
meta_screen_get_n_monitors (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_SCREEN (screen), 0);
|
||||
|
||||
return screen->n_monitor_infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_screen_get_monitor_geometry:
|
||||
* @screen: a #MetaScreen
|
||||
* @monitor: the monitor number
|
||||
* @geometry: (out): location to store the monitor geometry
|
||||
*
|
||||
* Stores the location and size of the indicated monitor in @geometry.
|
||||
*/
|
||||
void
|
||||
meta_screen_get_monitor_geometry (MetaScreen *screen,
|
||||
int monitor,
|
||||
MetaRectangle *geometry)
|
||||
{
|
||||
g_return_if_fail (META_IS_SCREEN (screen));
|
||||
g_return_if_fail (monitor >= 0 && monitor < screen->n_monitor_infos);
|
||||
g_return_if_fail (geometry != NULL);
|
||||
|
||||
*geometry = screen->monitor_infos[monitor].rect;
|
||||
}
|
||||
|
||||
#define _NET_WM_ORIENTATION_HORZ 0
|
||||
@ -2145,7 +2245,7 @@ set_work_area_hint (MetaScreen *screen)
|
||||
|
||||
if (workspace->screen == screen)
|
||||
{
|
||||
meta_workspace_get_work_area_all_xineramas (workspace, &area);
|
||||
meta_workspace_get_work_area_all_monitors (workspace, &area);
|
||||
tmp[0] = area.x;
|
||||
tmp[1] = area.y;
|
||||
tmp[2] = area.width;
|
||||
@ -2164,15 +2264,17 @@ set_work_area_hint (MetaScreen *screen)
|
||||
(guchar*) data, num_workspaces*4);
|
||||
g_free (data);
|
||||
meta_error_trap_pop (screen->display, FALSE);
|
||||
|
||||
g_signal_emit (screen, screen_signals[WORKAREAS_CHANGED], 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_work_area_idle_func (MetaScreen *screen)
|
||||
set_work_area_later_func (MetaScreen *screen)
|
||||
{
|
||||
meta_topic (META_DEBUG_WORKAREA,
|
||||
"Running work area idle function\n");
|
||||
"Running work area hint computation function\n");
|
||||
|
||||
screen->work_area_idle = 0;
|
||||
screen->work_area_later = 0;
|
||||
|
||||
set_work_area_hint (screen);
|
||||
|
||||
@ -2182,16 +2284,16 @@ set_work_area_idle_func (MetaScreen *screen)
|
||||
void
|
||||
meta_screen_queue_workarea_recalc (MetaScreen *screen)
|
||||
{
|
||||
/* Recompute work area in an idle */
|
||||
if (screen->work_area_idle == 0)
|
||||
/* Recompute work area later before redrawing */
|
||||
if (screen->work_area_later == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_WORKAREA,
|
||||
"Adding work area hint idle function\n");
|
||||
screen->work_area_idle =
|
||||
g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
|
||||
(GSourceFunc) set_work_area_idle_func,
|
||||
screen,
|
||||
NULL);
|
||||
"Adding work area hint computation function\n");
|
||||
screen->work_area_later =
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
(GSourceFunc) set_work_area_later_func,
|
||||
screen,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2513,7 +2615,7 @@ meta_screen_resize (MetaScreen *screen,
|
||||
screen->rect.width = width;
|
||||
screen->rect.height = height;
|
||||
|
||||
reload_xinerama_infos (screen);
|
||||
reload_monitor_infos (screen);
|
||||
set_desktop_geometry_hint (screen);
|
||||
|
||||
if (screen->display->compositor)
|
||||
@ -3043,11 +3145,14 @@ meta_screen_set_cm_selection (MetaScreen *screen)
|
||||
char selection[32];
|
||||
Atom a;
|
||||
|
||||
screen->wm_cm_timestamp = meta_display_get_current_time_roundtrip (
|
||||
screen->display);
|
||||
|
||||
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
|
||||
meta_verbose ("Setting selection: %s\n", selection);
|
||||
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
|
||||
XSetSelectionOwner (screen->display->xdisplay, a,
|
||||
screen->wm_cm_selection_window, CurrentTime);
|
||||
screen->wm_cm_selection_window, screen->wm_cm_timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3058,7 +3163,8 @@ meta_screen_unset_cm_selection (MetaScreen *screen)
|
||||
|
||||
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
|
||||
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
|
||||
XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime);
|
||||
XSetSelectionOwner (screen->display->xdisplay, a,
|
||||
None, screen->wm_cm_timestamp);
|
||||
}
|
||||
|
||||
GList *
|
||||
@ -3078,6 +3184,11 @@ meta_screen_get_active_workspace_index (MetaScreen *screen)
|
||||
return meta_workspace_index (active);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_screen_get_active_workspace:
|
||||
*
|
||||
* Returns: (transfer none): The current workspace
|
||||
*/
|
||||
MetaWorkspace *
|
||||
meta_screen_get_active_workspace (MetaScreen *screen)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifndef HAVE_SM
|
||||
void
|
||||
@ -83,6 +84,7 @@ 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
|
||||
@ -105,9 +107,12 @@ process_ice_messages (GIOChannel *channel,
|
||||
IcePointer context = IceGetConnectionContext (connection);
|
||||
#endif
|
||||
|
||||
/* We were disconnected */
|
||||
IceSetShutdownNegotiation (connection, False);
|
||||
IceCloseConnection (connection);
|
||||
/* 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);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -1104,8 +1109,6 @@ 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);
|
||||
@ -1749,11 +1752,11 @@ finish_interact (gboolean shutdown)
|
||||
}
|
||||
|
||||
static void
|
||||
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
|
||||
dialog_closed (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
gboolean shutdown = GPOINTER_TO_INT (user_data);
|
||||
|
||||
if (arg1 == 0) /* pressed "OK" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 0) /* pressed "OK" */
|
||||
{
|
||||
finish_interact (shutdown);
|
||||
}
|
||||
@ -1767,6 +1770,7 @@ 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);
|
||||
tmp = windows;
|
||||
@ -1814,23 +1818,20 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
||||
}
|
||||
g_slist_free (lame);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
g_slist_free (lame_details);
|
||||
|
||||
g_signal_connect (sigchld_nexus, "sigchld",
|
||||
G_CALLBACK (sigchld_handler),
|
||||
GINT_TO_POINTER (shutdown));
|
||||
|
||||
g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown));
|
||||
}
|
||||
|
||||
#endif /* HAVE_SM */
|
||||
|
@ -134,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_idle;
|
||||
guint sync_stack_later;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -383,8 +383,8 @@ meta_stack_tracker_new (MetaScreen *screen)
|
||||
void
|
||||
meta_stack_tracker_free (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle)
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
if (tracker->sync_stack_later)
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
|
||||
g_array_free (tracker->server_stack, TRUE);
|
||||
if (tracker->predicted_stack)
|
||||
@ -667,10 +667,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
int n_windows;
|
||||
int i;
|
||||
|
||||
if (tracker->sync_stack_idle)
|
||||
if (tracker->sync_stack_later)
|
||||
{
|
||||
g_source_remove (tracker->sync_stack_idle);
|
||||
tracker->sync_stack_idle = 0;
|
||||
meta_later_remove (tracker->sync_stack_later);
|
||||
tracker->sync_stack_later = 0;
|
||||
}
|
||||
|
||||
meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
|
||||
@ -696,7 +696,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stack_tracker_sync_stack_idle (gpointer data)
|
||||
stack_tracker_sync_stack_later (gpointer data)
|
||||
{
|
||||
meta_stack_tracker_sync_stack (data);
|
||||
|
||||
@ -719,10 +719,10 @@ stack_tracker_sync_stack_idle (gpointer data)
|
||||
void
|
||||
meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
|
||||
{
|
||||
if (tracker->sync_stack_idle == 0)
|
||||
if (tracker->sync_stack_later == 0)
|
||||
{
|
||||
tracker->sync_stack_idle = g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_idle,
|
||||
tracker->sync_stack_later = meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
stack_tracker_sync_stack_later,
|
||||
tracker, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -224,14 +224,14 @@ is_focused_foreach (MetaWindow *window,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
windows_on_different_xinerama (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
windows_on_different_monitor (MetaWindow *a,
|
||||
MetaWindow *b)
|
||||
{
|
||||
if (a->screen != b->screen)
|
||||
return TRUE;
|
||||
|
||||
return meta_screen_get_xinerama_for_window (a->screen, a) !=
|
||||
meta_screen_get_xinerama_for_window (b->screen, b);
|
||||
return meta_screen_get_monitor_for_window (a->screen, a) !=
|
||||
meta_screen_get_monitor_for_window (b->screen, b);
|
||||
}
|
||||
|
||||
/* Get layer ignoring any transient or group relationships */
|
||||
@ -275,8 +275,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_xinerama (window,
|
||||
window->display->expected_focus_window))))
|
||||
windows_on_different_monitor (window,
|
||||
window->display->expected_focus_window))))
|
||||
layer = META_LAYER_FULLSCREEN;
|
||||
else if (window->wm_state_above)
|
||||
layer = META_LAYER_TOP;
|
||||
|
@ -85,7 +85,7 @@ new_screen_edge (int x, int y, int width, int height, int side_type)
|
||||
}
|
||||
|
||||
static MetaEdge*
|
||||
new_xinerama_edge (int x, int y, int width, int height, int side_type)
|
||||
new_monitor_edge (int x, int y, int width, int height, int side_type)
|
||||
{
|
||||
MetaEdge* temporary;
|
||||
temporary = g_new (MetaEdge, 1);
|
||||
@ -94,7 +94,7 @@ new_xinerama_edge (int x, int y, int width, int height, int side_type)
|
||||
temporary->rect.width = width;
|
||||
temporary->rect.height = height;
|
||||
temporary->side_type = side_type;
|
||||
temporary->edge_type = META_EDGE_XINERAMA;
|
||||
temporary->edge_type = META_EDGE_MONITOR;
|
||||
|
||||
return temporary;
|
||||
}
|
||||
@ -317,15 +317,15 @@ get_screen_edges (int which)
|
||||
}
|
||||
|
||||
static GList*
|
||||
get_xinerama_edges (int which_xinerama_set, int which_strut_set)
|
||||
get_monitor_edges (int which_monitor_set, int which_strut_set)
|
||||
{
|
||||
GList *ret;
|
||||
GSList *struts;
|
||||
GList *xins;
|
||||
|
||||
xins = NULL;
|
||||
g_assert (which_xinerama_set >=0 && which_xinerama_set <= 3);
|
||||
switch (which_xinerama_set)
|
||||
g_assert (which_monitor_set >=0 && which_monitor_set <= 3);
|
||||
switch (which_monitor_set)
|
||||
{
|
||||
case 0:
|
||||
xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 1200));
|
||||
@ -348,7 +348,7 @@ get_xinerama_edges (int which_xinerama_set, int which_strut_set)
|
||||
ret = NULL;
|
||||
|
||||
struts = get_strut_list (which_strut_set);
|
||||
ret = meta_rectangle_find_nonintersected_xinerama_edges (xins, struts);
|
||||
ret = meta_rectangle_find_nonintersected_monitor_edges (xins, struts);
|
||||
|
||||
free_strut_list (struts);
|
||||
meta_rectangle_free_list_and_elements (xins);
|
||||
@ -1145,7 +1145,7 @@ test_find_onscreen_edges ()
|
||||
}
|
||||
|
||||
static void
|
||||
test_find_nonintersected_xinerama_edges ()
|
||||
test_find_nonintersected_monitor_edges ()
|
||||
{
|
||||
GList* edges;
|
||||
GList* tmp;
|
||||
@ -1156,32 +1156,32 @@ test_find_nonintersected_xinerama_edges ()
|
||||
int bottom = META_DIRECTION_BOTTOM;
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 0 for with region 0 has the correct edges */
|
||||
/* Make sure test monitor set 0 for with region 0 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (0, 0);
|
||||
edges = get_monitor_edges (0, 0);
|
||||
tmp = NULL;
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 2 for with region 1 has the correct edges */
|
||||
/* Make sure test monitor set 2 for with region 1 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (2, 1);
|
||||
edges = get_monitor_edges (2, 1);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, top));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 1 for with region 2 has the correct edges */
|
||||
/* Make sure test monitor set 1 for with region 2 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (1, 2);
|
||||
edges = get_monitor_edges (1, 2);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1080, right));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1180, left));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1080, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1180, left));
|
||||
#if 0
|
||||
#define FUDGE 50
|
||||
char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE];
|
||||
@ -1195,36 +1195,36 @@ test_find_nonintersected_xinerama_edges ()
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 3 has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 3 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 3);
|
||||
edges = get_monitor_edges (3, 3);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 425, right));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 525, left));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 425, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 525, left));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 4 has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 4 has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 4);
|
||||
edges = get_monitor_edges (3, 4);
|
||||
tmp = NULL;
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 0, 600, right));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, bottom));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, top));
|
||||
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 0, 600, right));
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
meta_rectangle_free_list_and_elements (edges);
|
||||
|
||||
/*************************************************************************/
|
||||
/* Make sure test xinerama set 3 for with region 5has the correct edges */
|
||||
/* Make sure test monitor set 3 for with region 5has the correct edges */
|
||||
/*************************************************************************/
|
||||
edges = get_xinerama_edges (3, 5);
|
||||
edges = get_monitor_edges (3, 5);
|
||||
tmp = NULL;
|
||||
verify_edge_lists_are_equal (edges, tmp);
|
||||
meta_rectangle_free_list_and_elements (tmp);
|
||||
@ -1405,7 +1405,7 @@ main()
|
||||
|
||||
/* And now the functions dealing with edges more than boxes */
|
||||
test_find_onscreen_edges ();
|
||||
test_find_nonintersected_xinerama_edges ();
|
||||
test_find_nonintersected_monitor_edges ();
|
||||
|
||||
/* And now the misfit functions that don't quite fit in anywhere else... */
|
||||
test_gravity_resize ();
|
||||
|
216
src/core/util.c
216
src/core/util.c
@ -26,9 +26,12 @@
|
||||
#define _POSIX_C_SOURCE 200112L /* for fdopen() */
|
||||
|
||||
#include <config.h>
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <clutter/clutter.h> /* For clutter_threads_add_repaint_func() */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -37,8 +40,6 @@
|
||||
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
|
||||
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
|
||||
|
||||
MetaNexus *sigchld_nexus;
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
void
|
||||
@ -557,7 +558,7 @@ meta_show_dialog (const char *type,
|
||||
int i=0;
|
||||
GPid child_pid;
|
||||
const char **argvl = g_malloc(sizeof (char*) *
|
||||
(15 +
|
||||
(17 +
|
||||
g_slist_length (columns)*2 +
|
||||
g_slist_length (entries)));
|
||||
|
||||
@ -565,6 +566,8 @@ meta_show_dialog (const char *type,
|
||||
argvl[i++] = type;
|
||||
argvl[i++] = "--screen";
|
||||
argvl[i++] = screen_number_text;
|
||||
argvl[i++] = "--class";
|
||||
argvl[i++] = "mutter-dialog";
|
||||
argvl[i++] = "--title";
|
||||
/* Translators: This is the title used on dialog boxes */
|
||||
argvl[i++] = _("Mutter");
|
||||
@ -638,29 +641,200 @@ meta_show_dialog (const char *type,
|
||||
return child_pid;
|
||||
}
|
||||
|
||||
GType
|
||||
meta_nexus_get_type (void)
|
||||
/***************************************************************************
|
||||
* Later functions: like idles but integrated with the Clutter repaint loop
|
||||
***************************************************************************/
|
||||
|
||||
static guint last_later_id = 0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
static GType nexus_type = 0;
|
||||
guint id;
|
||||
MetaLaterType when;
|
||||
GSourceFunc func;
|
||||
gpointer data;
|
||||
GDestroyNotify notify;
|
||||
int source;
|
||||
gboolean run_once;
|
||||
} MetaLater;
|
||||
|
||||
if (!nexus_type)
|
||||
static GSList *laters = NULL;
|
||||
/* This is a dummy timeline used to get the Clutter master clock running */
|
||||
static ClutterTimeline *later_timeline;
|
||||
static guint later_repaint_func = 0;
|
||||
|
||||
static void ensure_later_repaint_func (void);
|
||||
|
||||
static void
|
||||
destroy_later (MetaLater *later)
|
||||
{
|
||||
if (later->source)
|
||||
g_source_remove (later->source);
|
||||
if (later->notify)
|
||||
later->notify (later->data);
|
||||
g_slice_free (MetaLater, later);
|
||||
}
|
||||
|
||||
/* Used to sort the list of laters with the highest priority
|
||||
* functions first.
|
||||
*/
|
||||
static int
|
||||
compare_laters (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
return ((const MetaLater *)a)->when - ((const MetaLater *)b)->when;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_repaint_laters (gpointer data)
|
||||
{
|
||||
GSList *old_laters = laters;
|
||||
GSList *l;
|
||||
gboolean keep_timeline_running = FALSE;
|
||||
laters = NULL;
|
||||
|
||||
for (l = old_laters; l; l = l->next)
|
||||
{
|
||||
static const GTypeInfo nexus_info =
|
||||
{
|
||||
sizeof (MetaNexusClass),
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
sizeof (MetaNexus),
|
||||
0,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
nexus_type = g_type_register_static (G_TYPE_OBJECT,
|
||||
"MetaNexus",
|
||||
&nexus_info,
|
||||
0);
|
||||
MetaLater *later = l->data;
|
||||
if (later->source == 0 ||
|
||||
(later->when <= META_LATER_BEFORE_REDRAW && !later->run_once))
|
||||
{
|
||||
if (later->func (later->data))
|
||||
{
|
||||
if (later->source == 0)
|
||||
keep_timeline_running = TRUE;
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
}
|
||||
else
|
||||
destroy_later (later);
|
||||
}
|
||||
else
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
}
|
||||
|
||||
return nexus_type;
|
||||
if (!keep_timeline_running)
|
||||
clutter_timeline_stop (later_timeline);
|
||||
|
||||
g_slist_free (old_laters);
|
||||
|
||||
/* Just keep the repaint func around - it's cheap if the list is empty */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_later_repaint_func (void)
|
||||
{
|
||||
if (!later_timeline)
|
||||
later_timeline = clutter_timeline_new (G_MAXUINT);
|
||||
|
||||
if (later_repaint_func == 0)
|
||||
later_repaint_func = clutter_threads_add_repaint_func (run_repaint_laters,
|
||||
NULL, NULL);
|
||||
|
||||
/* Make sure the repaint function gets run */
|
||||
clutter_timeline_start (later_timeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
call_idle_later (gpointer data)
|
||||
{
|
||||
MetaLater *later = data;
|
||||
|
||||
if (!later->func (later->data))
|
||||
{
|
||||
laters = g_slist_remove (laters, later);
|
||||
later->source = 0;
|
||||
destroy_later (later);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
later->run_once = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_later_add:
|
||||
* @when: enumeration value determining the phase at which to run the callback
|
||||
* @func: callback to run later
|
||||
* @data: data to pass to the callback
|
||||
* @notify: function to call to destroy @data when it is no longer in use, or %NULL
|
||||
*
|
||||
* Sets up a callback to be called at some later time. @when determines the
|
||||
* particular later occasion at which it is called. This is much like g_idle_add(),
|
||||
* except that the functions interact properly with clutter event handling.
|
||||
* If a "later" function is added from a clutter event handler, and is supposed
|
||||
* to be run before the stage is redrawn, it will be run before that redraw
|
||||
* of the stage, not the next one.
|
||||
*
|
||||
* Return value: an integer ID (guaranteed to be non-zero) that can be used
|
||||
* to cancel the callback and prevent it from being run.
|
||||
*/
|
||||
guint
|
||||
meta_later_add (MetaLaterType when,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
MetaLater *later = g_slice_new0 (MetaLater);
|
||||
|
||||
later->id = ++last_later_id;
|
||||
later->when = when;
|
||||
later->func = func;
|
||||
later->data = data;
|
||||
later->notify = notify;
|
||||
|
||||
laters = g_slist_insert_sorted (laters, later, compare_laters);
|
||||
|
||||
switch (when)
|
||||
{
|
||||
case META_LATER_RESIZE:
|
||||
/* We add this one two ways - as a high-priority idle and as a
|
||||
* repaint func. If we are in a clutter event callback, the repaint
|
||||
* handler will get hit first, and we'll take care of this function
|
||||
* there so it gets called before the stage is redrawn, even if
|
||||
* we haven't gotten back to the main loop. Otherwise, the idle
|
||||
* handler will get hit first and we want to call this function
|
||||
* there so it will happen before GTK+ repaints.
|
||||
*/
|
||||
later->source = g_idle_add_full (META_PRIORITY_RESIZE, call_idle_later, later, NULL);
|
||||
ensure_later_repaint_func ();
|
||||
break;
|
||||
case META_LATER_BEFORE_REDRAW:
|
||||
ensure_later_repaint_func ();
|
||||
break;
|
||||
case META_LATER_IDLE:
|
||||
later->source = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, call_idle_later, later, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return later->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_later_remove:
|
||||
* @later_id: the integer ID returned from meta_later_add()
|
||||
*
|
||||
* Removes a callback added with meta_later_add()
|
||||
*/
|
||||
void
|
||||
meta_later_remove (guint later_id)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = laters; l; l = l->next)
|
||||
{
|
||||
MetaLater *later = l->data;
|
||||
if (later->id == later_id)
|
||||
{
|
||||
laters = g_slist_remove_link (laters, l);
|
||||
/* If this was a "repaint func" later, we just let the
|
||||
* repaint func run and get removed
|
||||
*/
|
||||
destroy_later (later);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eof util.c */
|
||||
|
@ -130,6 +130,12 @@ struct _MetaWindow
|
||||
/* Whether we're fullscreen */
|
||||
guint fullscreen : 1;
|
||||
|
||||
/* Whether the urgent flag of WM_HINTS is set */
|
||||
guint wm_hints_urgent : 1;
|
||||
|
||||
/* Whether we have to fullscreen after placement */
|
||||
guint fullscreen_after_placement : 1;
|
||||
|
||||
/* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has
|
||||
* been overridden (via a client message), the window will cover the union of
|
||||
* these monitors. If not, this is the single monitor which the window's
|
||||
@ -139,8 +145,8 @@ struct _MetaWindow
|
||||
/* Whether we're trying to constrain the window to be fully onscreen */
|
||||
guint require_fully_onscreen : 1;
|
||||
|
||||
/* Whether we're trying to constrain the window to be on a single xinerama */
|
||||
guint require_on_single_xinerama : 1;
|
||||
/* Whether we're trying to constrain the window to be on a single monitor */
|
||||
guint require_on_single_monitor : 1;
|
||||
|
||||
/* Whether we're trying to constrain the window's titlebar to be onscreen */
|
||||
guint require_titlebar_visible : 1;
|
||||
@ -246,6 +252,9 @@ struct _MetaWindow
|
||||
/* Have we placed this window? */
|
||||
guint placed : 1;
|
||||
|
||||
/* Must we force_save_user_window_placement? */
|
||||
guint force_save_user_rect : 1;
|
||||
|
||||
/* Is this not a transient of the focus window which is being denied focus? */
|
||||
guint denied_focus_and_not_transient : 1;
|
||||
|
||||
@ -316,6 +325,9 @@ struct _MetaWindow
|
||||
*/
|
||||
int unmaps_pending;
|
||||
|
||||
/* See docs for meta_window_get_stable_sequence() */
|
||||
guint32 stable_sequence;
|
||||
|
||||
/* set to the most recent user-interaction event timestamp that we
|
||||
know about for this window */
|
||||
guint32 net_wm_user_time;
|
||||
@ -377,6 +389,7 @@ struct _MetaWindowClass
|
||||
void (*workspace_changed) (MetaWindow *window, int old_workspace);
|
||||
void (*focus) (MetaWindow *window);
|
||||
void (*raised) (MetaWindow *window);
|
||||
void (*unmanaged) (MetaWindow *window);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
@ -544,13 +557,13 @@ GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
gboolean meta_window_located_on_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
void meta_window_get_work_area_current_xinerama (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_for_xinerama (MetaWindow *window,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_all_xineramas (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_current_monitor (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_for_monitor (MetaWindow *window,
|
||||
int which_monitor,
|
||||
MetaRectangle *area);
|
||||
void meta_window_get_work_area_all_monitors (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
|
||||
|
||||
gboolean meta_window_same_application (MetaWindow *window,
|
||||
|
@ -604,6 +604,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
window->shaded = FALSE;
|
||||
window->maximized_horizontally = FALSE;
|
||||
window->maximized_vertically = FALSE;
|
||||
window->fullscreen = FALSE;
|
||||
window->wm_state_modal = FALSE;
|
||||
window->wm_state_skip_taskbar = FALSE;
|
||||
window->wm_state_skip_pager = FALSE;
|
||||
@ -632,13 +633,7 @@ reload_net_wm_state (MetaWindow *window,
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
|
||||
window->wm_state_skip_pager = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
|
||||
{
|
||||
if (!window->fullscreen)
|
||||
{
|
||||
window->fullscreen = TRUE;
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
window->fullscreen_after_placement = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
|
||||
window->wm_state_above = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW)
|
||||
@ -1350,8 +1345,10 @@ reload_wm_hints (MetaWindow *window,
|
||||
gboolean initial)
|
||||
{
|
||||
Window old_group_leader;
|
||||
|
||||
gboolean old_urgent;
|
||||
|
||||
old_group_leader = window->xgroup_leader;
|
||||
old_urgent = window->wm_hints_urgent;
|
||||
|
||||
/* Fill in defaults */
|
||||
window->input = TRUE;
|
||||
@ -1359,7 +1356,8 @@ reload_wm_hints (MetaWindow *window,
|
||||
window->xgroup_leader = None;
|
||||
window->wm_hints_pixmap = None;
|
||||
window->wm_hints_mask = None;
|
||||
|
||||
window->wm_hints_urgent = FALSE;
|
||||
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
const XWMHints *hints = value->v.wm_hints;
|
||||
@ -1378,7 +1376,10 @@ reload_wm_hints (MetaWindow *window,
|
||||
|
||||
if (hints->flags & IconMaskHint)
|
||||
window->wm_hints_mask = hints->icon_mask;
|
||||
|
||||
|
||||
if (hints->flags & XUrgencyHint)
|
||||
window->wm_hints_urgent = TRUE;
|
||||
|
||||
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
|
||||
window->input, window->initially_iconic,
|
||||
window->xgroup_leader,
|
||||
@ -1394,6 +1395,21 @@ reload_wm_hints (MetaWindow *window,
|
||||
meta_window_group_leader_changed (window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not emit urgency notification on the inital property load
|
||||
*/
|
||||
if (!initial && (window->wm_hints_urgent != old_urgent))
|
||||
g_object_notify (G_OBJECT (window), "urgent");
|
||||
|
||||
/*
|
||||
* Do not emit signal for the initial property load, let the constructor to
|
||||
* take care of it once the MetaWindow is fully constructed.
|
||||
*
|
||||
* Only emit if the property is both changed and set.
|
||||
*/
|
||||
if (!initial && window->wm_hints_urgent && !old_urgent)
|
||||
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
||||
|
||||
meta_icon_cache_property_changed (&window->icon_cache,
|
||||
window->display,
|
||||
XA_WM_HINTS);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "mutter-enum-types.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlibint.h> /* For display->resource_mask */
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
@ -72,6 +73,9 @@ static gboolean process_property_notify (MetaWindow *window,
|
||||
static void meta_window_show (MetaWindow *window);
|
||||
static void meta_window_hide (MetaWindow *window);
|
||||
|
||||
static gboolean meta_window_same_client (MetaWindow *window,
|
||||
MetaWindow *other_window);
|
||||
|
||||
static void meta_window_save_rect (MetaWindow *window);
|
||||
static void save_user_window_placement (MetaWindow *window);
|
||||
static void force_save_user_window_placement (MetaWindow *window);
|
||||
@ -116,8 +120,9 @@ static void meta_window_apply_session_info (MetaWindow *window,
|
||||
static void unmaximize_window_before_freeing (MetaWindow *window);
|
||||
static void unminimize_window_and_all_transient_parents (MetaWindow *window);
|
||||
|
||||
/* Idle handlers for the three queues. The "data" parameter in each case
|
||||
* will be a GINT_TO_POINTER of the index into the queue arrays to use.
|
||||
/* Idle handlers for the three queues (run with meta_later_add()). The
|
||||
* "data" parameter in each case will be a GINT_TO_POINTER of the
|
||||
* index into the queue arrays to use.
|
||||
*
|
||||
* TODO: Possibly there is still some code duplication among these, which we
|
||||
* need to sort out at some point.
|
||||
@ -136,7 +141,12 @@ enum {
|
||||
PROP_MINI_ICON,
|
||||
PROP_DECORATED,
|
||||
PROP_FULLSCREEN,
|
||||
PROP_WINDOW_TYPE
|
||||
PROP_MAXIMIZED_HORIZONTALLY,
|
||||
PROP_MAXIMIZED_VERTICALLY,
|
||||
PROP_WINDOW_TYPE,
|
||||
PROP_USER_TIME,
|
||||
PROP_DEMANDS_ATTENTION,
|
||||
PROP_URGENT
|
||||
};
|
||||
|
||||
enum
|
||||
@ -144,6 +154,7 @@ enum
|
||||
WORKSPACE_CHANGED,
|
||||
FOCUS,
|
||||
RAISED,
|
||||
UNMANAGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
@ -199,9 +210,24 @@ meta_window_get_property(GObject *object,
|
||||
case PROP_FULLSCREEN:
|
||||
g_value_set_boolean (value, win->fullscreen);
|
||||
break;
|
||||
case PROP_MAXIMIZED_HORIZONTALLY:
|
||||
g_value_set_boolean (value, win->maximized_horizontally);
|
||||
break;
|
||||
case PROP_MAXIMIZED_VERTICALLY:
|
||||
g_value_set_boolean (value, win->maximized_vertically);
|
||||
break;
|
||||
case PROP_WINDOW_TYPE:
|
||||
g_value_set_enum (value, win->type);
|
||||
break;
|
||||
case PROP_USER_TIME:
|
||||
g_value_set_uint (value, win->net_wm_user_time);
|
||||
break;
|
||||
case PROP_DEMANDS_ATTENTION:
|
||||
g_value_set_boolean (value, win->wm_state_demands_attention);
|
||||
break;
|
||||
case PROP_URGENT:
|
||||
g_value_set_boolean (value, win->wm_hints_urgent);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -259,7 +285,7 @@ meta_window_class_init (MetaWindowClass *klass)
|
||||
PROP_DECORATED,
|
||||
g_param_spec_boolean ("decorated",
|
||||
"Decorated",
|
||||
"Whether windos is decorated",
|
||||
"Whether window is decorated",
|
||||
TRUE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
@ -267,7 +293,23 @@ meta_window_class_init (MetaWindowClass *klass)
|
||||
PROP_FULLSCREEN,
|
||||
g_param_spec_boolean ("fullscreen",
|
||||
"Fullscreen",
|
||||
"Whether windos is fullscreened",
|
||||
"Whether window is fullscreened",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_MAXIMIZED_HORIZONTALLY,
|
||||
g_param_spec_boolean ("maximized-horizontally",
|
||||
"Maximized horizontally",
|
||||
"Whether window is maximized horizontally",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_MAXIMIZED_VERTICALLY,
|
||||
g_param_spec_boolean ("maximized-vertically",
|
||||
"Maximizing vertically",
|
||||
"Whether window is maximized vertically",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
@ -280,6 +322,32 @@ meta_window_class_init (MetaWindowClass *klass)
|
||||
META_WINDOW_NORMAL,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_USER_TIME,
|
||||
g_param_spec_uint ("user-time",
|
||||
"User time",
|
||||
"Timestamp of last user interaction",
|
||||
0,
|
||||
G_MAXUINT,
|
||||
0,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DEMANDS_ATTENTION,
|
||||
g_param_spec_boolean ("demands-attention",
|
||||
"Demands Attention",
|
||||
"Whether the window has _NET_WM_STATE_DEMANDS_ATTENTION set",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_URGENT,
|
||||
g_param_spec_boolean ("urgent",
|
||||
"Urgent",
|
||||
"Whether the urgent flag of WM_HINTS is set",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
window_signals[WORKSPACE_CHANGED] =
|
||||
g_signal_new ("workspace-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
@ -307,6 +375,15 @@ meta_window_class_init (MetaWindowClass *klass)
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
window_signals[UNMANAGED] =
|
||||
g_signal_new ("unmanaged",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (MetaWindowClass, unmanaged),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -663,6 +740,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
meta_icon_cache_init (&window->icon_cache);
|
||||
window->wm_hints_pixmap = None;
|
||||
window->wm_hints_mask = None;
|
||||
window->wm_hints_urgent = FALSE;
|
||||
|
||||
window->frame = NULL;
|
||||
window->has_focus = FALSE;
|
||||
@ -673,9 +751,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
window->maximize_vertically_after_placement = FALSE;
|
||||
window->minimize_after_placement = FALSE;
|
||||
window->fullscreen = FALSE;
|
||||
window->fullscreen_after_placement = FALSE;
|
||||
window->fullscreen_monitors[0] = -1;
|
||||
window->require_fully_onscreen = TRUE;
|
||||
window->require_on_single_xinerama = TRUE;
|
||||
window->require_on_single_monitor = TRUE;
|
||||
window->require_titlebar_visible = TRUE;
|
||||
window->on_all_workspaces = FALSE;
|
||||
window->shaded = FALSE;
|
||||
@ -696,6 +775,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing window 0x%lx since it's already mapped\n",
|
||||
xwindow);
|
||||
window->force_save_user_rect = TRUE;
|
||||
window->denied_focus_and_not_transient = FALSE;
|
||||
window->unmanaging = FALSE;
|
||||
window->is_in_queues = 0;
|
||||
@ -707,6 +787,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
window->initial_timestamp_set = FALSE;
|
||||
window->net_wm_user_time_set = FALSE;
|
||||
window->user_time_window = None;
|
||||
window->take_focus = FALSE;
|
||||
window->delete_window = FALSE;
|
||||
window->net_wm_ping = FALSE;
|
||||
window->input = TRUE;
|
||||
window->calc_placement = FALSE;
|
||||
window->shaken_loose = FALSE;
|
||||
window->have_focus_click_grab = FALSE;
|
||||
@ -788,6 +872,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
|
||||
/* Assign this #MetaWindow a sequence number which can be used
|
||||
* for sorting.
|
||||
*/
|
||||
window->stable_sequence = ++display->window_sequence_counter;
|
||||
|
||||
/* assign the window to its group, or create a new group if needed
|
||||
*/
|
||||
@ -1062,6 +1150,14 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
|
||||
window->constructing = FALSE;
|
||||
|
||||
meta_display_notify_window_created (display, window);
|
||||
|
||||
if (window->wm_state_demands_attention)
|
||||
g_signal_emit_by_name (window->display, "window-demands-attention", window);
|
||||
|
||||
if (window->wm_hints_urgent)
|
||||
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
@ -1434,6 +1530,8 @@ meta_window_unmanage (MetaWindow *window,
|
||||
|
||||
meta_error_trap_pop (window->display, FALSE);
|
||||
|
||||
g_signal_emit (window, window_signals[UNMANAGED], 0);
|
||||
|
||||
g_object_unref (window);
|
||||
}
|
||||
|
||||
@ -1687,7 +1785,7 @@ meta_window_calc_showing (MetaWindow *window)
|
||||
implement_showing (window, meta_window_should_be_showing (window));
|
||||
}
|
||||
|
||||
static guint queue_idle[NUMBER_OF_QUEUES] = {0, 0, 0};
|
||||
static guint queue_later[NUMBER_OF_QUEUES] = {0, 0, 0};
|
||||
static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL};
|
||||
|
||||
static int
|
||||
@ -1725,7 +1823,7 @@ idle_calc_showing (gpointer data)
|
||||
copy = g_slist_copy (queue_pending[queue_index]);
|
||||
g_slist_free (queue_pending[queue_index]);
|
||||
queue_pending[queue_index] = NULL;
|
||||
queue_idle[queue_index] = 0;
|
||||
queue_later[queue_index] = 0;
|
||||
|
||||
destroying_windows_disallowed += 1;
|
||||
|
||||
@ -1853,8 +1951,10 @@ idle_calc_showing (gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] =
|
||||
{"calc_showing", "move_resize", "update_icon"};
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_window_unqueue (MetaWindow *window, guint queuebits)
|
||||
@ -1883,10 +1983,10 @@ meta_window_unqueue (MetaWindow *window, guint queuebits)
|
||||
* In that case, we should kill the function that deals with
|
||||
* the queue, because there's nothing left for it to do.
|
||||
*/
|
||||
if (queue_pending[queuenum] == NULL && queue_idle[queuenum] != 0)
|
||||
if (queue_pending[queuenum] == NULL && queue_later[queuenum] != 0)
|
||||
{
|
||||
g_source_remove (queue_idle[queuenum]);
|
||||
queue_idle[queuenum] = 0;
|
||||
meta_later_remove (queue_later[queuenum]);
|
||||
queue_later[queuenum] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1919,14 +2019,14 @@ meta_window_queue (MetaWindow *window, guint queuebits)
|
||||
* I seem to be turning into a Perl programmer.
|
||||
*/
|
||||
|
||||
const gint window_queue_idle_priority[NUMBER_OF_QUEUES] =
|
||||
const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] =
|
||||
{
|
||||
META_PRIORITY_BEFORE_REDRAW, /* CALC_SHOWING */
|
||||
META_PRIORITY_RESIZE, /* MOVE_RESIZE */
|
||||
META_PRIORITY_BEFORE_REDRAW /* UPDATE_ICON */
|
||||
META_LATER_BEFORE_REDRAW, /* CALC_SHOWING */
|
||||
META_LATER_RESIZE, /* MOVE_RESIZE */
|
||||
META_LATER_BEFORE_REDRAW /* UPDATE_ICON */
|
||||
};
|
||||
|
||||
const GSourceFunc window_queue_idle_handler[NUMBER_OF_QUEUES] =
|
||||
const GSourceFunc window_queue_later_handler[NUMBER_OF_QUEUES] =
|
||||
{
|
||||
idle_calc_showing,
|
||||
idle_move_resize,
|
||||
@ -1959,11 +2059,11 @@ meta_window_queue (MetaWindow *window, guint queuebits)
|
||||
* that. If not, we'll create one.
|
||||
*/
|
||||
|
||||
if (queue_idle[queuenum] == 0)
|
||||
queue_idle[queuenum] = g_idle_add_full
|
||||
if (queue_later[queuenum] == 0)
|
||||
queue_later[queuenum] = meta_later_add
|
||||
(
|
||||
window_queue_idle_priority[queuenum],
|
||||
window_queue_idle_handler[queuenum],
|
||||
window_queue_later_when[queuenum],
|
||||
window_queue_later_handler[queuenum],
|
||||
GUINT_TO_POINTER(queuenum),
|
||||
NULL
|
||||
);
|
||||
@ -2118,6 +2218,9 @@ __window_is_terminal (MetaWindow *window)
|
||||
/* mlterm ("multi lingual terminal emulator on X") */
|
||||
else if (strcmp (window->res_class, "mlterm") == 0)
|
||||
return TRUE;
|
||||
/* Terminal -- XFCE Terminal */
|
||||
else if (strcmp (window->res_class, "Terminal") == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -2362,6 +2465,7 @@ meta_window_show (MetaWindow *window)
|
||||
MetaWindow *focus_window;
|
||||
gboolean toplevel_was_mapped;
|
||||
gboolean toplevel_now_mapped;
|
||||
gboolean notify_demands_attention = FALSE;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_STATE,
|
||||
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
|
||||
@ -2496,7 +2600,13 @@ meta_window_show (MetaWindow *window)
|
||||
* which we are going to call ourselves here a few lines down.
|
||||
*/
|
||||
if (overlap)
|
||||
window->wm_state_demands_attention = TRUE;
|
||||
{
|
||||
if (!window->wm_state_demands_attention)
|
||||
{
|
||||
window->wm_state_demands_attention = TRUE;
|
||||
notify_demands_attention = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Shaded means the frame is mapped but the window is not */
|
||||
@ -2614,6 +2724,13 @@ meta_window_show (MetaWindow *window)
|
||||
* See http://bugzilla.gnome.org/show_bug.cgi?id=573922
|
||||
*/
|
||||
window->initial_timestamp_set = FALSE;
|
||||
|
||||
if (notify_demands_attention)
|
||||
{
|
||||
g_object_notify (G_OBJECT (window), "demands-attention");
|
||||
g_signal_emit_by_name (window->display, "window-demands-attention",
|
||||
window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2712,7 +2829,14 @@ meta_window_hide (MetaWindow *window)
|
||||
invalidate_work_areas (window);
|
||||
}
|
||||
|
||||
if (window->has_focus)
|
||||
/* The check on expected_focus_window is a temporary workaround for
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
|
||||
* We may have already switched away from this window but not yet
|
||||
* gotten FocusIn/FocusOut events. A more complete comprehensive
|
||||
* fix for these type of issues is described in the bug.
|
||||
*/
|
||||
if (window->has_focus &&
|
||||
window == window->display->expected_focus_window)
|
||||
{
|
||||
MetaWindow *not_this_one = NULL;
|
||||
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
|
||||
@ -2914,6 +3038,8 @@ meta_window_maximize_internal (MetaWindow *window,
|
||||
window->maximized_horizontally || maximize_horizontally;
|
||||
window->maximized_vertically =
|
||||
window->maximized_vertically || maximize_vertically;
|
||||
if (maximize_horizontally || maximize_vertically)
|
||||
window->force_save_user_rect = FALSE;
|
||||
|
||||
/* Fix for #336850: If the frame shape isn't reapplied, it is
|
||||
* possible that the frame will retains its rounded corners. That
|
||||
@ -2925,6 +3051,11 @@ meta_window_maximize_internal (MetaWindow *window,
|
||||
|
||||
recalc_window_features (window);
|
||||
set_net_wm_state (window);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
}
|
||||
|
||||
void
|
||||
@ -3093,6 +3224,10 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
window->display->grab_anchor_window_pos = target_rect;
|
||||
}
|
||||
|
||||
/* Make sure user_rect is current.
|
||||
*/
|
||||
force_save_user_window_placement (window);
|
||||
|
||||
if (window->display->compositor)
|
||||
{
|
||||
MetaRectangle old_rect, new_rect;
|
||||
@ -3125,6 +3260,11 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
recalc_window_features (window);
|
||||
set_net_wm_state (window);
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
}
|
||||
|
||||
void
|
||||
@ -3170,6 +3310,7 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
|
||||
meta_window_save_rect (window);
|
||||
|
||||
window->fullscreen = TRUE;
|
||||
window->force_save_user_rect = FALSE;
|
||||
|
||||
meta_stack_freeze (window->screen->stack);
|
||||
meta_window_update_layer (window);
|
||||
@ -3225,6 +3366,10 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
|
||||
/* Make sure user_rect is current.
|
||||
*/
|
||||
force_save_user_window_placement (window);
|
||||
|
||||
meta_window_update_layer (window);
|
||||
|
||||
recalc_window_features (window);
|
||||
@ -3241,10 +3386,10 @@ meta_window_update_fullscreen_monitors (MetaWindow *window,
|
||||
unsigned long left,
|
||||
unsigned long right)
|
||||
{
|
||||
if ((int)top < window->screen->n_xinerama_infos &&
|
||||
(int)bottom < window->screen->n_xinerama_infos &&
|
||||
(int)left < window->screen->n_xinerama_infos &&
|
||||
(int)right < window->screen->n_xinerama_infos)
|
||||
if ((int)top < window->screen->n_monitor_infos &&
|
||||
(int)bottom < window->screen->n_monitor_infos &&
|
||||
(int)left < window->screen->n_monitor_infos &&
|
||||
(int)right < window->screen->n_monitor_infos)
|
||||
{
|
||||
window->fullscreen_monitors[0] = top;
|
||||
window->fullscreen_monitors[1] = bottom;
|
||||
@ -4039,7 +4184,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
if (need_configure_notify)
|
||||
send_configure_notify (window);
|
||||
|
||||
if (!window->placed)
|
||||
if (!window->placed && window->force_save_user_rect && !window->fullscreen)
|
||||
force_save_user_window_placement (window);
|
||||
else if (is_user_action)
|
||||
save_user_window_placement (window);
|
||||
@ -4182,7 +4327,7 @@ idle_move_resize (gpointer data)
|
||||
copy = g_slist_copy (queue_pending[queue_index]);
|
||||
g_slist_free (queue_pending[queue_index]);
|
||||
queue_pending[queue_index] = NULL;
|
||||
queue_idle[queue_index] = 0;
|
||||
queue_later[queue_index] = 0;
|
||||
|
||||
destroying_windows_disallowed += 1;
|
||||
|
||||
@ -5067,8 +5212,7 @@ meta_window_configure_request (MetaWindow *window,
|
||||
{
|
||||
MetaWindow *active_window;
|
||||
active_window = window->display->expected_focus_window;
|
||||
if (meta_prefs_get_disable_workarounds () ||
|
||||
!meta_prefs_get_raise_on_click ())
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"%s sent an xconfigure stacking request; this is "
|
||||
@ -5077,6 +5221,7 @@ meta_window_configure_request (MetaWindow *window,
|
||||
}
|
||||
else if (active_window &&
|
||||
!meta_window_same_application (window, active_window) &&
|
||||
!meta_window_same_client (window, active_window) &&
|
||||
XSERVER_TIME_IS_BEFORE (window->net_wm_user_time,
|
||||
active_window->net_wm_user_time))
|
||||
{
|
||||
@ -6244,7 +6389,7 @@ idle_update_icon (gpointer data)
|
||||
copy = g_slist_copy (queue_pending[queue_index]);
|
||||
g_slist_free (queue_pending[queue_index]);
|
||||
queue_pending[queue_index] = NULL;
|
||||
queue_idle[queue_index] = 0;
|
||||
queue_later[queue_index] = 0;
|
||||
|
||||
destroying_windows_disallowed += 1;
|
||||
|
||||
@ -6788,7 +6933,7 @@ recalc_window_features (MetaWindow *window)
|
||||
|
||||
/* don't allow fullscreen if we can't resize, unless the size
|
||||
* is entire screen size (kind of broken, because we
|
||||
* actually fullscreen to xinerama head size not screen size)
|
||||
* actually fullscreen to monitor size not screen size)
|
||||
*/
|
||||
if (window->size_hints.min_width == window->screen->rect.width &&
|
||||
window->size_hints.min_height == window->screen->rect.height)
|
||||
@ -7449,22 +7594,22 @@ update_move (MetaWindow *window,
|
||||
|
||||
return;
|
||||
}
|
||||
/* remaximize window on an other xinerama monitor if window has
|
||||
* been shaken loose or it is still maximized (then move straight)
|
||||
/* remaximize window on another monitor if window has been shaken
|
||||
* loose or it is still maximized (then move straight)
|
||||
*/
|
||||
else if (window->shaken_loose || META_WINDOW_MAXIMIZED (window))
|
||||
{
|
||||
const MetaXineramaScreenInfo *wxinerama;
|
||||
const MetaMonitorInfo *wmonitor;
|
||||
MetaRectangle work_area;
|
||||
int monitor;
|
||||
|
||||
wxinerama = meta_screen_get_xinerama_for_window (window->screen, window);
|
||||
wmonitor = meta_screen_get_monitor_for_window (window->screen, window);
|
||||
|
||||
for (monitor = 0; monitor < window->screen->n_xinerama_infos; monitor++)
|
||||
for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++)
|
||||
{
|
||||
meta_window_get_work_area_for_xinerama (window, monitor, &work_area);
|
||||
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
|
||||
|
||||
/* check if cursor is near the top of a xinerama work area */
|
||||
/* check if cursor is near the top of a monitor work area */
|
||||
if (x >= work_area.x &&
|
||||
x < (work_area.x + work_area.width) &&
|
||||
y >= work_area.y &&
|
||||
@ -7473,7 +7618,7 @@ update_move (MetaWindow *window,
|
||||
/* move the saved rect if window will become maximized on an
|
||||
* other monitor so user isn't surprised on a later unmaximize
|
||||
*/
|
||||
if (wxinerama->number != monitor)
|
||||
if (wmonitor->number != monitor)
|
||||
{
|
||||
window->saved_rect.x = work_area.x;
|
||||
window->saved_rect.y = work_area.y;
|
||||
@ -7955,24 +8100,24 @@ meta_window_set_gravity (MetaWindow *window,
|
||||
}
|
||||
|
||||
static void
|
||||
get_work_area_xinerama (MetaWindow *window,
|
||||
MetaRectangle *area,
|
||||
int which_xinerama)
|
||||
get_work_area_monitor (MetaWindow *window,
|
||||
MetaRectangle *area,
|
||||
int which_monitor)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
g_assert (which_xinerama >= 0);
|
||||
g_assert (which_monitor >= 0);
|
||||
|
||||
/* Initialize to the whole xinerama */
|
||||
*area = window->screen->xinerama_infos[which_xinerama].rect;
|
||||
/* Initialize to the whole monitor */
|
||||
*area = window->screen->monitor_infos[which_monitor].rect;
|
||||
|
||||
tmp = meta_window_get_workspaces (window);
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaRectangle workspace_work_area;
|
||||
meta_workspace_get_work_area_for_xinerama (tmp->data,
|
||||
which_xinerama,
|
||||
&workspace_work_area);
|
||||
meta_workspace_get_work_area_for_monitor (tmp->data,
|
||||
which_monitor,
|
||||
&workspace_work_area);
|
||||
meta_rectangle_intersect (area,
|
||||
&workspace_work_area,
|
||||
area);
|
||||
@ -7980,39 +8125,39 @@ get_work_area_xinerama (MetaWindow *window,
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_WORKAREA,
|
||||
"Window %s xinerama %d has work area %d,%d %d x %d\n",
|
||||
window->desc, which_xinerama,
|
||||
"Window %s monitor %d has work area %d,%d %d x %d\n",
|
||||
window->desc, which_monitor,
|
||||
area->x, area->y, area->width, area->height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_get_work_area_current_xinerama (MetaWindow *window,
|
||||
MetaRectangle *area)
|
||||
meta_window_get_work_area_current_monitor (MetaWindow *window,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
const MetaXineramaScreenInfo *xinerama = NULL;
|
||||
xinerama = meta_screen_get_xinerama_for_window (window->screen,
|
||||
window);
|
||||
const MetaMonitorInfo *monitor = NULL;
|
||||
monitor = meta_screen_get_monitor_for_window (window->screen,
|
||||
window);
|
||||
|
||||
meta_window_get_work_area_for_xinerama (window,
|
||||
xinerama->number,
|
||||
area);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor->number,
|
||||
area);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_get_work_area_for_xinerama (MetaWindow *window,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area)
|
||||
meta_window_get_work_area_for_monitor (MetaWindow *window,
|
||||
int which_monitor,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
g_return_if_fail (which_xinerama >= 0);
|
||||
g_return_if_fail (which_monitor >= 0);
|
||||
|
||||
get_work_area_xinerama (window,
|
||||
area,
|
||||
which_xinerama);
|
||||
get_work_area_monitor (window,
|
||||
area,
|
||||
which_monitor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_get_work_area_all_xineramas (MetaWindow *window,
|
||||
MetaRectangle *area)
|
||||
meta_window_get_work_area_all_monitors (MetaWindow *window,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
@ -8023,8 +8168,8 @@ meta_window_get_work_area_all_xineramas (MetaWindow *window,
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaRectangle workspace_work_area;
|
||||
meta_workspace_get_work_area_all_xineramas (tmp->data,
|
||||
&workspace_work_area);
|
||||
meta_workspace_get_work_area_all_monitors (tmp->data,
|
||||
&workspace_work_area);
|
||||
meta_rectangle_intersect (area,
|
||||
&workspace_work_area,
|
||||
area);
|
||||
@ -8050,6 +8195,23 @@ meta_window_same_application (MetaWindow *window,
|
||||
group==other_group;
|
||||
}
|
||||
|
||||
/* Generally meta_window_same_application() is a better idea
|
||||
* of "sameness", since it handles the case where multiple apps
|
||||
* want to look like the same app or the same app wants to look
|
||||
* like multiple apps, but in the case of workarounds for legacy
|
||||
* applications (which likely aren't setting the group properly
|
||||
* anyways), it may be desirable to check this as well.
|
||||
*/
|
||||
static gboolean
|
||||
meta_window_same_client (MetaWindow *window,
|
||||
MetaWindow *other_window)
|
||||
{
|
||||
int resource_mask = window->display->xdisplay->resource_mask;
|
||||
|
||||
return ((window->xwindow & ~resource_mask) ==
|
||||
(other_window->xwindow & ~resource_mask));
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_refresh_resize_popup (MetaWindow *window)
|
||||
{
|
||||
@ -8456,6 +8618,26 @@ meta_window_stack_just_below (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_user_time:
|
||||
*
|
||||
* The user time represents a timestamp for the last time the user
|
||||
* interacted with this window. Note this property is only available
|
||||
* for non-override-redirect windows.
|
||||
*
|
||||
* The property is set by Mutter initially upon window creation,
|
||||
* and updated thereafter on input events (key and button presses) seen by Mutter,
|
||||
* client updates to the _NET_WM_USER_TIME property (if later than the current time)
|
||||
* and when focusing the window.
|
||||
*
|
||||
* Returns: The last time the user interacted with this window.
|
||||
*/
|
||||
guint32
|
||||
meta_window_get_user_time (MetaWindow *window)
|
||||
{
|
||||
return window->net_wm_user_time;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_user_time (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
@ -8494,6 +8676,28 @@ meta_window_set_user_time (MetaWindow *window,
|
||||
__window_is_terminal (window))
|
||||
window->display->allow_terminal_deactivation = FALSE;
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (window), "user-time");
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_stable_sequence:
|
||||
* @window: A #MetaWindow
|
||||
*
|
||||
* The stable sequence number is a monotonicially increasing
|
||||
* unique integer assigned to each #MetaWindow upon creation.
|
||||
*
|
||||
* This number can be useful for sorting windows in a stable
|
||||
* fashion.
|
||||
*
|
||||
* Returns: Internal sequence number for this window
|
||||
*/
|
||||
guint32
|
||||
meta_window_get_stable_sequence (MetaWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_WINDOW (window), 0);
|
||||
|
||||
return window->stable_sequence;
|
||||
}
|
||||
|
||||
/* Sets the demands_attention hint on a window, but only
|
||||
@ -8508,6 +8712,10 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
gboolean obscured = FALSE;
|
||||
|
||||
MetaWorkspace *workspace = window->screen->active_workspace;
|
||||
|
||||
if (window->wm_state_demands_attention)
|
||||
return;
|
||||
|
||||
if (workspace!=window->workspace)
|
||||
{
|
||||
/* windows on other workspaces are necessarily obscured */
|
||||
@ -8551,6 +8759,9 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
|
||||
window->wm_state_demands_attention = TRUE;
|
||||
set_net_wm_state (window);
|
||||
g_object_notify (G_OBJECT (window), "demands-attention");
|
||||
g_signal_emit_by_name (window->display, "window-demands-attention",
|
||||
window);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -8569,8 +8780,12 @@ meta_window_unset_demands_attention (MetaWindow *window)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Marking %s as not needing attention\n", window->desc);
|
||||
|
||||
window->wm_state_demands_attention = FALSE;
|
||||
set_net_wm_state (window);
|
||||
if (window->wm_state_demands_attention)
|
||||
{
|
||||
window->wm_state_demands_attention = FALSE;
|
||||
set_net_wm_state (window);
|
||||
g_object_notify (G_OBJECT (window), "demands-attention");
|
||||
}
|
||||
}
|
||||
|
||||
MetaFrame *
|
||||
@ -8799,6 +9014,25 @@ meta_window_get_transient_for (MetaWindow *window)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_transient_for_as_xid:
|
||||
* @window: a #MetaWindow
|
||||
*
|
||||
* Returns the XID of the window that is pointed to by the
|
||||
* WM_TRANSIENT_FOR hint on this window (see XGetTransientForHint()
|
||||
* or XSetTransientForHint()). Metacity keeps transient windows above their
|
||||
* parents. A typical usage of this hint is for a dialog that wants to stay
|
||||
* above its associated window.
|
||||
*
|
||||
* Return value: (transfer none): the window this window is transient for, or
|
||||
* None if the WM_TRANSIENT_FOR hint is unset.
|
||||
*/
|
||||
Window
|
||||
meta_window_get_transient_for_as_xid (MetaWindow *window)
|
||||
{
|
||||
return window->xtransient_for;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_pid:
|
||||
* @window: a #MetaWindow
|
||||
|
@ -47,12 +47,12 @@ struct _MetaWorkspace
|
||||
GList *list_containing_self;
|
||||
|
||||
MetaRectangle work_area_screen;
|
||||
MetaRectangle *work_area_xinerama;
|
||||
MetaRectangle *work_area_monitor;
|
||||
GList *screen_region;
|
||||
GList **xinerama_region;
|
||||
gint n_xinerama_regions;
|
||||
GList **monitor_region;
|
||||
gint n_monitor_regions;
|
||||
GList *screen_edges;
|
||||
GList *xinerama_edges;
|
||||
GList *monitor_edges;
|
||||
GSList *builtin_struts;
|
||||
GSList *all_struts;
|
||||
guint work_areas_invalid : 1;
|
||||
@ -77,14 +77,12 @@ void meta_workspace_relocate_windows (MetaWorkspace *workspace,
|
||||
void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
|
||||
|
||||
|
||||
void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
|
||||
int which_xinerama,
|
||||
void meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
|
||||
int which_monitor,
|
||||
MetaRectangle *area);
|
||||
GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
|
||||
int which_xinerama);
|
||||
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
|
||||
int which_monitor);
|
||||
|
||||
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one,
|
||||
|
@ -33,6 +33,9 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@ -170,16 +173,16 @@ meta_workspace_new (MetaScreen *screen)
|
||||
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
workspace->work_area_xinerama = NULL;
|
||||
workspace->work_area_monitor = NULL;
|
||||
workspace->work_area_screen.x = 0;
|
||||
workspace->work_area_screen.y = 0;
|
||||
workspace->work_area_screen.width = 0;
|
||||
workspace->work_area_screen.height = 0;
|
||||
|
||||
workspace->screen_region = NULL;
|
||||
workspace->xinerama_region = NULL;
|
||||
workspace->monitor_region = NULL;
|
||||
workspace->screen_edges = NULL;
|
||||
workspace->xinerama_edges = NULL;
|
||||
workspace->monitor_edges = NULL;
|
||||
workspace->list_containing_self = g_list_prepend (NULL, workspace);
|
||||
|
||||
workspace->builtin_struts = NULL;
|
||||
@ -263,7 +266,7 @@ meta_workspace_remove (MetaWorkspace *workspace)
|
||||
workspace->screen->workspaces =
|
||||
g_list_remove (workspace->screen->workspaces, workspace);
|
||||
|
||||
g_free (workspace->work_area_xinerama);
|
||||
g_free (workspace->work_area_monitor);
|
||||
|
||||
g_list_free (workspace->mru_list);
|
||||
g_list_free (workspace->list_containing_self);
|
||||
@ -280,12 +283,12 @@ meta_workspace_remove (MetaWorkspace *workspace)
|
||||
if (!workspace->work_areas_invalid)
|
||||
{
|
||||
workspace_free_all_struts (workspace);
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
|
||||
g_free (workspace->monitor_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
|
||||
}
|
||||
|
||||
g_object_unref (workspace);
|
||||
@ -439,6 +442,69 @@ meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
workspace_switch_sound(MetaWorkspace *from,
|
||||
MetaWorkspace *to)
|
||||
{
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
MetaWorkspaceLayout layout;
|
||||
int i, nw, x, y, fi, ti;
|
||||
const char *e;
|
||||
|
||||
nw = meta_screen_get_n_workspaces(from->screen);
|
||||
fi = meta_workspace_index(from);
|
||||
ti = meta_workspace_index(to);
|
||||
|
||||
meta_screen_calc_workspace_layout(from->screen,
|
||||
nw,
|
||||
fi,
|
||||
&layout);
|
||||
|
||||
for (i = 0; i < nw; i++)
|
||||
if (layout.grid[i] == ti)
|
||||
break;
|
||||
|
||||
if (i >= nw)
|
||||
{
|
||||
meta_bug("Failed to find destination workspace in layout\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
y = i / layout.cols;
|
||||
x = i % layout.cols;
|
||||
|
||||
/* We priorize horizontal over vertical movements here. The
|
||||
rationale for this is that horizontal movements are probably more
|
||||
interesting for sound effects because speakers are usually
|
||||
positioned on a horizontal and not a vertical axis. i.e. your
|
||||
spatial "Woosh!" effects will easily be able to encode horizontal
|
||||
movement but not such much vertical movement. */
|
||||
|
||||
if (x < layout.current_col)
|
||||
e = "desktop-switch-left";
|
||||
else if (x > layout.current_col)
|
||||
e = "desktop-switch-right";
|
||||
else if (y < layout.current_row)
|
||||
e = "desktop-switch-up";
|
||||
else if (y > layout.current_row)
|
||||
e = "desktop-switch-down";
|
||||
else
|
||||
{
|
||||
meta_bug("Uh, origin and destination workspace at same logic position!\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ca_context_play(ca_gtk_context_get(), 1,
|
||||
CA_PROP_EVENT_ID, e,
|
||||
CA_PROP_EVENT_DESCRIPTION, "Desktop switched",
|
||||
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
|
||||
NULL);
|
||||
|
||||
finish:
|
||||
meta_screen_free_workspace_layout (&layout);
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_workspace_activate_with_focus:
|
||||
* @workspace: a #MetaWorkspace
|
||||
@ -478,6 +544,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
if (workspace->screen->active_workspace == workspace)
|
||||
return;
|
||||
|
||||
/* Free any cached pointers to the workspaces's edges from
|
||||
* a current resize or move operation */
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
|
||||
if (workspace->screen->active_workspace)
|
||||
workspace_switch_sound (workspace->screen->active_workspace, workspace);
|
||||
|
||||
/* Note that old can be NULL; e.g. when starting up */
|
||||
old = workspace->screen->active_workspace;
|
||||
|
||||
@ -638,7 +711,7 @@ meta_workspace_update_window_hints (MetaWorkspace *workspace)
|
||||
* Gets windows contained on the workspace, including workspace->windows
|
||||
* and also sticky windows. Override-redirect windows are not included.
|
||||
*
|
||||
* Return value: (transfer container): the list of windows.
|
||||
* Return value: (transfer container) (element-type MetaWindow): the list of windows.
|
||||
*/
|
||||
GList*
|
||||
meta_workspace_list_windows (MetaWorkspace *workspace)
|
||||
@ -713,21 +786,26 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
|
||||
"Invalidating work area for workspace %d\n",
|
||||
meta_workspace_index (workspace));
|
||||
|
||||
g_free (workspace->work_area_xinerama);
|
||||
workspace->work_area_xinerama = NULL;
|
||||
/* If we are in the middle of a resize or move operation, we
|
||||
* might have cached pointers to the workspace's edges */
|
||||
if (workspace == workspace->screen->active_workspace)
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
|
||||
g_free (workspace->work_area_monitor);
|
||||
workspace->work_area_monitor = NULL;
|
||||
|
||||
workspace_free_all_struts (workspace);
|
||||
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
|
||||
g_free (workspace->monitor_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
workspace->xinerama_region = NULL;
|
||||
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
|
||||
workspace->monitor_region = NULL;
|
||||
workspace->screen_region = NULL;
|
||||
workspace->screen_edges = NULL;
|
||||
workspace->xinerama_edges = NULL;
|
||||
workspace->monitor_edges = NULL;
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
|
||||
@ -780,10 +858,10 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
return;
|
||||
|
||||
g_assert (workspace->all_struts == NULL);
|
||||
g_assert (workspace->xinerama_region == NULL);
|
||||
g_assert (workspace->monitor_region == NULL);
|
||||
g_assert (workspace->screen_region == NULL);
|
||||
g_assert (workspace->screen_edges == NULL);
|
||||
g_assert (workspace->xinerama_edges == NULL);
|
||||
g_assert (workspace->monitor_edges == NULL);
|
||||
|
||||
/* STEP 1: Get the list of struts */
|
||||
|
||||
@ -803,18 +881,18 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
g_list_free (windows);
|
||||
|
||||
/* STEP 2: Get the maximal/spanning rects for the onscreen and
|
||||
* on-single-xinerama regions
|
||||
* on-single-monitor regions
|
||||
*/
|
||||
g_assert (workspace->xinerama_region == NULL);
|
||||
g_assert (workspace->monitor_region == NULL);
|
||||
g_assert (workspace->screen_region == NULL);
|
||||
|
||||
workspace->xinerama_region = g_new (GList*,
|
||||
workspace->screen->n_xinerama_infos);
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
workspace->monitor_region = g_new (GList*,
|
||||
workspace->screen->n_monitor_infos);
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
{
|
||||
workspace->xinerama_region[i] =
|
||||
workspace->monitor_region[i] =
|
||||
meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
&workspace->screen->xinerama_infos[i].rect,
|
||||
&workspace->screen->monitor_infos[i].rect,
|
||||
workspace->all_struts);
|
||||
}
|
||||
workspace->screen_region =
|
||||
@ -823,7 +901,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->all_struts);
|
||||
|
||||
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
|
||||
* xineramas.
|
||||
* monitors.
|
||||
*/
|
||||
work_area = workspace->screen->rect; /* start with the screen */
|
||||
if (workspace->screen_region == NULL)
|
||||
@ -878,35 +956,35 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->work_area_screen.width,
|
||||
workspace->work_area_screen.height);
|
||||
|
||||
/* Now find the work areas for each xinerama */
|
||||
g_free (workspace->work_area_xinerama);
|
||||
workspace->work_area_xinerama = g_new (MetaRectangle,
|
||||
workspace->screen->n_xinerama_infos);
|
||||
/* Now find the work areas for each monitor */
|
||||
g_free (workspace->work_area_monitor);
|
||||
workspace->work_area_monitor = g_new (MetaRectangle,
|
||||
workspace->screen->n_monitor_infos);
|
||||
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
{
|
||||
work_area = workspace->screen->xinerama_infos[i].rect;
|
||||
work_area = workspace->screen->monitor_infos[i].rect;
|
||||
|
||||
if (workspace->xinerama_region[i] == NULL)
|
||||
if (workspace->monitor_region[i] == NULL)
|
||||
/* FIXME: constraints.c untested with this, but it might be nice for
|
||||
* a screen reader or magnifier.
|
||||
*/
|
||||
work_area = meta_rect (work_area.x, work_area.y, -1, -1);
|
||||
else
|
||||
meta_rectangle_clip_to_region (workspace->xinerama_region[i],
|
||||
meta_rectangle_clip_to_region (workspace->monitor_region[i],
|
||||
FIXED_DIRECTION_NONE,
|
||||
&work_area);
|
||||
|
||||
workspace->work_area_xinerama[i] = work_area;
|
||||
workspace->work_area_monitor[i] = work_area;
|
||||
meta_topic (META_DEBUG_WORKAREA,
|
||||
"Computed work area for workspace %d "
|
||||
"xinerama %d: %d,%d %d x %d\n",
|
||||
"monitor %d: %d,%d %d x %d\n",
|
||||
meta_workspace_index (workspace),
|
||||
i,
|
||||
workspace->work_area_xinerama[i].x,
|
||||
workspace->work_area_xinerama[i].y,
|
||||
workspace->work_area_xinerama[i].width,
|
||||
workspace->work_area_xinerama[i].height);
|
||||
workspace->work_area_monitor[i].x,
|
||||
workspace->work_area_monitor[i].y,
|
||||
workspace->work_area_monitor[i].width,
|
||||
workspace->work_area_monitor[i].height);
|
||||
}
|
||||
|
||||
/* STEP 4: Make sure the screen_region is nonempty (separate from step 2
|
||||
@ -920,17 +998,17 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
|
||||
}
|
||||
|
||||
/* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */
|
||||
/* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
|
||||
g_assert (workspace->screen_edges == NULL);
|
||||
g_assert (workspace->xinerama_edges == NULL);
|
||||
g_assert (workspace->monitor_edges == NULL);
|
||||
workspace->screen_edges =
|
||||
meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
|
||||
workspace->all_struts);
|
||||
tmp = NULL;
|
||||
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
|
||||
tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
|
||||
workspace->xinerama_edges =
|
||||
meta_rectangle_find_nonintersected_xinerama_edges (tmp,
|
||||
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
|
||||
tmp = g_list_prepend (tmp, &workspace->screen->monitor_infos[i].rect);
|
||||
workspace->monitor_edges =
|
||||
meta_rectangle_find_nonintersected_monitor_edges (tmp,
|
||||
workspace->all_struts);
|
||||
g_list_free (tmp);
|
||||
|
||||
@ -950,6 +1028,23 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
strut_lists_equal (GSList *l,
|
||||
GSList *m)
|
||||
{
|
||||
for (; l && m; l = l->next, m = m->next)
|
||||
{
|
||||
MetaStrut *a = l->data;
|
||||
MetaStrut *b = m->data;
|
||||
|
||||
if (a->side != b->side ||
|
||||
!meta_rectangle_equal (&a->rect, &b->rect))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return l == NULL && m == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_workspace_set_builtin_struts:
|
||||
* @workspace: a #MetaWorkspace
|
||||
@ -963,6 +1058,12 @@ void
|
||||
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
|
||||
GSList *struts)
|
||||
{
|
||||
/* Reordering doesn't actually matter, so we don't catch all
|
||||
* no-impact changes, but this is just a (possibly unnecessary
|
||||
* anyways) optimization */
|
||||
if (strut_lists_equal (struts, workspace->builtin_struts))
|
||||
return;
|
||||
|
||||
workspace_free_builtin_struts (workspace);
|
||||
workspace->builtin_struts = copy_strut_list (struts);
|
||||
|
||||
@ -970,21 +1071,21 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
|
||||
int which_xinerama,
|
||||
MetaRectangle *area)
|
||||
meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
|
||||
int which_monitor,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
g_assert (which_xinerama >= 0);
|
||||
g_assert (which_monitor >= 0);
|
||||
|
||||
ensure_work_areas_validated (workspace);
|
||||
g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
|
||||
g_assert (which_monitor < workspace->screen->n_monitor_infos);
|
||||
|
||||
*area = workspace->work_area_xinerama[which_xinerama];
|
||||
*area = workspace->work_area_monitor[which_monitor];
|
||||
}
|
||||
|
||||
void
|
||||
meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area)
|
||||
meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
|
||||
MetaRectangle *area)
|
||||
{
|
||||
ensure_work_areas_validated (workspace);
|
||||
|
||||
@ -1000,12 +1101,12 @@ meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
|
||||
}
|
||||
|
||||
GList*
|
||||
meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
|
||||
int which_xinerama)
|
||||
meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
|
||||
int which_monitor)
|
||||
{
|
||||
ensure_work_areas_validated (workspace);
|
||||
|
||||
return workspace->xinerama_region[which_xinerama];
|
||||
return workspace->monitor_region[which_monitor];
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
@ -1202,7 +1303,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
|
||||
MetaWindow *ancestor;
|
||||
ancestor = NULL;
|
||||
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
|
||||
if (ancestor != NULL)
|
||||
if (ancestor != NULL &&
|
||||
(ancestor->on_all_workspaces ||
|
||||
ancestor->workspace == workspace) &&
|
||||
meta_window_showing_on_its_workspace (ancestor))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s, ancestor of %s\n",
|
||||
|
@ -264,6 +264,16 @@ cardinal_list_from_results (GetPropertyResults *results,
|
||||
*n_cardinals_p = results->n_items;
|
||||
results->prop = NULL;
|
||||
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < *n_cardinals_p; i++)
|
||||
(*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -608,6 +618,10 @@ cardinal_with_atom_type_from_results (GetPropertyResults *results,
|
||||
return FALSE;
|
||||
|
||||
*cardinal_p = *(gulong*) results->prop;
|
||||
#if GLIB_SIZEOF_LONG == 8
|
||||
/* Xlib sign-extends format=32 items, but we want them unsigned */
|
||||
*cardinal_p &= 0xffffffff;
|
||||
#endif
|
||||
XFree (results->prop);
|
||||
results->prop = NULL;
|
||||
|
||||
|
@ -167,7 +167,7 @@ keybind (switch_panels_backward, handle_switch, META_TAB_LIST_DOCKS,
|
||||
"using a popup window"))
|
||||
|
||||
keybind (cycle_group, handle_cycle, META_TAB_LIST_GROUP,
|
||||
BINDING_REVERSES, "<Alt>F6",
|
||||
BINDING_REVERSES, "<Alt>grave",
|
||||
_("Move between windows of an application immediately"))
|
||||
keybind (cycle_group_backward, handle_cycle, META_TAB_LIST_GROUP,
|
||||
REVERSES_AND_REVERSED, NULL,
|
||||
|
@ -1,73 +0,0 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef META_ALT_TAB_HANDLER_H
|
||||
#define META_ALT_TAB_HANDLER_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define META_TYPE_ALT_TAB_HANDLER (meta_alt_tab_handler_get_type ())
|
||||
#define META_ALT_TAB_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandler))
|
||||
#define META_ALT_TAB_HANDLER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandlerInterface))
|
||||
|
||||
typedef struct _MetaAltTabHandler MetaAltTabHandler;
|
||||
typedef struct _MetaAltTabHandlerInterface MetaAltTabHandlerInterface;
|
||||
|
||||
struct _MetaAltTabHandlerInterface {
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (*add_window) (MetaAltTabHandler *handler,
|
||||
MetaWindow *window);
|
||||
|
||||
void (*show) (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection);
|
||||
void (*destroy) (MetaAltTabHandler *handler);
|
||||
|
||||
void (*forward) (MetaAltTabHandler *handler);
|
||||
void (*backward) (MetaAltTabHandler *handler);
|
||||
|
||||
MetaWindow * (*get_selected) (MetaAltTabHandler *handler);
|
||||
};
|
||||
|
||||
GType meta_alt_tab_handler_get_type (void);
|
||||
|
||||
void meta_alt_tab_handler_register (GType type);
|
||||
MetaAltTabHandler *meta_alt_tab_handler_new (MetaScreen *screen,
|
||||
gboolean immediate);
|
||||
|
||||
void meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
|
||||
MetaWindow *window);
|
||||
|
||||
void meta_alt_tab_handler_show (MetaAltTabHandler *handler,
|
||||
MetaWindow *initial_selection);
|
||||
void meta_alt_tab_handler_destroy (MetaAltTabHandler *handler);
|
||||
|
||||
void meta_alt_tab_handler_forward (MetaAltTabHandler *handler);
|
||||
void meta_alt_tab_handler_backward (MetaAltTabHandler *handler);
|
||||
|
||||
MetaWindow *meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler);
|
||||
|
||||
#endif
|
||||
|
@ -1,55 +0,0 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#ifndef META_ALT_TAB_HANDLER_DEFAULT_H
|
||||
#define META_ALT_TAB_HANDLER_DEFAULT_H
|
||||
|
||||
#include "alttabhandler.h"
|
||||
#include "tabpopup.h"
|
||||
|
||||
#define META_TYPE_ALT_TAB_HANDLER_DEFAULT (meta_alt_tab_handler_default_get_type ())
|
||||
#define META_ALT_TAB_HANDLER_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER_DEFAULT, MetaAltTabHandlerDefault))
|
||||
|
||||
typedef struct _MetaAltTabHandlerDefault MetaAltTabHandlerDefault;
|
||||
typedef struct _MetaAltTabHandlerDefaultClass MetaAltTabHandlerDefaultClass;
|
||||
|
||||
struct _MetaAltTabHandlerDefault {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
|
||||
GArray *entries;
|
||||
gboolean immediate_mode;
|
||||
|
||||
MetaTabPopup *tab_popup;
|
||||
};
|
||||
|
||||
struct _MetaAltTabHandlerDefaultClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
GType meta_alt_tab_handler_default_get_type (void);
|
||||
|
||||
#endif
|
||||
|
@ -58,6 +58,7 @@ item(_MUTTER_RESTART_MESSAGE)
|
||||
item(_MUTTER_RELOAD_THEME_MESSAGE)
|
||||
item(_MUTTER_SET_KEYBINDINGS_MESSAGE)
|
||||
item(_MUTTER_TOGGLE_VERBOSE)
|
||||
item(_GNOME_WM_KEYBINDINGS)
|
||||
item(_GNOME_PANEL_ACTION)
|
||||
item(_GNOME_PANEL_ACTION_MAIN_MENU)
|
||||
item(_GNOME_PANEL_ACTION_RUN_DIALOG)
|
||||
|
@ -58,7 +58,7 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
META_EDGE_WINDOW,
|
||||
META_EDGE_XINERAMA,
|
||||
META_EDGE_MONITOR,
|
||||
META_EDGE_SCREEN
|
||||
} MetaEdgeType;
|
||||
|
||||
@ -193,7 +193,7 @@ void meta_rectangle_expand_to_avoiding_struts (
|
||||
* or
|
||||
* meta_rectangle_find_onscreen_edges ()
|
||||
* or
|
||||
* meta_rectangle_find_nonintersected_xinerama_edges()
|
||||
* meta_rectangle_find_nonintersected_monitor_edges()
|
||||
*/
|
||||
void meta_rectangle_free_list_and_elements (GList *filled_list);
|
||||
|
||||
@ -280,11 +280,11 @@ GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
|
||||
GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
|
||||
const GSList *all_struts);
|
||||
|
||||
/* Finds edges between adjacent xineramas which are not covered by the given
|
||||
/* Finds edges between adjacent monitors which are not covered by the given
|
||||
* struts.
|
||||
*/
|
||||
GList* meta_rectangle_find_nonintersected_xinerama_edges (
|
||||
const GList *xinerama_rects,
|
||||
GList* meta_rectangle_find_nonintersected_monitor_edges (
|
||||
const GList *monitor_rects,
|
||||
const GSList *all_struts);
|
||||
|
||||
#endif /* META_BOXES_H */
|
||||
|
@ -317,8 +317,10 @@ struct _MetaButtonLayout
|
||||
* coelesce multiple things together, the appropriate place to
|
||||
* do it is usually META_PRIORITY_BEFORE_REDRAW.
|
||||
*
|
||||
* (FIXME: Use a Clutter paint() function instead, to prevent
|
||||
* starving the repaints)
|
||||
* Note that its usually better to use meta_later_add() rather
|
||||
* than calling g_idle_add() directly; this will make sure things
|
||||
* get run when added from a clutter event handler without
|
||||
* waiting for another repaint cycle.
|
||||
*
|
||||
* If something has a priority lower than the redraw priority
|
||||
* (such as a default priority idle), then it may be arbitrarily
|
||||
|
@ -59,9 +59,10 @@ typedef enum
|
||||
META_PREF_CURSOR_SIZE,
|
||||
META_PREF_COMPOSITING_MANAGER,
|
||||
META_PREF_RESIZE_WITH_RIGHT_BUTTON,
|
||||
META_PREF_FORCE_FULLSCREEN,
|
||||
META_PREF_CLUTTER_PLUGINS,
|
||||
META_PREF_LIVE_HIDDEN_WINDOWS,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
META_PREF_NO_TAB_POPUP
|
||||
} MetaPreference;
|
||||
|
||||
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
|
||||
@ -115,6 +116,7 @@ void meta_prefs_change_workspace_name (int i,
|
||||
const char* meta_prefs_get_cursor_theme (void);
|
||||
int meta_prefs_get_cursor_size (void);
|
||||
gboolean meta_prefs_get_compositing_manager (void);
|
||||
gboolean meta_prefs_get_force_fullscreen (void);
|
||||
|
||||
/**
|
||||
* Sets whether the compositor is turned on.
|
||||
@ -123,6 +125,8 @@ gboolean meta_prefs_get_compositing_manager (void);
|
||||
*/
|
||||
void meta_prefs_set_compositing_manager (gboolean whether);
|
||||
|
||||
void meta_prefs_set_force_fullscreen (gboolean whether);
|
||||
|
||||
GSList * meta_prefs_get_clutter_plugins (void);
|
||||
|
||||
/**
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define META_TYPE_SCREEN (meta_screen_get_type ())
|
||||
#define META_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SCREEN, MetaScreen))
|
||||
#define META_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SCREEN, MetaScreenClass))
|
||||
#define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_SCREEN_TYPE))
|
||||
#define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SCREEN))
|
||||
#define META_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SCREEN))
|
||||
#define META_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SCREEN, MetaScreenClass))
|
||||
|
||||
@ -75,4 +75,9 @@ int meta_screen_get_active_workspace_index (MetaScreen *screen);
|
||||
|
||||
MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
|
||||
|
||||
int meta_screen_get_n_monitors (MetaScreen *screen);
|
||||
void meta_screen_get_monitor_geometry (MetaScreen *screen,
|
||||
int monitor,
|
||||
MetaRectangle *geometry);
|
||||
|
||||
#endif
|
||||
|
@ -131,35 +131,25 @@ GPid meta_show_dialog (const char *type,
|
||||
|
||||
#endif /* !WITH_VERBOSE_MODE */
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#define META_TYPE_NEXUS (meta_nexus_get_type ())
|
||||
#define META_NEXUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_NEXUS, MetaNexus))
|
||||
#define META_NEXUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_NEXUS, MetaNexusClass))
|
||||
#define META_IS_NEXUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_NEXUS))
|
||||
#define META_IS_NEXUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_NEXUS))
|
||||
#define META_NEXUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_NEXUS, MetaNexusClass))
|
||||
|
||||
typedef struct _MetaNexus
|
||||
{
|
||||
GObject parent_instance;
|
||||
} MetaNexus;
|
||||
|
||||
typedef struct _MetaNexusClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
} MetaNexusClass;
|
||||
|
||||
GType meta_nexus_get_type (void) G_GNUC_CONST;
|
||||
MetaNexus *meta_nexus_new ();
|
||||
|
||||
/**
|
||||
* An object which exists purely to attach signals to; this is to receive
|
||||
* signals when a child process exits. The signal is "sigchld" with no detail.
|
||||
*
|
||||
* \bug Eventually we should have a specialised type for objects like these.
|
||||
*/
|
||||
extern MetaNexus *sigchld_nexus;
|
||||
* MetaLaterType:
|
||||
* @META_LATER_RESIZE: call in a resize processing phase that is done
|
||||
* before GTK+ repainting (including window borders) is done.
|
||||
* @META_LATER_BEFORE_REDRAW: call before the stage is redrawn
|
||||
* @META_LATER_IDLE: call at a very low priority (can be blocked
|
||||
* by running animations or redrawing applications)
|
||||
**/
|
||||
typedef enum {
|
||||
META_LATER_RESIZE,
|
||||
META_LATER_BEFORE_REDRAW,
|
||||
META_LATER_IDLE
|
||||
} MetaLaterType;
|
||||
|
||||
guint meta_later_add (MetaLaterType when,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void meta_later_remove (guint later_id);
|
||||
|
||||
#endif /* META_UTIL_H */
|
||||
|
||||
|
@ -116,8 +116,11 @@ void meta_window_minimize (MetaWindow *window);
|
||||
void meta_window_unminimize (MetaWindow *window);
|
||||
const char *meta_window_get_title (MetaWindow *window);
|
||||
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
|
||||
Window meta_window_get_transient_for_as_xid (MetaWindow *window);
|
||||
void meta_window_delete (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
guint meta_window_get_stable_sequence (MetaWindow *window);
|
||||
guint32 meta_window_get_user_time (MetaWindow *window);
|
||||
int meta_window_get_pid (MetaWindow *window);
|
||||
const char *meta_window_get_client_machine (MetaWindow *window);
|
||||
gboolean meta_window_is_modal (MetaWindow *window);
|
||||
|
@ -51,8 +51,8 @@ GType meta_workspace_get_type (void);
|
||||
int meta_workspace_index (MetaWorkspace *workspace);
|
||||
MetaScreen *meta_workspace_get_screen (MetaWorkspace *workspace);
|
||||
GList* meta_workspace_list_windows (MetaWorkspace *workspace);
|
||||
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
void meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
|
||||
MetaRectangle *area);
|
||||
void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp);
|
||||
void meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
MetaWindow *focus_this,
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
<schema>
|
||||
<key>/schemas/apps/mutter/general/overlay_key</key>
|
||||
<applyto>/apps/metacity/general/overlay_key</applyto>
|
||||
<owner>metacity</owner>
|
||||
<applyto>/apps/mutter/general/overlay_key</applyto>
|
||||
<owner>mutter</owner>
|
||||
<type>string</type>
|
||||
<default><Super_L></default>
|
||||
<default>Super_L</default>
|
||||
<locale name="C">
|
||||
<short>Modifier to use for extended window management operations</short>
|
||||
<long>
|
||||
|
@ -71,6 +71,8 @@ meta_fixed_tip_show (Display *xdisplay, int screen_number,
|
||||
if (tip == NULL)
|
||||
{
|
||||
tip = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_window_set_type_hint (GTK_WINDOW(tip), GDK_WINDOW_TYPE_HINT_TOOLTIP);
|
||||
|
||||
{
|
||||
GdkScreen *gdk_screen;
|
||||
GdkRectangle monitor;
|
||||
|
@ -72,7 +72,7 @@ meta_preview_class_init (MetaPreviewClass *class)
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
parent_class = gtk_type_class (GTK_TYPE_BIN);
|
||||
parent_class = g_type_class_peek (GTK_TYPE_BIN);
|
||||
|
||||
gobject_class->finalize = meta_preview_finalize;
|
||||
|
||||
|
@ -1658,8 +1658,16 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
|
||||
op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL);
|
||||
op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL);
|
||||
op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL);
|
||||
op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL);
|
||||
|
||||
if (strcmp(x1, x2)==0)
|
||||
op->data.line.x2 = NULL;
|
||||
else
|
||||
op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL);
|
||||
|
||||
if (strcmp(y1, y2)==0)
|
||||
op->data.line.y2 = NULL;
|
||||
else
|
||||
op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL);
|
||||
|
||||
op->data.line.width = width_val;
|
||||
op->data.line.dash_on_length = dash_on_val;
|
||||
@ -3713,7 +3721,8 @@ text_handler (GMarkupParseContext *context,
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_PARSE,
|
||||
_("<name> specified twice for this theme"));
|
||||
_("<%s> specified twice for this theme"),
|
||||
"name");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3724,7 +3733,8 @@ text_handler (GMarkupParseContext *context,
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_PARSE,
|
||||
_("<author> specified twice for this theme"));
|
||||
_("<%s> specified twice for this theme"),
|
||||
"author");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3735,7 +3745,8 @@ text_handler (GMarkupParseContext *context,
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_PARSE,
|
||||
_("<copyright> specified twice for this theme"));
|
||||
_("<%s> specified twice for this theme"),
|
||||
"copyright");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3746,7 +3757,8 @@ text_handler (GMarkupParseContext *context,
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_PARSE,
|
||||
_("<date> specified twice for this theme"));
|
||||
_("<%s> specified twice for this theme"),
|
||||
"date");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3757,7 +3769,8 @@ text_handler (GMarkupParseContext *context,
|
||||
{
|
||||
set_error (error, context, G_MARKUP_ERROR,
|
||||
G_MARKUP_ERROR_PARSE,
|
||||
_("<description> specified twice for this theme"));
|
||||
_("<%s> specified twice for this theme"),
|
||||
"description");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2645,6 +2645,7 @@ parse_size_unchecked (MetaDrawSpec *spec,
|
||||
void
|
||||
meta_draw_spec_free (MetaDrawSpec *spec)
|
||||
{
|
||||
if (!spec) return;
|
||||
free_tokens (spec->tokens, spec->n_tokens);
|
||||
g_slice_free (MetaDrawSpec, spec);
|
||||
}
|
||||
@ -3489,10 +3490,25 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
|
||||
x1 = parse_x_position_unchecked (op->data.line.x1, env);
|
||||
y1 = parse_y_position_unchecked (op->data.line.y1, env);
|
||||
x2 = parse_x_position_unchecked (op->data.line.x2, env);
|
||||
y2 = parse_y_position_unchecked (op->data.line.y2, env);
|
||||
|
||||
gdk_draw_line (drawable, gc, x1, y1, x2, y2);
|
||||
if (!op->data.line.x2 &&
|
||||
!op->data.line.y2 &&
|
||||
op->data.line.width==0)
|
||||
gdk_draw_point (drawable, gc, x1, y1);
|
||||
else
|
||||
{
|
||||
if (op->data.line.x2)
|
||||
x2 = parse_x_position_unchecked (op->data.line.x2, env);
|
||||
else
|
||||
x2 = x1;
|
||||
|
||||
if (op->data.line.y2)
|
||||
y2 = parse_y_position_unchecked (op->data.line.y2, env);
|
||||
else
|
||||
y2 = y1;
|
||||
|
||||
gdk_draw_line (drawable, gc, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (gc));
|
||||
}
|
||||
@ -5220,16 +5236,6 @@ meta_theme_draw_frame_by_name (MetaTheme *theme,
|
||||
mini_icon, icon);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
meta_theme_get_frame_borders (MetaTheme *theme,
|
||||
MetaFrameType type,
|
||||
@ -5526,6 +5532,15 @@ meta_theme_define_color_constant (MetaTheme *theme,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a colour constant.
|
||||
*
|
||||
* \param theme the theme containing the constant
|
||||
* \param name the name of the constant
|
||||
* \param value [out] the string representation of the colour, or NULL if it
|
||||
* doesn't exist
|
||||
* \return TRUE if it exists, FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
meta_theme_lookup_color_constant (MetaTheme *theme,
|
||||
const char *name,
|
||||
@ -5572,6 +5587,13 @@ meta_gtk_widget_get_font_desc (GtkWidget *widget,
|
||||
return font_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the letters in a particular font.
|
||||
*
|
||||
* \param font_desc the font
|
||||
* \param context the context of the font
|
||||
* \return the height of the letters
|
||||
*/
|
||||
int
|
||||
meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc,
|
||||
PangoContext *context)
|
||||
@ -6117,6 +6139,13 @@ meta_gtk_arrow_to_string (GtkArrowType arrow)
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fill_type from a string. The inverse of
|
||||
* meta_image_fill_type_to_string().
|
||||
*
|
||||
* \param str a string representing a fill_type
|
||||
* \result the fill_type, or -1 if it represents no fill_type.
|
||||
*/
|
||||
MetaImageFillType
|
||||
meta_image_fill_type_from_string (const char *str)
|
||||
{
|
||||
@ -6128,6 +6157,13 @@ meta_image_fill_type_from_string (const char *str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of a fill_type. The inverse of
|
||||
* meta_image_fill_type_from_string().
|
||||
*
|
||||
* \param fill_type the fill type
|
||||
* \result a string representing that type
|
||||
*/
|
||||
const char*
|
||||
meta_image_fill_type_to_string (MetaImageFillType fill_type)
|
||||
{
|
||||
@ -6142,7 +6178,15 @@ meta_image_fill_type_to_string (MetaImageFillType fill_type)
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
/* gtkstyle.c cut-and-pastage */
|
||||
/**
|
||||
* Takes a colour "a", scales the lightness and saturation by a certain amount,
|
||||
* and sets "b" to the resulting colour.
|
||||
* gtkstyle.c cut-and-pastage.
|
||||
*
|
||||
* \param a the starting colour
|
||||
* \param b [out] the resulting colour
|
||||
* \param k amount to scale lightness and saturation by
|
||||
*/
|
||||
static void
|
||||
gtk_style_shade (GdkColor *a,
|
||||
GdkColor *b,
|
||||
@ -6177,6 +6221,13 @@ gtk_style_shade (GdkColor *a,
|
||||
b->blue = blue * 65535.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a red/green/blue triplet to a hue/lightness/saturation triplet.
|
||||
*
|
||||
* \param r on input, red; on output, hue
|
||||
* \param g on input, green; on output, lightness
|
||||
* \param b on input, blue; on output, saturation
|
||||
*/
|
||||
static void
|
||||
rgb_to_hls (gdouble *r,
|
||||
gdouble *g,
|
||||
@ -6248,6 +6299,13 @@ rgb_to_hls (gdouble *r,
|
||||
*b = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hue/lightness/saturation triplet to a red/green/blue triplet.
|
||||
*
|
||||
* \param h on input, hue; on output, red
|
||||
* \param l on input, lightness; on output, green
|
||||
* \param s on input, saturation; on output, blue
|
||||
*/
|
||||
static void
|
||||
hls_to_rgb (gdouble *h,
|
||||
gdouble *l,
|
||||
@ -6536,6 +6594,14 @@ draw_bg_gradient_composite (const MetaTextureSpec *bg,
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the earliest version of the theme format which required support
|
||||
* for a particular button. (For example, "shade" first appeared in v2, and
|
||||
* "close" in v1.)
|
||||
*
|
||||
* \param type the button type
|
||||
* \return the number of the theme format
|
||||
*/
|
||||
guint
|
||||
meta_theme_earliest_version_with_button (MetaButtonType type)
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ meta_area_class_init (MetaAreaClass *class)
|
||||
|
||||
object_class = (GtkObjectClass*) class;
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
parent_class = gtk_type_class (gtk_misc_get_type ());
|
||||
parent_class = g_type_class_peek (gtk_misc_get_type ());
|
||||
|
||||
gobject_class->finalize = meta_area_finalize;
|
||||
|
||||
|
@ -656,7 +656,7 @@ meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
/* we shouldn't cause focus if we're an override redirect
|
||||
* toplevel which is not foreign
|
||||
*/
|
||||
if (window && gdk_window_get_type (window) == GDK_WINDOW_TEMP)
|
||||
if (window && gdk_window_get_window_type (window) == GDK_WINDOW_TEMP)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@ -773,7 +773,7 @@ meta_ui_parse_accelerator (const char *accel,
|
||||
*keycode = 0;
|
||||
*mask = 0;
|
||||
|
||||
if (strcmp (accel, "disabled") == 0)
|
||||
if (!accel[0] || strcmp (accel, "disabled") == 0)
|
||||
return TRUE;
|
||||
|
||||
meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
|
||||
@ -860,7 +860,7 @@ meta_ui_parse_modifier (const char *accel,
|
||||
|
||||
*mask = 0;
|
||||
|
||||
if (accel == NULL || strcmp (accel, "disabled") == 0)
|
||||
if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
|
||||
return TRUE;
|
||||
|
||||
meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
|
||||
|
@ -79,7 +79,7 @@ get_size (Display *d, Drawable draw,
|
||||
*yp = y;
|
||||
if (widthp)
|
||||
*widthp = width;
|
||||
if (*heightp)
|
||||
if (heightp)
|
||||
*heightp = height;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user