Compare commits

..

16 Commits

Author SHA1 Message Date
Carlos Garnacho
3ed80495e0 compositor: emit grab-op-begin/end signals on plugin grabs
This makes it possible to track there grabs triggered this way, in
addition to the ones handled by mutter.
2014-06-25 16:38:29 +02:00
Carlos Garnacho
f13c86d651 gesture-tracker: Implement threshold-based sequence rejection
If a sequence moves past a certain distance without being used by a
gesture, reject it so clients may see and react to it ASAP. This makes
gestures to be began by initially quasi-static touchpoints, in addition to
quasi-simultaneous.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
be2ca66735 wayland: Export meta_wayland_touch_cancel()
This will be necessary in order to hook the gesture tracker
to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
2df807549e frames: Keep information about the ongoing grab operation, and retry if needed.
When a passive touch grab is rejected over the frame, management is punted to
the frame itself, and pointer events emulated, but the attempt to transfer the
grab from the GDK connection to the Clutter one fails with AlreadyGrabbed, and
will fail until the Clutter connection receives the XI_TouchEnd resulting from
XIRejectTouch, gotten after the XI_ButtonPress on the GDK connection.

In order to bypass this shortcoming, store the current grab operation on the
frame as long as the button is pressed, so it is retried once on the next
motion event happening during frame dragging, that will have a recent enough
timestamp to succeed. If no grabbing succeeded, the current grab operation
data will be reset on GDK_BUTTON_RELEASE.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66cdb1bb71 backend: Use the most recent event time on replayed touch events
When a touch sequence is passively grabbed and later rejected, events
will be replayed on the next client in propagation order, although those
events (either transformed to pointer events or not) will contain the
original timestamps, this will make grabs fail with InvalidTime if triggered
from the replayed ButtonPress/TouchBegin handler.

In order to work around this, store the most recent event time (presumably
gotten from the XI_TouchEnd caused by the passive grab being rejected), and
use that time on the events being replayed afterwards and grabs, so we don't
possibly fail with InvalidTime if those events result in a compositor grab.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
8030a2972e display: Set an X11 passive touch grab on the root window
Touch events will be caught first by the compositor this way,
whenever the MetaGestureTracker notifies of the accepted/rejected
state of a sequence, XIAllowTouchEvents() will be called on it
accordingly, so it is handled exclusively by the compositor or
punted to clients.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ba086dea8c events: Hook MetaGestureTracker to display event processing
Events aren't actually consumed by the MetaGestureTracker, but it
rather defines whether the event will reach clients, or the stage.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
6a02d7dfa3 backend: Ensure touch event coordinates are translated to the stage's
Now that those events are going to be received, coordinates translation
should also happen on those.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
c5db56da5c display: Add a getter for the gesture tracker
The MetaDisplay will contain a global MetaGestureTracker,
shared through this getter.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b5c605df5e core: Add MetaGestureTracker
This object tracks both touch sequences happening on the stage and
gestures attached to the stage actor. When a gesture emits
::gesture-begin, All triggering sequences and future ones will be
marked as "accepted" by the compositor, and events will be listened
for meanwhile there are active gestures.

If a sequence goes unclaimed for a short time, it will be
automatically "denied", and punted to the client or shell element
below.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
4ad2865cce events: Update current time on CLUTTER_TOUCH_BEGIN events
Just as with key/button press events, update the current interaction
time when a touch begins on a window.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
b9687d1a72 ui: Remove unneeded code
There's no way now that GDK will hold a grab, so it is safe to remove
this now.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
66d18fcc55 x11/events: Filter out all pointer/touch GDK events
Mutter does its own input event processing, including for the places
where interaction is wanted with the remaining GTK UI elements
(frames), so GDK is largely disposable.

Even though the GDK display connection remains, and events will
be delivered over there due to event selections on that display,
all pointer and touch events will be handled and filtered out by
the GDK filter function.

The dedicated event processing meant for frames in src/ui/ui.c
now hooks to the display connection through
meta_display_events_x11_add_func(), added to let all event filters
run and stop processing at a single point.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
321cd5d85f ui: Remove XI_TouchBegin handling from window frame event handlers
This is now unnecessary as only pointer events are selected, so pointer
emulation will take care of sending only pointer events.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
ae91de5d03 frame: Only select for ButtonPress/Release/Motion/Crossing
Touch events are largely ignored on GdkEvent emulation, so only
make frames receive pointer events, only the pointer emulating
touch will be reported, and any other further touches will be
ignored, which is about the behavior we want. This makes window
dragging possible again on touch.
2014-06-25 15:17:13 +02:00
Carlos Garnacho
7247b8d81b backend-x11: Remove pointless goto
The function is not as complex as needing that, plus it always jumped
anytime bypass_clutter is TRUE, so make all conditional code depend on
that.
2014-06-25 15:17:12 +02:00
131 changed files with 16118 additions and 13536 deletions

11
.gitignore vendored
View File

@@ -43,7 +43,6 @@ POTFILES
po/*.pot
libmutter.pc
mutter
mutter-restart-helper
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@@ -52,6 +51,16 @@ testasyncgetprop
testboxes
testgradient
m4/*
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]

59
NEWS
View File

@@ -1,62 +1,3 @@
3.13.91
=======
* Misc. bug fixes [Carlos; #735452]
Contributors:
Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
Rico Tzschichholz
Translations:
Chao-Hsiung Liao po/zh_HK, zh_TW.po, Enrico Nicoletto [pt_BR],
Kjartan Maraas [nb], Fran Diéguez [gl], Yosef Or Boczko [he],
Maria Mavridou [el], Claude Paroz [fr]
3.13.90
=======
* Only call XSync() once per frame [Rui; #728464]
* Update capabilities on device list changes [Carlos; #733563]
* Make use of GLSL optional [Adel; #733623]
* Handle gestures and touch events on wayland [Carlos; #733631]
* Add support for unminimize compositor effects [Cosimo; #733789]
* Always set the frame background to None [Giovanni; #734054]
* Add backend methods to handle keymaps [Rui; #734301]
* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400]
* Rely on explicit -backward switcher keybindings instead of <shift>-magic
[Christophe; #732295, #732385]
* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852,
#734960]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg,
Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos,
Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters,
Owen W. Taylor
Translations:
Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi],
ngoswami [as], Daniel Mustieles [es]
3.13.4
======
* Fix move/resize operations for wayland clients [Marek; #731237]
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
* Handle keysyms without the XF86 prefix [Owen; #727993]
* Add touch gesture support [Carlos]
* Fix a deadlock when exiting [Owen; #733068]
* Add framework for restarting the compositor with nice visuals
[Owen; #733026]
* Toggle seat capabilities on VT switch [Carlos; #733563]
* Misc bug fixes [Florian, Owen; #732695, #732350]
Contributors:
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
Enrico Nicoletto [pt_BR]
3.13.3
======
* Improve behavior of window buttons with compositor menus [Florian; #731058]

View File

@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [91])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -72,28 +72,20 @@ CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.25.10
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
$CLUTTER_PACKAGE >= 1.19.5
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.17.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
cogl-1.0 >= 1.17.1
gbm
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0
xcomposite >= 0.2
xcursor
xdamage
xext
xfixes
xi >= 1.6.0
xkbfile
xkeyboard-config
xkbcommon >= 0.4.3
xkbcommon-x11
x11-xcb
xcb-randr
"
GLIB_GSETTINGS
@@ -192,27 +184,20 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no])
if test $have_wayland = yes; then
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test $WAYLAND_SCANNER = "no"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
fi
AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes])
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -249,8 +234,16 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found])
fi
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
[XKB base dir])
found_xkb=no
AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h,
found_xkb=yes)],
, $ALL_X_LIBS)
if test "x$found_xkb" = "xyes"; then
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
fi
RANDR_LIBS=
found_randr=no

View File

@@ -45,68 +45,26 @@
_description="Move window one monitor down" />
<KeyListEntry name="switch-applications"
reverse-entry="switch-applications-backward"
_description="Switch applications"/>
<KeyListEntry name="switch-applications-backward"
reverse-entry="switch-applications"
hidden="true"
_description="Switch to previous application"/>
<KeyListEntry name="switch-windows"
reverse-entry="switch-windows-backward"
_description="Switch windows"/>
<KeyListEntry name="switch-windows-backward"
reverse-entry="switch-windows"
hidden="true"
_description="Switch to previous window"/>
<KeyListEntry name="switch-group"
reverse-entry="switch-group-backward"
_description="Switch windows of an application"/>
<KeyListEntry name="switch-group-backward"
reverse-entry="switch-group"
hidden="true"
_description="Switch to previous window of an application"/>
<KeyListEntry name="switch-panels"
reverse-entry="switch-panels-backward"
_description="Switch system controls"/>
<KeyListEntry name="switch-panels-backward"
reverse-entry="switch-panels"
hidden="true"
_description="Switch to previous system control"/>
<KeyListEntry name="cycle-windows"
reverse-entry="cycle-windows-backward"
_description="Switch windows directly"/>
<KeyListEntry name="cycle-windows-backward"
reverse-entry="cycle-windows"
hidden="true"
_description="Switch directly to previous window"/>
<KeyListEntry name="cycle-group"
reverse-entry="cycle-group-backward"
_description="Switch windows of an app directly"/>
<KeyListEntry name="cycle-group-backward"
reverse-entry="cycle-group"
hidden="true"
_description="Switch directly to previous window of an app"/>
<KeyListEntry name="cycle-panels"
reverse-entry="cycle-panels-backward"
_description="Switch system controls directly"/>
<KeyListEntry name="cycle-panels-backward"
reverse-entry="cycle-panels"
hidden="true"
_description="Switch directly to previous system control"/>
<KeyListEntry name="show-desktop"
_description="Hide all normal windows"/>

View File

@@ -300,7 +300,6 @@ MetaPluginVersion
META_PLUGIN_DECLARE
meta_plugin_switch_workspace_completed
meta_plugin_minimize_completed
meta_plugin_unminimize_completed
meta_plugin_maximize_completed
meta_plugin_unmaximize_completed
meta_plugin_map_completed

View File

@@ -23,8 +23,7 @@ environment.</description>
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>C</programming-language>
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<maintainer>
<foaf:Person>

1520
po/as.po

File diff suppressed because it is too large Load Diff

3490
po/el.po

File diff suppressed because it is too large Load Diff

895
po/es.po

File diff suppressed because it is too large Load Diff

1259
po/eu.po

File diff suppressed because it is too large Load Diff

1421
po/fi.po

File diff suppressed because it is too large Load Diff

1056
po/fr.po

File diff suppressed because it is too large Load Diff

886
po/gl.po

File diff suppressed because it is too large Load Diff

880
po/he.po

File diff suppressed because it is too large Load Diff

1010
po/lt.po

File diff suppressed because it is too large Load Diff

1028
po/nb.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1291
po/ru.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,6 @@ AM_CPPFLAGS = \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
@@ -35,16 +33,13 @@ mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
meta/meta-version.h \
mutter-enum-types.h \
mutter-enum-types.c
if HAVE_WAYLAND
mutter_built_sources += \
mutter-enum-types.c \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h
endif
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
@@ -52,7 +47,7 @@ wayland_protocols = \
libmutter_la_SOURCES = \
backends/meta-backend.c \
meta/meta-backend.h \
backends/meta-backend.h \
backends/meta-backend-private.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
@@ -72,8 +67,6 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/meta-stage.h \
backends/meta-stage.c \
backends/edid-parse.c \
backends/edid.h \
backends/x11/meta-backend-x11.c \
@@ -118,6 +111,10 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -155,8 +152,8 @@ libmutter_la_SOURCES = \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
core/gesture-tracker.c \
core/gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@@ -168,7 +165,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/restart.c \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@@ -213,12 +209,7 @@ libmutter_la_SOURCES = \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h
if HAVE_WAYLAND
libmutter_la_SOURCES += \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
x11/mutter-Xatomtype.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
@@ -243,7 +234,6 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h
endif
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
@@ -281,7 +271,6 @@ libmutterinclude_headers = \
meta/group.h \
meta/keybindings.h \
meta/main.h \
meta/meta-backend.h \
meta/meta-background-actor.h \
meta/meta-background-group.h \
meta/meta-background.h \
@@ -325,10 +314,6 @@ bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
libexec_PROGRAMS = mutter-restart-helper
mutter_restart_helper_SOURCES = core/restart-helper.c
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@@ -376,12 +361,10 @@ dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
CLEANFILES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers) \
$(typelib_DATA) \
$(gir_DATA)
DISTCLEANFILES = \
$(libmutterinclude_built_headers)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
@@ -394,10 +377,7 @@ EXTRA_DIST = \
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml
BUILT_SOURCES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers)
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)

View File

@@ -28,15 +28,7 @@
#include <glib-object.h>
#include <xkbcommon/xkbcommon.h>
#include <meta/meta-backend.h>
#include <meta/meta-idle-monitor.h>
#include "meta-cursor-renderer.h"
#include "meta-monitor-manager.h"
#define DEFAULT_XKB_RULES_FILE "evdev"
#define DEFAULT_XKB_MODEL "pc105+inet"
#include "meta-backend.h"
#define META_TYPE_BACKEND (meta_backend_get_type ())
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
@@ -74,37 +66,6 @@ struct _MetaBackendClass
void (* warp_pointer) (MetaBackend *backend,
int x,
int y);
void (* set_keymap) (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options);
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
void (* lock_layout_group) (MetaBackend *backend,
guint idx);
void (* update_screen_size) (MetaBackend *backend, int width, int height);
void (* select_stage_events) (MetaBackend *backend);
};
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
#endif /* META_BACKEND_PRIVATE_H */

View File

@@ -24,11 +24,12 @@
#include "config.h"
#include <meta/meta-backend.h>
#include "meta-backend.h"
#include "meta-backend-private.h"
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#include "meta-stage.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
@@ -36,13 +37,6 @@
static MetaBackend *_backend;
/**
* meta_get_backend:
*
* Accessor for the singleton MetaBackend.
*
* Returns: (transfer none): The only #MetaBackend there is.
*/
MetaBackend *
meta_get_backend (void)
{
@@ -53,8 +47,6 @@ struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
ClutterActor *stage;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
@@ -78,40 +70,12 @@ meta_backend_finalize (GObject *object)
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_sync_screen_size (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int width, height;
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
meta_backend_sync_screen_size (backend);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->stage = meta_stage_new ();
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend);
meta_backend_sync_screen_size (backend);
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
}
@@ -139,21 +103,6 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
return TRUE;
}
static void
meta_backend_real_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
clutter_actor_set_size (priv->stage, width, height);
}
static void
meta_backend_real_select_stage_events (MetaBackend *backend)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@@ -165,15 +114,6 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->update_screen_size = meta_backend_real_update_screen_size;
klass->select_stage_events = meta_backend_real_select_stage_events;
g_signal_new ("keymap-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static void
@@ -205,9 +145,6 @@ meta_backend_post_init (MetaBackend *backend)
META_BACKEND_GET_CLASS (backend)->post_init (backend);
}
/**
* meta_backend_get_idle_monitor: (skip)
*/
MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id)
@@ -223,9 +160,6 @@ meta_backend_get_idle_monitor (MetaBackend *backend,
return backend->device_monitors[device_id];
}
/**
* meta_backend_get_monitor_manager: (skip)
*/
MetaMonitorManager *
meta_backend_get_monitor_manager (MetaBackend *backend)
{
@@ -234,9 +168,6 @@ meta_backend_get_monitor_manager (MetaBackend *backend)
return priv->monitor_manager;
}
/**
* meta_backend_get_cursor_renderer: (skip)
*/
MetaCursorRenderer *
meta_backend_get_cursor_renderer (MetaBackend *backend)
{
@@ -245,9 +176,6 @@ meta_backend_get_cursor_renderer (MetaBackend *backend)
return priv->cursor_renderer;
}
/**
* meta_backend_grab_device: (skip)
*/
gboolean
meta_backend_grab_device (MetaBackend *backend,
int device_id,
@@ -256,9 +184,6 @@ meta_backend_grab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
}
/**
* meta_backend_ungrab_device: (skip)
*/
gboolean
meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
@@ -267,9 +192,6 @@ meta_backend_ungrab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
}
/**
* meta_backend_warp_pointer: (skip)
*/
void
meta_backend_warp_pointer (MetaBackend *backend,
int x,
@@ -278,47 +200,6 @@ meta_backend_warp_pointer (MetaBackend *backend,
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
}
void
meta_backend_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
}
/**
* meta_backend_get_keymap: (skip)
*/
struct xkb_keymap *
meta_backend_get_keymap (MetaBackend *backend)
{
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
}
void
meta_backend_lock_layout_group (MetaBackend *backend,
guint idx)
{
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
}
/**
* meta_backend_get_stage:
* @backend: A #MetaBackend
*
* Gets the global #ClutterStage that's managed by this backend.
*
* Returns: (transfer none): the #ClutterStage
*/
ClutterActor *
meta_backend_get_stage (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->stage;
}
static GType
get_backend_type (void)
{
@@ -391,9 +272,6 @@ static GSourceFuncs event_funcs = {
event_dispatch
};
/**
* meta_clutter_init: (skip)
*/
void
meta_clutter_init (void)
{

View File

@@ -27,7 +27,9 @@
#include <glib-object.h>
#include <clutter/clutter.h>
#include <meta/meta-idle-monitor.h>
#include "meta-monitor-manager.h"
#include "meta-cursor-renderer.h"
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass;
@@ -36,15 +38,21 @@ GType meta_backend_get_type (void);
MetaBackend * meta_get_backend (void);
void meta_backend_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options);
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
void meta_backend_lock_layout_group (MetaBackend *backend,
guint idx);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
ClutterActor *meta_backend_get_stage (MetaBackend *backend);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
void meta_clutter_init (void);

View File

@@ -27,14 +27,14 @@
#include "meta-cursor-renderer.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include "meta-stage.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorRendererPrivate
{
int current_x, current_y;
@@ -51,20 +51,17 @@ static void
queue_redraw (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage = meta_backend_get_stage (backend);
CoglTexture *texture;
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
/* During early initialization, we can have no stage */
if (!stage)
return;
if (priv->displayed_cursor && !priv->handled_by_backend)
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
if (priv->handled_by_backend)
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
else
texture = NULL;
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
}
static gboolean

View File

@@ -23,6 +23,8 @@
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
@@ -30,6 +32,7 @@
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing;

View File

@@ -34,21 +34,25 @@
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "meta-backend-private.h"
#include "meta-backend.h"
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
@@ -56,12 +60,10 @@ static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing)
return NULL;
if (meta_display_windows_are_interactable (display))
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
@@ -95,9 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
MetaBackend *backend = meta_get_backend ();
self->renderer = meta_backend_get_cursor_renderer (backend);
self->is_showing = TRUE;
}
@@ -130,9 +129,47 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
}
static MetaCursorTracker *
meta_cursor_tracker_new (void)
make_wayland_cursor_tracker (MetaScreen *screen)
{
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
MetaBackend *backend = meta_get_backend ();
MetaWaylandCompositor *compositor;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->pointer.cursor_tracker = self;
meta_cursor_tracker_update_position (self, 0, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
static MetaCursorTracker *
meta_cursor_tracker_new (MetaScreen *screen)
{
if (meta_is_wayland_compositor ())
return make_wayland_cursor_tracker (screen);
else
return make_x11_cursor_tracker (screen);
}
static MetaCursorTracker *_cursor_tracker;
@@ -149,7 +186,7 @@ MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new ();
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker;
}
@@ -170,13 +207,12 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
@@ -207,7 +243,6 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
@@ -217,7 +252,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (tracker->xfixes_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;

View File

@@ -27,7 +27,7 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend-private.h"
#include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
@@ -39,9 +39,7 @@
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <cogl/cogl-wayland-server.h>
#endif
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
@@ -249,7 +247,6 @@ meta_cursor_reference_from_theme (MetaCursor cursor)
return self;
}
#ifdef HAVE_WAYLAND
static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
struct wl_resource *buffer,
@@ -348,7 +345,6 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
return self;
}
#endif
CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,

View File

@@ -28,15 +28,13 @@ MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/common.h>
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);

View File

@@ -38,7 +38,7 @@
#include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-backend-private.h"
#include "meta-backend.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));

View File

@@ -60,7 +60,7 @@ typedef struct {
gboolean enabled;
MetaRectangle rect;
float refresh_rate;
MetaMonitorTransform transform;
enum wl_output_transform transform;
gboolean is_primary;
gboolean is_presentation;
@@ -656,20 +656,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0)
{
if (strncmp (text, "normal", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
else if (strncmp (text, "left", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_90;
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
else if (strncmp (text, "upside_down", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_180;
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270;
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text);
}
else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ?
META_MONITOR_TRANSFORM_FLIPPED : 0;
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
else if (strcmp (parser->output_field, "reflect_y") == 0)
{
/* FIXME (look at the rotation map in monitor.c) */
@@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
@@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
}
@@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
@@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
}
else
@@ -1512,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x,
output->rect.y,
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
}
@@ -1621,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
}
static gboolean
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
MetaMonitorTransform transform,
MetaOutput *output)
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
enum wl_output_transform transform,
MetaOutput *output)
{
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);

View File

@@ -27,7 +27,7 @@
#include "meta-monitor-manager-dummy.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].winsys_id = 1;
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");

View File

@@ -37,7 +37,7 @@
#include <meta/errors.h>
#include "meta-monitor-config.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h"
#include "meta-backend.h"
enum {
CONFIRM_DISPLAY_CHANGE,
@@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.output_id = 0;
g_array_append_val (monitor_infos, info);
@@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
if (output->is_primary || info->output_id == 0)
info->output_id = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
@@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
@@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
(gint64)output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y;
int new_screen_width, new_screen_height;
guint transform;
guint output_index;
guint output_id;
GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
@@ -694,6 +694,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new ();
@@ -755,8 +756,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -767,18 +768,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
{
MetaOutput *output;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode))
{
@@ -823,12 +824,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@@ -837,7 +838,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
output_info = g_slice_new0 (MetaOutputInfo);
output_info->output = &manager->outputs[output_index];
output_info->output = &manager->outputs[output_id];
if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary;
@@ -908,7 +909,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
guint serial,
guint output_index,
guint output_id,
gint value)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@@ -922,14 +923,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (value < 0 || value > 100)
{

View File

@@ -41,6 +41,8 @@
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
@@ -58,23 +60,12 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
META_MONITOR_TRANSFORM_90,
META_MONITOR_TRANSFORM_180,
META_MONITOR_TRANSFORM_270,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_270,
} MetaMonitorTransform;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong winsys_id;
glong output_id;
char *name;
char *vendor;
char *product;
@@ -123,7 +114,7 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
MetaMonitorTransform transform;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
@@ -171,14 +162,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong winsys_id;
glong output_id;
};
/*
@@ -194,7 +185,7 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode;
int x;
int y;
MetaMonitorTransform transform;
enum wl_output_transform transform;
GPtrArray *outputs;
};
@@ -348,7 +339,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}

View File

@@ -188,49 +188,6 @@ meta_backend_native_warp_pointer (MetaBackend *backend,
clutter_evdev_warp_pointer (device, time_, x, y);
}
static void
meta_backend_native_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
struct xkb_rule_names names;
struct xkb_keymap *keymap;
struct xkb_context *context;
names.rules = DEFAULT_XKB_RULES_FILE;
names.model = DEFAULT_XKB_MODEL;
names.layout = layouts;
names.variant = variants;
names.options = options;
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
clutter_evdev_set_keyboard_map (manager, keymap);
g_signal_emit_by_name (backend, "keymap-changed", 0);
xkb_keymap_unref (keymap);
}
static struct xkb_keymap *
meta_backend_native_get_keymap (MetaBackend *backend)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
return clutter_evdev_get_keyboard_map (manager);
}
static void
meta_backend_native_lock_layout_group (MetaBackend *backend,
guint idx)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_layout_index (manager, idx);
}
static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
@@ -242,9 +199,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->warp_pointer = meta_backend_native_warp_pointer;
backend_class->set_keymap = meta_backend_native_set_keymap;
backend_class->get_keymap = meta_backend_native_get_keymap;
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
}
static void

View File

@@ -41,7 +41,8 @@
#include "dbus-utils.h"
#include "meta-dbus-login1.h"
#include "backends/meta-backend-private.h"
#include "wayland/meta-wayland-private.h"
#include "backends/meta-backend.h"
#include "meta-cursor-renderer-native.h"
struct _MetaLauncher
@@ -100,15 +101,15 @@ session_unpause (void)
clutter_egl_thaw_master_clock ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
ClutterActor *stage = meta_backend_get_stage (backend);
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (stage);
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
}
}

View File

@@ -40,6 +40,8 @@
#include <meta/errors.h>
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
@@ -257,7 +259,7 @@ find_output_by_id (MetaOutput *outputs,
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
@@ -361,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
@@ -406,7 +408,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->winsys_id = connector->connector_id;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
@@ -489,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id);
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
@@ -665,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
@@ -746,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->winsys_id;
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;

View File

@@ -24,18 +24,11 @@
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/sync.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XKBrules.h>
#include <X11/Xlib-xcb.h>
#include <xkbcommon/xkbcommon-x11.h>
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
@@ -50,7 +43,6 @@ struct _MetaBackendX11Private
{
/* The host X11 display */
Display *xdisplay;
xcb_connection_t *xcb;
GSource *source;
int xsync_event_base;
@@ -60,11 +52,6 @@ struct _MetaBackendX11Private
int xinput_event_base;
int xinput_error_base;
Time latest_evtime;
uint8_t xkb_event_base;
uint8_t xkb_error_base;
struct xkb_keymap *keymap;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
@@ -158,21 +145,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
}
}
static void
keymap_changed (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap)
{
xkb_keymap_unref (priv->keymap);
priv->keymap = NULL;
}
g_signal_emit_by_name (backend, "keymap-changed", 0);
}
static void
handle_host_xevent (MetaBackend *backend,
XEvent *event)
@@ -183,37 +155,9 @@ handle_host_xevent (MetaBackend *backend,
XGetEventData (priv->xdisplay, &event->xcookie);
{
MetaDisplay *display = meta_get_display ();
if (display)
{
MetaCompositor *compositor = display->compositor;
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
bypass_clutter = TRUE;
}
}
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
if (event->type == priv->xkb_event_base)
{
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
{
switch (xkb_ev->xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
keymap_changed (backend);
default:
break;
}
}
}
{
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
@@ -308,24 +252,6 @@ x_event_source_new (MetaBackend *backend)
return source;
}
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (priv->xdisplay),
False, &mask, 1, &mods);
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
@@ -363,19 +289,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
take_touch_grab (backend);
priv->xcb = XGetXCBConnection (priv->xdisplay);
if (!xkb_x11_setup_xkb_extension (priv->xcb,
XKB_X11_MIN_MAJOR_XKB_VERSION,
XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
NULL, NULL,
&priv->xkb_event_base,
&priv->xkb_error_base))
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
@@ -469,198 +382,6 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
x, y);
}
static void
get_xkbrf_var_defs (Display *xdisplay,
const char *layouts,
const char *variants,
const char *options,
char **rules_p,
XkbRF_VarDefsRec *var_defs)
{
char *rules = NULL;
/* Get it from the X property or fallback on defaults */
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
{
rules = strdup (DEFAULT_XKB_RULES_FILE);
var_defs->model = strdup (DEFAULT_XKB_MODEL);
var_defs->layout = NULL;
var_defs->variant = NULL;
var_defs->options = NULL;
}
/* Swap in our new options... */
free (var_defs->layout);
var_defs->layout = strdup (layouts);
free (var_defs->variant);
var_defs->variant = strdup (variants);
free (var_defs->options);
var_defs->options = strdup (options);
/* Sometimes, the property is a file path, and sometimes it's
not. Normalize it so it's always a file path. */
if (rules[0] == '/')
*rules_p = g_strdup (rules);
else
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
free (rules);
}
static void
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
{
free (var_defs->model);
free (var_defs->layout);
free (var_defs->variant);
free (var_defs->options);
}
static void
free_xkb_component_names (XkbComponentNamesRec *p)
{
free (p->keymap);
free (p->keycodes);
free (p->types);
free (p->compat);
free (p->symbols);
free (p->geometry);
}
static void
upload_xkb_description (Display *xdisplay,
const gchar *rules_file_path,
XkbRF_VarDefsRec *var_defs,
XkbComponentNamesRec *comp_names)
{
XkbDescRec *xkb_desc;
gchar *rules_file;
/* Upload it to the X server using the same method as setxkbmap */
xkb_desc = XkbGetKeyboardByName (xdisplay,
XkbUseCoreKbd,
comp_names,
XkbGBN_AllComponentsMask,
XkbGBN_AllComponentsMask &
(~XkbGBN_GeometryMask), True);
if (!xkb_desc)
{
g_warning ("Couldn't upload new XKB keyboard description");
return;
}
XkbFreeKeyboard (xkb_desc, 0, True);
rules_file = g_path_get_basename (rules_file_path);
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
g_warning ("Couldn't update the XKB root window property");
g_free (rules_file);
}
static void
meta_backend_x11_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbRF_RulesRec *xkb_rules;
XkbRF_VarDefsRec xkb_var_defs = { 0 };
gchar *rules_file_path;
get_xkbrf_var_defs (priv->xdisplay,
layouts,
variants,
options,
&rules_file_path,
&xkb_var_defs);
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
if (xkb_rules)
{
XkbComponentNamesRec xkb_comp_names = { 0 };
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
free_xkb_component_names (&xkb_comp_names);
XkbRF_Free (xkb_rules, True);
}
else
{
g_warning ("Couldn't load XKB rules");
}
free_xkbrf_var_defs (&xkb_var_defs);
g_free (rules_file_path);
}
static struct xkb_keymap *
meta_backend_x11_get_keymap (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap == NULL)
{
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
priv->keymap = xkb_x11_keymap_new_from_device (context,
priv->xcb,
xkb_x11_get_core_keyboard_device_id (priv->xcb),
XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
}
return priv->keymap;
}
static void
meta_backend_x11_lock_layout_group (MetaBackend *backend,
guint idx)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
}
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
static void
meta_backend_x11_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
@@ -670,14 +391,10 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
backend_class->set_keymap = meta_backend_x11_set_keymap;
backend_class->get_keymap = meta_backend_x11_get_keymap;
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
}
static void
@@ -698,6 +415,12 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
if (compositor == NULL)
return None;
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
return clutter_x11_get_stage_window (stage);
}

View File

@@ -35,8 +35,6 @@
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h>
#include <X11/Xlib-xcb.h>
#include <xcb/randr.h>
#include "meta-backend-x11.h"
#include <meta/main.h>
@@ -44,7 +42,7 @@
#include "edid.h"
#include "meta-monitor-config.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
/* Look for DPI_FALLBACK in:
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
@@ -69,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
static MetaMonitorTransform
meta_monitor_transform_from_xrandr (Rotation rotation)
static enum wl_output_transform
wl_transform_from_xrandr (Rotation rotation)
{
static const MetaMonitorTransform y_reflected_map[4] = {
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_270
static const enum wl_output_transform y_reflected_map[4] = {
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
MetaMonitorTransform ret;
enum wl_output_transform ret;
switch (rotation & 0x7F)
{
default:
case RR_Rotate_0:
ret = META_MONITOR_TRANSFORM_NORMAL;
ret = WL_OUTPUT_TRANSFORM_NORMAL;
break;
case RR_Rotate_90:
ret = META_MONITOR_TRANSFORM_90;
ret = WL_OUTPUT_TRANSFORM_90;
break;
case RR_Rotate_180:
ret = META_MONITOR_TRANSFORM_180;
ret = WL_OUTPUT_TRANSFORM_180;
break;
case RR_Rotate_270:
ret = META_MONITOR_TRANSFORM_270;
ret = WL_OUTPUT_TRANSFORM_270;
break;
}
@@ -107,42 +105,42 @@ meta_monitor_transform_from_xrandr (Rotation rotation)
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
static MetaMonitorTransform
meta_monitor_transform_from_xrandr_all (Rotation rotation)
static unsigned int
wl_transform_from_xrandr_all (Rotation rotation)
{
unsigned ret;
/* Handle the common cases first (none or all) */
if (rotation == 0 || rotation == RR_Rotate_0)
return (1 << META_MONITOR_TRANSFORM_NORMAL);
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
/* All rotations and one reflection -> all of them by composition */
if ((rotation & ALL_ROTATIONS) &&
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
return ALL_TRANSFORMS;
return ALL_WL_TRANSFORMS;
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (rotation & RR_Rotate_90)
ret |= 1 << META_MONITOR_TRANSFORM_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
if (rotation & RR_Rotate_180)
ret |= 1 << META_MONITOR_TRANSFORM_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
if (rotation & RR_Rotate_270)
ret |= 1 << META_MONITOR_TRANSFORM_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
return ret;
}
static gboolean
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname)
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gboolean value;
Atom atom, actual_type;
@@ -150,9 +148,9 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
unsigned long nitems, bytes_after;
unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format,
@@ -168,13 +166,6 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
return value;
}
static gboolean
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
}
static int
normalize_backlight (MetaOutput *output,
int hw_value)
@@ -195,7 +186,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
@@ -216,34 +207,30 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
Atom atom;
xcb_connection_t *xcb_conn;
xcb_randr_query_output_property_reply_t *reply;
XRRPropertyInfo *info;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
atom);
xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay);
reply = xcb_randr_query_output_property_reply (xcb_conn,
xcb_randr_query_output_property (xcb_conn,
(xcb_randr_output_t) output->winsys_id,
(xcb_atom_t) atom),
NULL);
if (info == NULL)
{
meta_verbose ("could not get output property for %s\n", output->name);
return;
}
/* This can happen on systems without backlights. */
if (reply == NULL)
return;
if (!reply->range || reply->length != 2)
if (!info->range || info->num_values != 2)
{
meta_verbose ("backlight %s was not range\n", output->name);
goto out;
}
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
output->backlight_min = values[0];
output->backlight_max = values[1];
output->backlight_min = info->values[0];
output->backlight_max = info->values[1];
out:
free (reply);
XFree (info);
}
static int
@@ -291,25 +278,25 @@ get_edid_property (Display *dpy,
static GBytes *
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id)
XID output_id)
{
Atom edid_atom;
guint8 *result;
gsize len;
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (result)
@@ -325,26 +312,26 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
XID output_id)
{
return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
}
Atom atom;
XRRPropertyInfo *info;
gboolean result = FALSE;
static char *
get_xmode_name (XRRModeInfo *xmode)
{
int width = xmode->width;
int height = xmode->height;
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
atom);
if (xmode->hSkew != 0)
if (info)
{
width += 2 * (xmode->hSkew >> 8);
height += 2 * (xmode->hSkew & 0xff);
result = TRUE;
XFree (info);
}
return g_strdup_printf ("%dx%d", width, height);
return result;
}
static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{
@@ -430,7 +417,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
mode->height = xmode->height;
mode->refresh_rate = (xmode->dotClock /
((float)xmode->hTotal * xmode->vTotal));
mode->name = get_xmode_name (xmode);
}
for (i = 0; i < (unsigned)resources->ncrtc; i++)
@@ -448,8 +434,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++)
{
@@ -481,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
GBytes *edid;
MonitorInfo *parsed_edid;
meta_output->winsys_id = resources->outputs[i];
meta_output->output_id = resources->outputs[i];
meta_output->name = g_strdup (output->name);
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
edid = read_output_edid (manager_xrandr, meta_output->output_id);
if (edid)
{
gsize len;
@@ -517,7 +503,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -569,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
}
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
@@ -602,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
for (k = 0; k < manager->n_outputs; k++)
{
if (clone == (XID)manager->outputs[k].winsys_id)
if (clone == (XID)manager->outputs[k].output_id)
{
meta_output->possible_clones[j] = &manager->outputs[k];
break;
@@ -618,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
return read_output_edid (manager_xrandr, output->winsys_id);
return read_output_edid (manager_xrandr, output->output_id);
}
static void
@@ -650,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
}
static Rotation
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
wl_transform_to_xrandr (enum wl_output_transform transform)
{
switch (transform)
{
case META_MONITOR_TRANSFORM_NORMAL:
case WL_OUTPUT_TRANSFORM_NORMAL:
return RR_Rotate_0;
case META_MONITOR_TRANSFORM_90:
case WL_OUTPUT_TRANSFORM_90:
return RR_Rotate_90;
case META_MONITOR_TRANSFORM_180:
case WL_OUTPUT_TRANSFORM_180:
return RR_Rotate_180;
case META_MONITOR_TRANSFORM_270:
case WL_OUTPUT_TRANSFORM_270:
return RR_Rotate_270;
case META_MONITOR_TRANSFORM_FLIPPED:
case WL_OUTPUT_TRANSFORM_FLIPPED:
return RR_Reflect_X | RR_Rotate_0;
case META_MONITOR_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return RR_Reflect_X | RR_Rotate_90;
case META_MONITOR_TRANSFORM_FLIPPED_180:
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return RR_Reflect_X | RR_Rotate_180;
case META_MONITOR_TRANSFORM_FLIPPED_270:
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return RR_Reflect_X | RR_Rotate_270;
}
@@ -685,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1);
@@ -841,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->crtc = crtc;
new_controlled_mask |= 1UL << j;
outputs[j] = output->winsys_id;
outputs[j] = output->output_id;
}
if (crtc->current_mode == mode &&
@@ -860,7 +847,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
manager_xrandr->time,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform),
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
if (ok != Success)
@@ -904,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
{
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->winsys_id);
(XID)output_info->output->output_id);
}
output_set_presentation_xrandr (manager_xrandr,
@@ -947,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);

View File

@@ -22,6 +22,48 @@
#include <clutter/clutter.h>
#include "cogl-utils.h"
/**
* meta_create_color_texture_4ub:
* @red: red component
* @green: green component
* @blue: blue component
* @alpha: alpha component
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE;
* %COGL_TEXTURE_NO_SLICING is useful if the texture will be
* repeated to create a constant color fill, since hardware
* repeat can't be used for a sliced texture.
*
* Creates a texture that is a single pixel with the specified
* unpremultiplied color components.
*
* Return value: (transfer full): a newly created Cogl texture
*/
CoglTexture *
meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha,
CoglTextureFlags flags)
{
CoglColor color;
guint8 pixel[4];
cogl_color_init_from_4ub (&color, red, green, blue, alpha);
cogl_color_premultiply (&color);
pixel[0] = cogl_color_get_red_byte (&color);
pixel[1] = cogl_color_get_green_byte (&color);
pixel[2] = cogl_color_get_blue_byte (&color);
pixel[3] = cogl_color_get_alpha_byte (&color);
return cogl_texture_new_from_data (1, 1,
flags,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
4, pixel);
}
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
/**

View File

@@ -23,6 +23,11 @@
#include <cogl/cogl.h>
CoglTexture * meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha,
CoglTextureFlags flags);
CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture);
#endif /* __META_COGL_UTILS_H__ */

View File

@@ -38,8 +38,6 @@ struct _MetaCompositor
gint switch_workspace_in_progress;
MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
};
/* Wait 2ms after vblank before starting to draw next frame */

View File

@@ -67,29 +67,40 @@
#include <meta/compositor-mutter.h>
#include <meta/prefs.h>
#include <meta/main.h>
#include <meta/meta-backend.h>
#include <meta/meta-background-actor.h>
#include <meta/meta-background-group.h>
#include <meta/meta-shadow-factory.h>
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-stage.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h"
#include "frame.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland-private.h"
#endif
static gboolean
is_modal (MetaDisplay *display)
{
return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB;
return display->grab_op == META_GRAB_OP_COMPOSITOR;
}
static inline gboolean
composite_at_least_version (MetaDisplay *display, int maj, int min)
{
static int major = -1;
static int minor = -1;
if (major == -1)
meta_display_get_compositor_version (display, &major, &minor);
return (major > maj || (major == maj && minor >= min));
}
static void sync_actor_stacking (MetaCompositor *compositor);
@@ -135,8 +146,33 @@ process_damage (MetaCompositor *compositor,
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_process_x11_damage (window_actor, event);
}
compositor->frame_has_updated_xsurfaces = TRUE;
static Window
get_output_window (MetaCompositor *compositor)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
Window output;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
meta_core_add_old_event_mask (xdisplay, output, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, output, &mask, 1);
return output;
}
/* compat helper */
@@ -345,7 +381,6 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
display->grab_window = NULL;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
@@ -355,10 +390,7 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
display->grab_window, display->grab_op);
if (meta_is_wayland_compositor ())
{
meta_display_sync_wayland_input_focus (display);
meta_display_cancel_touch (display);
}
meta_display_sync_wayland_input_focus (display);
return TRUE;
}
@@ -378,7 +410,6 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
display->grab_window, display->grab_op);
display->grab_op = META_GRAB_OP_NONE;
display->event_route = META_EVENT_ROUTE_NORMAL;
display->grab_window = NULL;
display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE;
@@ -400,10 +431,8 @@ after_stage_paint (ClutterStage *stage,
for (l = compositor->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
#endif
}
static void
@@ -455,24 +484,62 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaDisplay *display = compositor->display;
Display *xdisplay = display->xdisplay;
MetaScreen *screen = display->screen;
Window xwin = 0;
gint width, height;
meta_screen_set_cm_selection (display->screen);
{
MetaBackend *backend = meta_get_backend ();
compositor->stage = meta_backend_get_stage (backend);
}
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
* and calls glFinish(). The timing information from that will be
* more accurate if we hold off until that completes before we signal
* apps to begin drawing the next frame. If there are no other
* connections to ::after-paint, connect() vs. connect_after() doesn't
* matter.
*/
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
G_CALLBACK (after_stage_paint), compositor);
compositor->stage = meta_stage_new ();
clutter_actor_show (compositor->stage);
wayland_compositor->stage = compositor->stage;
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (compositor->stage, width, height);
}
else
{
compositor->stage = clutter_stage_new ();
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (compositor->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
}
}
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
after_stage_paint,
compositor,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
@@ -491,12 +558,7 @@ meta_compositor_manage (MetaCompositor *compositor)
}
else
{
Window xwin;
compositor->output = screen->composite_overlay_window;
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
compositor->output = get_output_window (compositor);
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen);
@@ -701,6 +763,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
@@ -988,6 +1053,43 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
}
void
meta_compositor_sync_screen_size (MetaCompositor *compositor,
guint width,
guint height)
{
MetaDisplay *display = compositor->display;
if (meta_is_wayland_compositor ())
{
/* FIXME: when we support a sliced stage, this is the place to do it
But! This is not the place to apply KMS config, here we only
notify Clutter/Cogl/GL that the framebuffer sizes changed.
And because for now clutter does not do sliced, we use one
framebuffer the size of the whole screen, and when running on
bare metal MetaMonitorManager will do the necessary tricks to
show the right portions on the right screens.
*/
clutter_actor_set_size (compositor->stage, width, height);
}
else
{
Display *xdisplay;
Window xwin;
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
}
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (display->screen),
width, height);
}
static void
frame_callback (CoglOnscreen *onscreen,
CoglFrameEvent event,
@@ -1058,33 +1160,6 @@ pre_paint_windows (MetaCompositor *compositor)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
if (compositor->frame_has_updated_xsurfaces)
{
/* We need to make sure that any X drawing that happens before
* the XDamageSubtract() for each window above is visible to
* subsequent GL rendering; the only standardized way to do this
* is EXT_x11_sync_object, which isn't yet widely available. For
* now, we count on details of Xorg and the open source drivers,
* and hope for the best otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use
* DamageReportBoundingBox there may be drawing between the last
* damage event and the XDamageSubtract() that needs to be
* flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any
* round trip request at this point is sufficient to flush the
* GLX buffers.
*/
XSync (compositor->display->xdisplay, False);
compositor->frame_has_updated_xsurfaces = FALSE;
}
}
static gboolean
@@ -1115,7 +1190,11 @@ meta_compositor_new (MetaDisplay *display)
{
MetaCompositor *compositor;
if (!composite_at_least_version (display, 0, 3))
return NULL;
compositor = g_new0 (MetaCompositor, 1);
compositor->display = display;
if (g_getenv("META_DISABLE_MIPMAPS"))

View File

@@ -185,7 +185,7 @@ cullable_iface_init (MetaCullableInterface *iface)
* meta_background_actor_get_clip_region:
* @self: a #MetaBackgroundActor
*
* Return value (transfer none): a #cairo_region_t that represents the part of
* Return value (transfer full): a #cairo_region_t that represents the part of
* the background not obscured by other #MetaBackgroundActor or
* #MetaWindowActor objects.
*/
@@ -193,5 +193,24 @@ cairo_region_t *
meta_background_actor_get_clip_region (MetaBackgroundActor *self)
{
MetaBackgroundActorPrivate *priv = self->priv;
return priv->clip_region;
ClutterActorBox content_box;
cairo_rectangle_int_t content_area = { 0 };
cairo_region_t *clip_region;
g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
if (!priv->clip_region)
return NULL;
clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
content_area.x = content_box.x1;
content_area.y = content_box.y1;
content_area.width = content_box.x2 - content_box.x1;
content_area.height = content_box.y2 - content_box.y1;
clip_region = cairo_region_create_rectangle (&content_area);
cairo_region_intersect (clip_region, priv->clip_region);
return clip_region;
}

View File

@@ -288,26 +288,6 @@ get_wrap_mode (MetaBackground *self)
}
}
static gboolean
texture_has_alpha (CoglTexture *texture)
{
if (!texture)
return FALSE;
switch (cogl_texture_get_components (texture))
{
case COGL_TEXTURE_COMPONENTS_A:
case COGL_TEXTURE_COMPONENTS_RGBA:
return TRUE;
case COGL_TEXTURE_COMPONENTS_RG:
case COGL_TEXTURE_COMPONENTS_RGB:
case COGL_TEXTURE_COMPONENTS_DEPTH:
return FALSE;
default:
g_assert_not_reached ();
}
}
static ClutterPaintNode *
meta_background_paint_node_new (MetaBackground *self,
ClutterActor *actor)
@@ -316,7 +296,6 @@ meta_background_paint_node_new (MetaBackground *self,
ClutterPaintNode *node;
guint8 opacity;
guint8 color_component;
gboolean needs_blending;
opacity = clutter_actor_get_paint_opacity (actor);
color_component = (guint8) (0.5 + opacity * priv->brightness);
@@ -329,13 +308,6 @@ meta_background_paint_node_new (MetaBackground *self,
node = clutter_pipeline_node_new (priv->pipeline);
needs_blending = (opacity < 255) || (texture_has_alpha (priv->texture));
if (needs_blending)
cogl_pipeline_set_blend (priv->pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))", NULL);
else
cogl_pipeline_set_blend (priv->pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL);
return node;
}
@@ -410,6 +382,8 @@ meta_background_paint_content (ClutterContent *content,
if (priv->texture == NULL)
return;
node = meta_background_paint_node_new (self, actor);
clutter_actor_get_content_box (actor, &actor_box);
/* First figure out where on the monitor the texture is supposed to be painted.
@@ -439,14 +413,12 @@ meta_background_paint_content (ClutterContent *content,
clip_region = meta_background_actor_get_clip_region (META_BACKGROUND_ACTOR (actor));
if (clip_region != NULL)
cairo_region_intersect (paintable_region, clip_region);
{
cairo_region_intersect (paintable_region, clip_region);
cairo_region_destroy (clip_region);
}
}
if (cairo_region_is_empty (paintable_region))
goto out;
node = meta_background_paint_node_new (self, actor);
/* Finally, split the paintable region up into distinct areas
* and paint each area one by one
*/
@@ -469,11 +441,10 @@ meta_background_paint_content (ClutterContent *content,
clutter_paint_node_add_texture_rectangle (node, &texture_rectangle, tx1, ty1, tx2, ty2);
}
cairo_region_destroy (paintable_region);
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
out:
cairo_region_destroy (paintable_region);
}
static void
@@ -527,8 +498,7 @@ set_brightness (MetaBackground *self,
priv->brightness = brightness;
if (clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL) &&
priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
if (priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
{
ensure_pipeline (self);
cogl_pipeline_set_uniform_1f (priv->pipeline,
@@ -536,14 +506,6 @@ set_brightness (MetaBackground *self,
"brightness"),
priv->brightness);
}
else
{
ensure_pipeline (self);
CoglColor blend_color;
cogl_color_init_from_4f (&blend_color, brightness, brightness, brightness, 1.0);
cogl_pipeline_set_layer_combine (priv->pipeline, 1, "RGB=MODULATE(PREVIOUS, CONSTANT) A=REPLACE(PREVIOUS)", NULL);
cogl_pipeline_set_layer_combine_constant (priv->pipeline, 1, &blend_color);
}
clutter_content_invalidate (CLUTTER_CONTENT (self));
@@ -561,9 +523,6 @@ set_vignette_sharpness (MetaBackground *self,
priv->vignette_sharpness = sharpness;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
return;
if (priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
{
ensure_pipeline (self);
@@ -584,9 +543,6 @@ add_vignette (MetaBackground *self)
MetaBackgroundPrivate *priv = self->priv;
static CoglSnippet *snippet = NULL;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
return;
ensure_pipeline (self);
/* Cogl automatically caches pipelines with no eviction policy,
@@ -814,8 +770,6 @@ meta_background_load_gradient (MetaBackground *self,
ClutterColor *color,
ClutterColor *second_color)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
MetaBackgroundPrivate *priv = self->priv;
CoglTexture *texture;
guint width, height;
@@ -845,17 +799,18 @@ meta_background_load_gradient (MetaBackground *self,
pixels[0] = color->red;
pixels[1] = color->green;
pixels[2] = color->blue;
pixels[3] = 0xFF;
pixels[3] = color->alpha;
pixels[4] = second_color->red;
pixels[5] = second_color->green;
pixels[6] = second_color->blue;
pixels[7] = 0xFF;
pixels[7] = second_color->alpha;
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
COGL_PIXEL_FORMAT_RGB_888,
4,
pixels,
NULL));
texture = cogl_texture_new_from_data (width, height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888,
COGL_PIXEL_FORMAT_ANY,
4,
pixels);
set_texture (self, COGL_TEXTURE (texture));
}
@@ -873,13 +828,10 @@ void
meta_background_load_color (MetaBackground *self,
ClutterColor *color)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
MetaBackgroundPrivate *priv = self->priv;
CoglTexture *texture;
ClutterActor *stage = meta_get_stage_for_screen (priv->screen);
ClutterColor stage_color;
uint8_t pixels[4];
ensure_pipeline (self);
@@ -892,16 +844,11 @@ meta_background_load_color (MetaBackground *self,
color = &stage_color;
}
pixels[0] = color->red;
pixels[1] = color->green;
pixels[2] = color->blue;
pixels[3] = 0xFF;
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, 1, 1,
COGL_PIXEL_FORMAT_RGB_888,
4,
pixels,
NULL));
texture = meta_create_color_texture_4ub (color->red,
color->green,
color->blue,
0xff,
COGL_TEXTURE_NO_SLICING);
set_texture (self, COGL_TEXTURE (texture));
}
@@ -999,8 +946,6 @@ meta_background_load_file_finish (MetaBackground *self,
GAsyncResult *result,
GError **error)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
GTask *task;
LoadFileTaskData *task_data;
CoglTexture *texture;
@@ -1009,7 +954,6 @@ meta_background_load_file_finish (MetaBackground *self,
guchar *pixels;
gboolean has_alpha;
gboolean loaded = FALSE;
CoglPixelFormat pixel_format;
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
@@ -1028,13 +972,15 @@ meta_background_load_file_finish (MetaBackground *self,
pixels = gdk_pixbuf_get_pixels (pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
pixel_format = has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888;
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
pixel_format,
row_stride,
pixels,
NULL));
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NO_ATLAS,
has_alpha ?
COGL_PIXEL_FORMAT_RGBA_8888 :
COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
row_stride,
pixels);
if (texture == NULL)
{

View File

@@ -170,15 +170,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
klass->minimize (plugin, actor);
}
break;
case META_PLUGIN_UNMINIMIZE:
if (klass->unminimize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->unminimize (plugin, actor);
}
break;
case META_PLUGIN_MAP:
if (klass->map)
{

View File

@@ -35,7 +35,6 @@
#define META_PLUGIN_MAP (1<<3)
#define META_PLUGIN_DESTROY (1<<4)
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
#define META_PLUGIN_UNMINIMIZE (1<<6)
#define META_PLUGIN_ALL_EFFECTS (~0)

View File

@@ -110,13 +110,6 @@ meta_plugin_minimize_completed (MetaPlugin *plugin,
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
}
void
meta_plugin_unminimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMINIMIZE);
}
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)

View File

@@ -541,7 +541,7 @@ blur_xspan (guchar *row,
* be well predicted and there are enough different possibilities
* that trying to write this as a series of unconditional loops
* is hard and not an obvious win. The main slow down here seems
* to be the integer division per pixel; one possible optimization
* to be the integer division for pixel; one possible optimization
* would be to accumulate into two 16-bit integer buffers and
* only divide down after all three passes. (SSE parallel implementation
* of the divide step is possible.)
@@ -549,27 +549,27 @@ blur_xspan (guchar *row,
for (i = x0 - d + offset; i < x1 + offset; i++)
{
if (i >= 0 && i < row_width)
sum += row[i];
sum += row[i];
if (i >= x0 + offset)
{
if (i >= d)
sum -= row[i - d];
{
if (i >= d)
sum -= row[i - d];
tmp_buffer[i - offset] = (sum + d / 2) / d;
}
tmp_buffer[i - offset] = (sum + d / 2) / d;
}
}
memcpy (row + x0, tmp_buffer + x0, x1 - x0);
memcpy(row + x0, tmp_buffer + x0, x1 - x0);
}
static void
blur_rows (cairo_region_t *convolve_region,
int x_offset,
int y_offset,
guchar *buffer,
int buffer_width,
int buffer_height,
guchar *buffer,
int buffer_width,
int buffer_height,
int d)
{
int i, j;
@@ -586,30 +586,30 @@ blur_rows (cairo_region_t *convolve_region,
cairo_region_get_rectangle (convolve_region, i, &rect);
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
{
guchar *row = buffer + j * buffer_width;
int x0 = x_offset + rect.x;
int x1 = x0 + rect.width;
{
guchar *row = buffer + j * buffer_width;
int x0 = x_offset + rect.x;
int x1 = x0 + rect.width;
/* We want to produce a symmetric blur that spreads a pixel
* equally far to the left and right. If d is odd that happens
* naturally, but for d even, we approximate by using a blur
* on either side and then a centered blur of size d + 1.
* (technique also from the SVG specification)
* (techique also from the SVG specification)
*/
if (d % 2 == 1)
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
}
else
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0);
}
}
if (d % 2 == 1)
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
}
else
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0);
}
}
}
g_free (tmp_buffer);
@@ -634,7 +634,7 @@ fade_bytes (guchar *bytes,
*/
static guchar *
flip_buffer (guchar *buffer,
int width,
int width,
int height)
{
/* Working in blocks increases cache efficiency, compared to reading
@@ -646,33 +646,33 @@ flip_buffer (guchar *buffer,
int i0, j0;
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE)
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE)
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
if (i0 == j0)
{
for (j = j0; j < max_j; j++)
for (i = i0; i < j; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
else
{
for (j = j0; j < max_j; j++)
for (i = i0; i < max_i; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
}
if (i0 == j0)
{
for (j = j0; j < max_j; j++)
for (i = i0; i < j; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
else
{
for (j = j0; j < max_j; j++)
for (i = i0; i < max_i; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
}
return buffer;
}
@@ -683,15 +683,15 @@ flip_buffer (guchar *buffer,
for (i0 = 0; i0 < width; i0 += BLOCK_SIZE)
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
for (i = i0; i < max_i; i++)
for (j = j0; j < max_j; j++)
new_buffer[i * height + j] = buffer[j * width + i];
}
new_buffer[i * height + j] = buffer[j * width + i];
}
g_free (buffer);
@@ -704,8 +704,6 @@ static void
make_shadow (MetaShadow *shadow,
cairo_region_t *region)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
int d = get_box_filter_size (shadow->key.radius);
int spread = get_shadow_spread (shadow->key.radius);
cairo_rectangle_int_t extents;
@@ -765,7 +763,7 @@ make_shadow (MetaShadow *shadow,
cairo_region_get_rectangle (region, k, &rect);
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width);
memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width);
}
/* Step 2: swap rows and columns */
@@ -795,15 +793,15 @@ make_shadow (MetaShadow *shadow,
* in the case of top_fade >= 0. We also account for padding at the left for symmetry
* though that doesn't currently occur.
*/
shadow->texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx,
shadow->outer_border_left + extents.width + shadow->outer_border_right,
shadow->outer_border_top + extents.height + shadow->outer_border_bottom,
COGL_PIXEL_FORMAT_A_8,
buffer_width,
(buffer +
(y_offset - shadow->outer_border_top) * buffer_width +
(x_offset - shadow->outer_border_left)),
NULL));
shadow->texture = cogl_texture_new_from_data (shadow->outer_border_left + extents.width + shadow->outer_border_right,
shadow->outer_border_top + extents.height + shadow->outer_border_bottom,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
buffer_width,
(buffer +
(y_offset - shadow->outer_border_top) * buffer_width +
(x_offset - shadow->outer_border_left)));
cairo_region_destroy (row_convolve_region);
cairo_region_destroy (column_convolve_region);

View File

@@ -32,6 +32,8 @@
ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
CoglTexture *texture);
gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *stex,
cairo_rectangle_int_t *unobscured_bounds);
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
#endif

View File

@@ -28,14 +28,16 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include "meta-shaped-texture-private.h"
#include <cogl/cogl.h>
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
#include <meta/util.h>
#include "clutter-utils.h"
#include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h"
#include "meta-window-actor-private.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
#include "meta-cullable.h"
static void meta_shaped_texture_dispose (GObject *object);
@@ -63,14 +65,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_AC
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
MetaShapedTexturePrivate))
enum {
SIZE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
@@ -103,13 +97,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
actor_class->paint = meta_shaped_texture_paint;
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
}
@@ -262,20 +249,22 @@ set_cogl_texture (MetaShapedTexture *stex,
cogl_object_ref (cogl_tex);
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
if (width != priv->tex_width ||
height != priv->tex_height)
{
priv->tex_width = width;
priv->tex_height = height;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
}
else
{
width = 0;
height = 0;
}
if (priv->tex_width != width ||
priv->tex_height != height)
{
priv->tex_width = width;
priv->tex_height = height;
/* size changed to 0 going to an invalid handle */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
g_signal_emit (stex, signals[SIZE_CHANGED], 0);
}
/* NB: We don't queue a redraw of the actor here because we don't
@@ -296,8 +285,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
guchar opacity;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglPipeline *pipeline = NULL;
CoglTexture *paint_tex;
ClutterActorBox alloc;
cairo_region_t *blended_region = NULL;
CoglPipelineFilter filter;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
@@ -335,8 +326,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
/* Use nearest-pixel interpolation if the texture is unscaled. This
* improves performance, especially with software rendering.
*/
@@ -352,45 +341,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_allocation_box (actor, &alloc);
cairo_region_t *blended_region;
gboolean use_opaque_region = (priv->opaque_region != NULL && opacity == 255);
if (use_opaque_region)
{
if (priv->clip_region != NULL)
blended_region = cairo_region_copy (priv->clip_region);
else
blended_region = cairo_region_create_rectangle (&tex_rect);
cairo_region_subtract (blended_region, priv->opaque_region);
}
else
{
if (priv->clip_region != NULL)
blended_region = cairo_region_reference (priv->clip_region);
else
blended_region = NULL;
}
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
#define MAX_RECTS 16
if (blended_region != NULL)
{
int n_rects = cairo_region_num_rectangles (blended_region);
if (n_rects > MAX_RECTS)
{
/* Fall back to taking the fully blended path. */
use_opaque_region = FALSE;
cairo_region_destroy (blended_region);
blended_region = NULL;
}
}
/* First, paint the unblended parts, which are part of the opaque region. */
if (use_opaque_region)
if (priv->opaque_region != NULL && opacity == 255)
{
CoglPipeline *opaque_pipeline;
cairo_region_t *region;
@@ -407,87 +358,103 @@ meta_shaped_texture_paint (ClutterActor *actor)
region = cairo_region_reference (priv->opaque_region);
}
if (!cairo_region_is_empty (region))
if (cairo_region_is_empty (region))
goto paint_blended;
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
{
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
}
cogl_object_unref (opaque_pipeline);
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
}
cogl_object_unref (opaque_pipeline);
if (priv->clip_region != NULL)
{
blended_region = cairo_region_copy (priv->clip_region);
}
else
{
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
blended_region = cairo_region_create_rectangle (&rect);
}
cairo_region_subtract (blended_region, priv->opaque_region);
paint_blended:
cairo_region_destroy (region);
}
/* Now, go ahead and paint the blended parts. */
if (blended_region == NULL && priv->clip_region != NULL)
blended_region = cairo_region_reference (priv->clip_region);
/* We have three cases:
* 1) blended_region has rectangles - paint the rectangles.
* 2) blended_region is empty - don't paint anything
* 3) blended_region is NULL - paint fully-blended.
*
* 1) and 3) are the times where we have to paint stuff. This tests
* for 1) and 3).
*/
if (blended_region == NULL || !cairo_region_is_empty (blended_region))
if (blended_region != NULL && cairo_region_is_empty (blended_region))
goto out;
if (priv->mask_texture == NULL)
{
CoglPipeline *blended_pipeline;
if (priv->mask_texture == NULL)
{
blended_pipeline = get_unmasked_pipeline (ctx);
}
else
{
blended_pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
}
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (blended_pipeline, &color);
if (blended_region != NULL)
{
/* 1) blended_region is not empty. Paint the rectangles. */
int i;
int n_rects = cairo_region_num_rectangles (blended_region);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (blended_region, i, &rect);
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
}
}
else
{
/* 3) blended_region is NULL. Do a full paint. */
cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
cogl_object_unref (blended_pipeline);
pipeline = get_unmasked_pipeline (ctx);
}
else
{
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
}
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
{
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (pipeline, &color);
}
if (blended_region != NULL)
{
int n_rects;
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
# define MAX_RECTS 16
n_rects = cairo_region_num_rectangles (blended_region);
if (n_rects <= MAX_RECTS)
{
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (blended_region, i, &rect);
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
}
goto out;
}
}
cogl_framebuffer_draw_rectangle (fb, pipeline,
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
out:
if (pipeline != NULL)
cogl_object_unref (pipeline);
if (blended_region != NULL)
cairo_region_destroy (blended_region);
}
@@ -505,7 +472,7 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
priv = META_SHAPED_TEXTURE (self)->priv;
if (min_width_p)
*min_width_p = priv->tex_width;
*min_width_p = 0;
if (natural_width_p)
*natural_width_p = priv->tex_width;
@@ -524,70 +491,43 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
priv = META_SHAPED_TEXTURE (self)->priv;
if (min_height_p)
*min_height_p = priv->tex_height;
*min_height_p = 0;
if (natural_height_p)
*natural_height_p = priv->tex_height;
}
static cairo_region_t *
effective_unobscured_region (MetaShapedTexture *self)
{
MetaShapedTexturePrivate *priv = self->priv;
ClutterActor *actor;
/* Fail if we have any mapped clones. */
actor = CLUTTER_ACTOR (self);
do
{
if (clutter_actor_has_mapped_clones (actor))
return NULL;
actor = clutter_actor_get_parent (actor);
}
while (actor != NULL);
return priv->unobscured_region;
}
static gboolean
get_unobscured_bounds (MetaShapedTexture *self,
cairo_rectangle_int_t *unobscured_bounds)
{
cairo_region_t *unobscured_region = effective_unobscured_region (self);
if (unobscured_region)
{
cairo_region_get_extents (unobscured_region, unobscured_bounds);
return TRUE;
}
else
return FALSE;
}
static gboolean
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
MetaShapedTexture *self = META_SHAPED_TEXTURE (actor);
ClutterActorBox box;
cairo_rectangle_int_t unobscured_bounds;
if (!clutter_actor_has_allocation (actor))
if (!clutter_paint_volume_set_from_allocation (volume, actor))
return FALSE;
clutter_actor_get_allocation_box (actor, &box);
if (get_unobscured_bounds (self, &unobscured_bounds))
if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds))
{
box.x1 = MAX (unobscured_bounds.x, box.x1);
box.x2 = MIN (unobscured_bounds.x + unobscured_bounds.width, box.x2);
box.y1 = MAX (unobscured_bounds.y, box.y1);
box.y2 = MIN (unobscured_bounds.y + unobscured_bounds.height, box.y2);
}
box.x2 = MAX (box.x2, box.x1);
box.y2 = MAX (box.y2, box.y1);
ClutterVertex origin;
cairo_rectangle_int_t bounds;
/* I hate ClutterPaintVolume so much... */
clutter_paint_volume_get_origin (volume, &origin);
bounds.x = origin.x;
bounds.y = origin.y;
bounds.width = clutter_paint_volume_get_width (volume);
bounds.height = clutter_paint_volume_get_height (volume);
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
origin.x = bounds.x;
origin.y = bounds.y;
clutter_paint_volume_set_origin (volume, &origin);
clutter_paint_volume_set_width (volume, bounds.width);
clutter_paint_volume_set_height (volume, bounds.height);
}
clutter_paint_volume_union_box (volume, &box);
return TRUE;
}
@@ -633,6 +573,39 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
static cairo_region_t *
effective_unobscured_region (MetaShapedTexture *self)
{
MetaShapedTexturePrivate *priv = self->priv;
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
return NULL;
while (parent && !META_IS_WINDOW_ACTOR (parent))
parent = clutter_actor_get_parent (parent);
if (parent && clutter_actor_has_mapped_clones (parent))
return NULL;
return priv->unobscured_region;
}
gboolean
meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *self,
cairo_rectangle_int_t *unobscured_bounds)
{
cairo_region_t *unobscured_region = effective_unobscured_region (self);
if (unobscured_region)
{
cairo_region_get_extents (unobscured_region, unobscured_bounds);
return TRUE;
}
else
return FALSE;
}
gboolean
meta_shaped_texture_is_obscured (MetaShapedTexture *self)
{

View File

@@ -25,85 +25,35 @@
#include "meta-stage.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include "meta-backend.h"
#include <meta/util.h>
typedef struct {
gboolean enabled;
struct _MetaStagePrivate {
CoglPipeline *pipeline;
CoglTexture *texture;
gboolean should_paint_cursor;
MetaCursorReference *cursor;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
} MetaOverlay;
struct _MetaStagePrivate {
MetaOverlay cursor_overlay;
};
typedef struct _MetaStagePrivate MetaStagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
static void
meta_overlay_init (MetaOverlay *overlay)
update_pipeline (MetaStage *stage)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
overlay->pipeline = cogl_pipeline_new (ctx);
}
static void
meta_overlay_free (MetaOverlay *overlay)
{
if (overlay->pipeline)
cogl_object_unref (overlay->pipeline);
}
static void
meta_overlay_set (MetaOverlay *overlay,
CoglTexture *texture,
MetaRectangle *rect)
{
if (overlay->texture != texture)
if (priv->cursor)
{
overlay->texture = texture;
if (texture)
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
overlay->enabled = TRUE;
}
else
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
overlay->enabled = FALSE;
}
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL);
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
}
overlay->current_rect = *rect;
}
static void
meta_overlay_paint (MetaOverlay *overlay)
{
if (!overlay->enabled)
return;
g_assert (meta_is_wayland_compositor ());
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
overlay->pipeline,
overlay->current_rect.x,
overlay->current_rect.y,
overlay->current_rect.x +
overlay->current_rect.width,
overlay->current_rect.y +
overlay->current_rect.height);
overlay->previous_rect = overlay->current_rect;
overlay->previous_is_valid = TRUE;
else
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL);
}
static void
@@ -112,18 +62,42 @@ meta_stage_finalize (GObject *object)
MetaStage *stage = META_STAGE (object);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_free (&priv->cursor_overlay);
if (priv->pipeline)
cogl_object_unref (priv->pipeline);
}
static void
paint_cursor (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor ());
if (!priv->cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
priv->pipeline,
priv->current_rect.x,
priv->current_rect.y,
priv->current_rect.x +
priv->current_rect.width,
priv->current_rect.y +
priv->current_rect.height);
priv->previous_rect = priv->current_rect;
priv->previous_is_valid = TRUE;
}
static void
meta_stage_paint (ClutterActor *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
meta_overlay_paint (&priv->cursor_overlay);
if (meta_is_wayland_compositor ())
paint_cursor (stage);
}
static void
@@ -140,9 +114,10 @@ meta_stage_class_init (MetaStageClass *klass)
static void
meta_stage_init (MetaStage *stage)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_init (&priv->cursor_overlay);
priv->pipeline = cogl_pipeline_new (ctx);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
}
@@ -156,42 +131,46 @@ meta_stage_new (void)
}
static void
queue_redraw_for_overlay (MetaStage *stage,
MetaOverlay *overlay)
queue_redraw (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
cairo_rectangle_int_t clip;
/* Clear the location the overlay was at before, if we need to. */
if (overlay->previous_is_valid)
/* Clear the location the cursor was at before, if we need to. */
if (priv->previous_is_valid)
{
clip.x = overlay->previous_rect.x;
clip.y = overlay->previous_rect.y;
clip.width = overlay->previous_rect.width;
clip.height = overlay->previous_rect.height;
clip.x = priv->previous_rect.x;
clip.y = priv->previous_rect.y;
clip.width = priv->previous_rect.width;
clip.height = priv->previous_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
overlay->previous_is_valid = FALSE;
priv->previous_is_valid = FALSE;
}
/* Draw the overlay at the new position */
if (overlay->enabled)
/* And queue a redraw for the current cursor location. */
if (priv->cursor)
{
clip.x = overlay->current_rect.x;
clip.y = overlay->current_rect.y;
clip.width = overlay->current_rect.width;
clip.height = overlay->current_rect.height;
clip.x = priv->current_rect.x;
clip.y = priv->current_rect.y;
clip.width = priv->current_rect.width;
clip.height = priv->current_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
}
}
void
meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect)
meta_stage_set_cursor (MetaStage *stage,
MetaCursorReference *cursor,
MetaRectangle *rect)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor () || texture == NULL);
if (priv->cursor != cursor)
{
priv->cursor = cursor;
update_pipeline (stage);
}
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
priv->current_rect = *rect;
queue_redraw (stage);
}

View File

@@ -51,9 +51,9 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
ClutterActor *meta_stage_new (void);
void meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect);
void meta_stage_set_cursor (MetaStage *stage,
MetaCursorReference *cursor,
MetaRectangle *rect);
G_END_DECLS
#endif /* META_STAGE_H */

View File

@@ -34,15 +34,45 @@
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
struct wl_listener buffer_destroy_listener;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data)
{
MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener);
/* If the buffer is destroyed while we're attached to it,
* we want to unset priv->buffer so we don't access freed
* memory. Keep the texture set however so the user doesn't
* see the window disappear. */
priv->buffer = NULL;
}
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
if (priv->buffer)
{
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
}
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
}
static void
@@ -79,7 +109,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
}
static int
get_output_scale (int winsys_id)
get_output_scale (int output_id)
{
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
MetaOutput *outputs;
@@ -90,7 +120,7 @@ get_output_scale (int winsys_id)
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == winsys_id)
if (outputs[i].output_id == output_id)
{
output_scale = outputs[i].scale;
break;
@@ -120,7 +150,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
output_scale = get_output_scale (window->monitor->winsys_id);
output_scale = get_output_scale (window->monitor->output_id);
return (double)output_scale / (double)priv->surface->scale;
}
@@ -183,7 +213,7 @@ meta_surface_actor_wayland_dispose (GObject *object)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
meta_surface_actor_wayland_set_texture (self, NULL);
meta_surface_actor_wayland_set_buffer (self, NULL);
G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
}
@@ -214,6 +244,9 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
static void
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy;
}
MetaSurfaceActor *
@@ -230,11 +263,24 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
}
void
meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
CoglTexture *texture)
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
meta_shaped_texture_set_texture (stex, texture);
if (priv->buffer)
wl_list_remove (&priv->buffer_destroy_listener.link);
priv->buffer = buffer;
if (priv->buffer)
{
wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener);
meta_shaped_texture_set_texture (stex, priv->buffer->texture);
}
else
meta_shaped_texture_set_texture (stex, NULL);
}
MetaWaylandSurface *

View File

@@ -58,8 +58,8 @@ GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
CoglTexture *texture);
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer);
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);

View File

@@ -179,6 +179,19 @@ is_visible (MetaSurfaceActorX11 *self)
return (priv->pixmap != None) && !priv->unredirected;
}
static void
damage_area (MetaSurfaceActorX11 *self,
int x, int y, int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
@@ -205,10 +218,11 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
priv->does_full_damage = TRUE;
}
if (!is_visible (self))
/* Drop damage event for unredirected windows */
if (priv->unredirected)
return;
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
damage_area (self, x, y, width, height);
}
static void
@@ -225,6 +239,26 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display);
/* We need to make sure that any X drawing that happens before the
* XDamageSubtract() above is visible to subsequent GL rendering;
* the only standardized way to do this is EXT_x11_sync_object,
* which isn't yet widely available. For now, we count on details
* of Xorg and the open source drivers, and hope for the best
* otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use DamageReportBoundingBox
* there may be drawing between the last damage event and the
* XDamageSubtract() that needs to be flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any round trip
* request at this point is sufficient to flush the GLX buffers.
*/
XSync (xdisplay, False);
priv->received_damage = FALSE;
}

View File

@@ -36,13 +36,20 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_
enum {
REPAINT_SCHEDULED,
SIZE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
gboolean
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
cairo_rectangle_int_t *unobscured_bounds)
{
MetaSurfaceActorPrivate *priv = self->priv;
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
}
static void
meta_surface_actor_pick (ClutterActor *actor,
const ClutterColor *color)
@@ -121,13 +128,6 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
}
@@ -152,14 +152,6 @@ cullable_iface_init (MetaCullableInterface *iface)
iface->reset_culling = meta_surface_actor_reset_culling;
}
static void
texture_size_changed (MetaShapedTexture *texture,
gpointer user_data)
{
MetaSurfaceActor *actor = META_SURFACE_ACTOR (user_data);
g_signal_emit (actor, signals[SIZE_CHANGED], 0);
}
static void
meta_surface_actor_init (MetaSurfaceActor *self)
{
@@ -170,8 +162,6 @@ meta_surface_actor_init (MetaSurfaceActor *self)
MetaSurfaceActorPrivate);
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
g_signal_connect_object (priv->texture, "size-changed",
G_CALLBACK (texture_size_changed), self, 0);
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
}
@@ -188,7 +178,7 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
return self->priv->texture;
}
static void
void
meta_surface_actor_update_area (MetaSurfaceActor *self,
int x, int y, int width, int height)
{
@@ -262,9 +252,6 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
}
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
if (meta_surface_actor_is_visible (self))
meta_surface_actor_update_area (self, x, y, width, height);
}
void
@@ -280,15 +267,9 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
/* If we don't have a texture, like during initialization, assume
* that we're ARGB32.
*
* If we are unredirected and we have no texture assume that we are
* not ARGB32 otherwise we wouldn't be unredirected in the first
* place. This prevents us from continually redirecting and
* unredirecting on every paint.
*/
* that we're ARGB32. */
if (!texture)
return !meta_surface_actor_is_unredirected (self);
return TRUE;
switch (cogl_texture_get_components (texture))
{

View File

@@ -55,12 +55,17 @@ MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
cairo_rectangle_int_t *unobscured_bounds);
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region);
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
cairo_region_t *region);
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);

View File

@@ -378,8 +378,8 @@ texture_tower_create_texture (MetaTextureTower *tower,
}
static void
texture_tower_revalidate (MetaTextureTower *tower,
int level)
texture_tower_revalidate_fbo (MetaTextureTower *tower,
int level)
{
CoglTexture *source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
@@ -425,9 +425,13 @@ texture_tower_revalidate (MetaTextureTower *tower,
(2. * invalid->y2) / source_texture_height);
cogl_object_unref (pipeline);
}
tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
static void
texture_tower_revalidate (MetaTextureTower *tower,
int level)
{
texture_tower_revalidate_fbo (tower, level);
}
/**

View File

@@ -32,17 +32,9 @@
#include "meta-surface-actor.h"
#include "meta-surface-actor-x11.h"
#ifdef HAVE_WAYLAND
#include "meta-surface-actor-wayland.h"
#include "wayland/meta-wayland-surface.h"
#endif
typedef enum {
INITIALLY_FROZEN,
DRAWING_FIRST_FRAME,
EMITTED_FIRST_FRAME
} FirstFrameState;
#include "wayland/meta-wayland-surface.h"
struct _MetaWindowActorPrivate
{
@@ -78,7 +70,7 @@ struct _MetaWindowActorPrivate
gint64 frame_drawn_time;
guint repaint_scheduled_id;
guint size_changed_id;
guint allocation_changed_id;
/*
* These need to be counters rather than flags, since more plugins
@@ -86,7 +78,6 @@ struct _MetaWindowActorPrivate
* might be dubious, but we have to at least handle it correctly.
*/
gint minimize_in_progress;
gint unminimize_in_progress;
gint maximize_in_progress;
gint unmaximize_in_progress;
gint map_in_progress;
@@ -113,7 +104,6 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
guint updates_frozen : 1;
guint first_frame_state : 2; /* FirstFrameState */
};
typedef struct _FrameData FrameData;
@@ -125,14 +115,6 @@ struct _FrameData
gint64 frame_drawn_time;
};
enum
{
FIRST_FRAME,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
enum
{
PROP_META_WINDOW = 1,
@@ -199,31 +181,6 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
actor_class->paint = meta_window_actor_paint;
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
/**
* MetaWindowActor::first-frame:
* @actor: the #MetaWindowActor instance
*
* The ::first-frame signal will be emitted the first time a frame
* of window contents has been drawn by the application and Mutter
* has had the chance to drawn that frame to the screen. If the
* window starts off initially hidden, obscured, or on on a
* different workspace, the ::first-frame signal will be emitted
* even though the user doesn't see the contents.
*
* MetaDisplay::window-created is a good place to connect to this
* signal - at that point, the MetaWindowActor for the window
* exists, but the window has reliably not yet been drawn.
* Connecting to an existing window that has already been drawn to
* the screen is not useful.
*/
signals[FIRST_FRAME] =
g_signal_new ("first-frame",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
pspec = g_param_spec_object ("meta-window",
"MetaWindow",
"The displayed MetaWindow",
@@ -275,11 +232,12 @@ window_appears_focused_notify (MetaWindow *mw,
}
static void
surface_size_changed (MetaSurfaceActor *actor,
gpointer user_data)
surface_allocation_changed_notify (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
MetaWindowActor *self)
{
MetaWindowActor *self = META_WINDOW_ACTOR (user_data);
meta_window_actor_sync_actor_geometry (self, FALSE);
meta_window_actor_update_shape (self);
}
@@ -348,9 +306,6 @@ meta_window_actor_thaw (MetaWindowActor *self)
if (priv->freeze_count > 0)
return;
if (priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
if (priv->surface)
meta_surface_actor_set_frozen (priv->surface, FALSE);
@@ -371,8 +326,9 @@ set_surface (MetaWindowActor *self,
if (priv->surface)
{
g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id);
g_signal_handler_disconnect (priv->surface, priv->size_changed_id);
priv->repaint_scheduled_id = 0;
g_signal_handler_disconnect (priv->surface, priv->allocation_changed_id);
priv->allocation_changed_id = 0;
clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
g_object_unref (priv->surface);
}
@@ -384,17 +340,14 @@ set_surface (MetaWindowActor *self,
g_object_ref_sink (priv->surface);
priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
G_CALLBACK (surface_repaint_scheduled), self);
priv->size_changed_id = g_signal_connect (priv->surface, "size-changed",
G_CALLBACK (surface_size_changed), self);
priv->allocation_changed_id = g_signal_connect (priv->surface, "allocation-changed",
G_CALLBACK (surface_allocation_changed_notify), self);
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
/* If the previous surface actor was frozen, start out
* frozen as well... */
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
meta_window_actor_update_shape (self);
}
}
@@ -406,12 +359,9 @@ meta_window_actor_update_surface (MetaWindowActor *self)
MetaWindow *window = priv->window;
MetaSurfaceActor *surface_actor;
#ifdef HAVE_WAYLAND
if (window->surface)
surface_actor = window->surface->surface_actor;
else
#endif
if (!meta_is_wayland_compositor ())
else if (!meta_is_wayland_compositor ())
surface_actor = meta_surface_actor_x11_new (window);
else
surface_actor = NULL;
@@ -601,7 +551,6 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
cairo_region_get_extents (priv->shape_region, bounds);
#ifdef HAVE_WAYLAND
if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
{
double scale = priv->surface ?
@@ -611,7 +560,6 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
bounds->width *= scale;
bounds->height *= scale;
}
#endif
}
static void
@@ -719,16 +667,25 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
{
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
MetaWindowActorPrivate *priv = self->priv;
cairo_rectangle_int_t unobscured_bounds, bounds;
gboolean appears_focused = meta_window_appears_focused (priv->window);
ClutterVertex origin;
/* The paint volume is computed before paint functions are called
* so our bounds might not be updated yet. Force an update. */
meta_window_actor_handle_updates (self);
meta_window_actor_get_shape_bounds (self, &bounds);
if (priv->surface)
{
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
cairo_rectangle_int_t shadow_bounds;
ClutterActorBox shadow_box;
/* We could compute an full clip region as we do for the window
* texture, but the shadow is relatively cheap to draw, and
@@ -738,24 +695,16 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
*/
meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
shadow_box.x1 = shadow_bounds.x;
shadow_box.x2 = shadow_bounds.x + shadow_bounds.width;
shadow_box.y1 = shadow_bounds.y;
shadow_box.y2 = shadow_bounds.y + shadow_bounds.height;
clutter_paint_volume_union_box (volume, &shadow_box);
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
}
if (priv->surface)
{
const ClutterPaintVolume *child_volume;
origin.x = bounds.x;
origin.y = bounds.y;
origin.z = 0.0f;
clutter_paint_volume_set_origin (volume, &origin);
child_volume = clutter_actor_get_transformed_paint_volume (CLUTTER_ACTOR (priv->surface), actor);
if (!child_volume)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
clutter_paint_volume_set_width (volume, bounds.width);
clutter_paint_volume_set_height (volume, bounds.height);
return TRUE;
}
@@ -904,7 +853,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc)
if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
{
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
break;
@@ -1013,9 +962,6 @@ start_simple_effect (MetaWindowActor *self,
case META_PLUGIN_MINIMIZE:
counter = &priv->minimize_in_progress;
break;
case META_PLUGIN_UNMINIMIZE:
counter = &priv->unminimize_in_progress;
break;
case META_PLUGIN_MAP:
counter = &priv->map_in_progress;
break;
@@ -1086,16 +1032,6 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
}
}
break;
case META_PLUGIN_UNMINIMIZE:
{
priv->unminimize_in_progress--;
if (priv->unminimize_in_progress < 0)
{
g_warning ("Error in unminimize accounting.");
priv->unminimize_in_progress = 0;
}
}
break;
case META_PLUGIN_MAP:
/*
* Make sure that the actor is at the correct place in case
@@ -1261,7 +1197,8 @@ meta_window_actor_show (MetaWindowActor *self,
event = META_PLUGIN_MAP;
break;
case META_COMP_EFFECT_UNMINIMIZE:
event = META_PLUGIN_UNMINIMIZE;
/* FIXME: should have META_PLUGIN_UNMINIMIZE */
event = META_PLUGIN_MAP;
break;
case META_COMP_EFFECT_NONE:
break;
@@ -1391,11 +1328,6 @@ meta_window_actor_new (MetaWindow *window)
meta_window_actor_sync_updates_frozen (self);
if (is_frozen (self))
priv->first_frame_state = INITIALLY_FROZEN;
else
priv->first_frame_state = DRAWING_FIRST_FRAME;
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
*/
@@ -1664,8 +1596,6 @@ build_and_scan_frame_mask (MetaWindowActor *self,
cairo_rectangle_int_t *client_area,
cairo_region_t *shape_region)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
MetaWindowActorPrivate *priv = self->priv;
guchar *mask_data;
guint tex_width, tex_height;
@@ -1728,7 +1658,10 @@ build_and_scan_frame_mask (MetaWindowActor *self,
if (meta_texture_rectangle_check (paint_tex))
{
mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, tex_width, tex_height));
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *context = clutter_backend_get_cogl_context (backend);
mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (context, tex_width, tex_height));
cogl_texture_set_components (mask_texture, COGL_TEXTURE_COMPONENTS_A);
cogl_texture_set_region (mask_texture,
0, 0, /* src_x/y */
@@ -1740,9 +1673,15 @@ build_and_scan_frame_mask (MetaWindowActor *self,
}
else
{
mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, tex_width, tex_height,
COGL_PIXEL_FORMAT_A_8,
stride, mask_data, NULL));
/* Note: we don't allow slicing for this texture because we
* need to use it with multi-texturing which doesn't support
* sliced textures */
mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
stride,
mask_data);
}
meta_shaped_texture_set_mask_texture (stex, mask_texture);
@@ -1971,12 +1910,6 @@ meta_window_actor_post_paint (MetaWindowActor *self)
do_send_frame_drawn (self, priv->frames->data);
priv->needs_frame_drawn = FALSE;
}
if (priv->first_frame_state == DRAWING_FIRST_FRAME)
{
priv->first_frame_state = EMITTED_FIRST_FRAME;
g_signal_emit (self, signals[FIRST_FRAME], 0);
}
}
static void

View File

@@ -69,9 +69,12 @@
*
* If the configure script found we had no XKB, this does not exist.
*/
#ifdef HAVE_XKB
static void
bell_flash_fullscreen (MetaDisplay *display)
bell_flash_fullscreen (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
{
g_assert (xkb_ev->xkb_type == XkbBellNotify);
meta_compositor_flash_screen (display->compositor, display->screen);
}
@@ -136,17 +139,30 @@ bell_flash_window_frame (MetaWindow *window)
* @display: The display the bell event came in on
* @xkb_ev: The bell event we just received
*
* Flashes the frame of the focused window. If there is no focused window,
* Flashes the frame of the focussed window. If there is no focussed window,
* flashes the screen.
*/
static void
bell_flash_frame (MetaDisplay *display,
MetaWindow *window)
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))
{
window = display->focus_window;
}
if (window && window->frame)
bell_flash_window_frame (window);
else
bell_flash_fullscreen (display);
{
bell_flash_window_frame (window);
}
else /* revert to fullscreen flash if there's no focussed window */
{
bell_flash_fullscreen (display, xkb_ev);
}
}
/**
@@ -156,73 +172,69 @@ bell_flash_frame (MetaDisplay *display,
*
* Gives the user some kind of visual bell substitute, in response to a
* bell event. What this is depends on the "visual bell type" pref.
*
* If the configure script found we had no XKB, this does not exist.
*/
/*
* Bug: This should be merged with meta_bell_notify().
*/
static void
bell_visual_notify (MetaDisplay *display,
MetaWindow *window)
XkbAnyEvent *xkb_ev)
{
switch (meta_prefs_get_visual_bell_type ())
{
case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH:
bell_flash_fullscreen (display);
bell_flash_fullscreen (display, xkb_ev);
break;
case G_DESKTOP_VISUAL_BELL_FRAME_FLASH:
bell_flash_frame (display, window);
bell_flash_frame (display, xkb_ev); /* does nothing yet */
break;
}
}
static gboolean
bell_audible_notify (MetaDisplay *display,
MetaWindow *window)
{
#ifdef HAVE_LIBCANBERRA
ca_proplist *p;
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");
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);
}
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
ca_proplist_destroy (p);
return res == CA_SUCCESS || res == CA_ERROR_DISABLED;
#endif /* HAVE_LIBCANBERRA */
return FALSE;
}
void
meta_bell_notify (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
{
MetaWindow *window;
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window && display->focus_window && display->focus_window->frame)
window = display->focus_window;
/* flash something */
if (meta_prefs_get_visual_bell ())
bell_visual_notify (display, window);
bell_visual_notify (display, xkb_ev);
#ifdef HAVE_LIBCANBERRA
if (meta_prefs_bell_is_audible ())
{
if (!bell_audible_notify (display, window))
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)
{
/* Force a classic bell if the libcanberra bell failed. */
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,
@@ -230,11 +242,14 @@ meta_bell_notify (MetaDisplay *display,
xkb_bell_event->percent);
}
}
#endif /* HAVE_LIBCANBERRA */
}
#endif /* HAVE_XKB */
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 */
@@ -247,11 +262,13 @@ meta_bell_set_audible (MetaDisplay *display, gboolean audible)
XkbUseCoreKbd,
XkbAudibleBellMask,
enable_system_bell ? XkbAudibleBellMask : 0);
#endif /* HAVE_XKB */
}
gboolean
meta_bell_init (MetaDisplay *display)
{
#ifdef HAVE_XKB
int xkb_base_error_type, xkb_opcode;
if (!XkbQueryExtension (display->xdisplay, &xkb_opcode,
@@ -281,17 +298,20 @@ meta_bell_init (MetaDisplay *display)
}
return TRUE;
}
#endif
return FALSE;
}
void
meta_bell_shutdown (MetaDisplay *display)
{
#ifdef HAVE_XKB
/* TODO: persist initial bell state in display, reset here */
XkbChangeEnabledControls (display->xdisplay,
XkbUseCoreKbd,
XkbAudibleBellMask,
XkbAudibleBellMask);
#endif
}
/**

View File

@@ -18,10 +18,13 @@
*/
#include <X11/Xlib.h>
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#endif
#include "display-private.h"
#include "frame.h"
#ifdef HAVE_XKB
/**
* meta_bell_notify:
* @display: The display the bell event came in on
@@ -34,6 +37,7 @@
* If the configure script found we had no XKB, this does not exist.
*/
void meta_bell_notify (MetaDisplay *display, XkbAnyEvent *xkb_ev);
#endif
/**
* meta_bell_set_audible:
@@ -57,6 +61,12 @@ void meta_bell_set_audible (MetaDisplay *display, gboolean audible);
* to send us bell notifications, and then also switching
* off the audible bell if we're using a visual one ourselves.
*
* Unlike most X extensions we use, we only initialise XKB here
* (rather than in main()). It's possible that XKB is not
* installed at all, but if that was known at build time
* we will have HAVE_XKB undefined, which will cause this
* function to be a no-op.
*
* \bug There is a line of code that's never run that tells
* XKB to reset the bell status after we quit. Bill H said
* (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)

View File

@@ -495,5 +495,46 @@ meta_core_set_screen_cursor (Display *xdisplay,
void
meta_invalidate_default_icons (void)
{
/* XXX: Actually invalidate the icons when they're used. */
MetaDisplay *display = meta_get_display ();
GSList *windows;
GSList *l;
if (display == NULL)
return; /* We can validly be called before the display is opened. */
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
for (l = windows; l != NULL; l = l->next)
{
MetaWindow *window = (MetaWindow*)l->data;
if (window->icon_cache.origin == USING_FALLBACK_ICON)
{
meta_icon_cache_free (&(window->icon_cache));
meta_window_update_icon_now (window);
}
}
g_slist_free (windows);
}
void
meta_core_add_old_event_mask (Display *xdisplay,
Window xwindow,
XIEventMask *mask)
{
XIEventMask *prev;
gint n_masks, i, j;
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
for (i = 0; i < n_masks; i++)
{
if (prev[i].deviceid != XIAllMasterDevices)
continue;
for (j = 0; j < MIN (mask->mask_len, prev[i].mask_len); j++)
mask->mask[j] |= prev[i].mask[j];
}
XFree (prev);
}

View File

@@ -169,4 +169,8 @@ void meta_core_set_screen_cursor (Display *xdisplay,
void meta_invalidate_default_icons (void);
void meta_core_add_old_event_mask (Display *xdisplay,
Window xwindow,
XIEventMask *mask);
#endif

View File

@@ -37,6 +37,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "wayland/meta-wayland-surface.h"
static void
dialog_exited (GPid pid, int status, gpointer user_data)
{

View File

@@ -35,7 +35,7 @@
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "meta-gesture-tracker-private.h"
#include "gesture-tracker-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
@@ -79,24 +79,6 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
typedef enum {
/* Normal interaction where you're interacting with windows.
* Events go to windows normally. */
META_EVENT_ROUTE_NORMAL,
/* In a compositor grab operation. All events go to the
* compositor plugin. */
META_EVENT_ROUTE_COMPOSITOR_GRAB,
/* A Wayland application has a popup open. All events go to
* the Wayland application. */
META_EVENT_ROUTE_WAYLAND_POPUP,
/* In a window operation like moving or resizing. All events
* goes to MetaWindow, but not to the actual client window. */
META_EVENT_ROUTE_WINDOW_OP,
} MetaEventRoute;
struct _MetaDisplay
{
GObject parent_instance;
@@ -164,6 +146,8 @@ struct _MetaDisplay
GHashTable *xids;
GHashTable *wayland_windows;
int server_grab_count;
/* serials of leave/unmap events that may
* correspond to an enter event we should
* ignore
@@ -192,8 +176,8 @@ struct _MetaDisplay
guint autoraise_timeout_id;
MetaWindow* autoraise_window;
/* Event routing */
MetaEventRoute event_route;
/* Alt+click button grabs */
ClutterModifierType window_grab_modifiers;
/* current window operation */
MetaGrabOp grab_op;
@@ -218,17 +202,34 @@ struct _MetaDisplay
GTimeVal grab_last_moveresize_time;
MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap;
guint32 grab_timestamp;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
*/
int sentinel_counter;
#ifdef HAVE_XKB
int xkb_base_event_type;
guint32 last_bell_time;
#endif
int grab_resize_timeout_id;
MetaKeyBindingManager key_binding_manager;
/* Keybindings stuff */
GHashTable *key_bindings;
GHashTable *key_bindings_index;
int min_keycode;
int max_keycode;
KeySym *keymap;
int keysyms_per_keycode;
unsigned int ignored_modifier_mask;
unsigned int hyper_mask;
unsigned int super_mask;
unsigned int meta_mask;
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
MetaKeyCombo *iso_next_group_combos;
int n_iso_next_group_combos;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
@@ -254,7 +255,6 @@ struct _MetaDisplay
MetaCompositor *compositor;
MetaGestureTracker *gesture_tracker;
ClutterEventSequence *pointer_emulating_sequence;
int composite_event_base;
int composite_error_base;
@@ -314,6 +314,8 @@ struct _MetaDisplayClass
gboolean meta_display_open (void);
void meta_display_close (MetaDisplay *display,
guint32 timestamp);
void meta_display_grab (MetaDisplay *display);
void meta_display_ungrab (MetaDisplay *display);
void meta_display_unmanage_windows_for_screen (MetaDisplay *display,
MetaScreen *screen,
@@ -398,8 +400,14 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
gboolean meta_grab_op_is_moving (MetaGrabOp op);
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
gboolean meta_grab_op_should_block_wayland (MetaGrabOp op);
void meta_display_devirtualize_modifiers (MetaDisplay *display,
MetaVirtualModifier modifiers,
unsigned int *mask);
void meta_display_increment_focus_sentinel (MetaDisplay *display);
void meta_display_decrement_focus_sentinel (MetaDisplay *display);
@@ -437,20 +445,6 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
guint32 *timestamp);
void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
MetaWindow *window);
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
gboolean meta_display_show_restart_message (MetaDisplay *display,
const char *message);
gboolean meta_display_request_restart (MetaDisplay *display);
void meta_restart_init (void);
void meta_restart_finish (void);
void meta_display_cancel_touch (MetaDisplay *display);
gboolean meta_display_windows_are_interactable (MetaDisplay *display);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -23,10 +23,10 @@
#include "config.h"
#include "events.h"
#include <meta/meta-backend.h>
#include "core.h"
#include "display-private.h"
#include "window-private.h"
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
@@ -34,45 +34,34 @@
#include "backends/native/meta-idle-monitor-native.h"
#endif
#ifdef HAVE_WAYLAND
#include "backends/meta-cursor-tracker-private.h"
#include "x11/events.h"
#include "wayland/meta-wayland-private.h"
#endif
#include "meta-surface-actor.h"
static MetaWindow *
get_window_for_event (MetaDisplay *display,
const ClutterEvent *event)
{
switch (display->event_route)
ClutterActor *source;
if (display->grab_op != META_GRAB_OP_NONE)
return display->grab_window;
/* Always use the key focused window for key events. */
switch (event->type)
{
case META_EVENT_ROUTE_NORMAL:
{
ClutterActor *source;
/* Always use the key focused window for key events. */
switch (event->type)
{
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
return display->focus_window;
default:
break;
}
source = clutter_event_get_source (event);
if (META_IS_SURFACE_ACTOR (source))
return meta_surface_actor_get_window (META_SURFACE_ACTOR (source));
else
return NULL;
}
case META_EVENT_ROUTE_WAYLAND_POPUP:
case META_EVENT_ROUTE_WINDOW_OP:
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
return display->grab_window;
case CLUTTER_KEY_PRESS:
case CLUTTER_KEY_RELEASE:
return display->focus_window;
default:
g_assert_not_reached ();
break;
}
source = clutter_event_get_source (event);
if (META_IS_SURFACE_ACTOR (source))
return meta_surface_actor_get_window (META_SURFACE_ACTOR (source));
return NULL;
}
static void
@@ -111,90 +100,20 @@ handle_idletime_for_event (const ClutterEvent *event)
#endif /* HAVE_NATIVE_BACKEND */
}
static gboolean
sequence_is_pointer_emulated (MetaDisplay *display,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
if (clutter_event_is_pointer_emulated (event))
return TRUE;
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
/* When using Clutter's native input backend there is no concept of
* pointer emulating sequence, we still must make up our own to be
* able to implement single-touch (hence pointer alike) behavior.
*
* This is implemented similarly to X11, where only the first touch
* on screen gets the "pointer emulated" flag, and it won't get assigned
* to another sequence until the next first touch on an idle touchscreen.
*/
if (META_IS_BACKEND_NATIVE (backend))
{
MetaGestureTracker *tracker;
tracker = meta_display_get_gesture_tracker (display);
if (event->type == CLUTTER_TOUCH_BEGIN &&
meta_gesture_tracker_get_n_current_touches (tracker) == 0)
return TRUE;
}
#endif /* HAVE_NATIVE_BACKEND */
return FALSE;
}
static void
meta_display_update_pointer_emulating_sequence (MetaDisplay *display,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
if (event->type == CLUTTER_TOUCH_BEGIN &&
!display->pointer_emulating_sequence &&
sequence_is_pointer_emulated (display, event))
display->pointer_emulating_sequence = sequence;
else if (event->type == CLUTTER_TOUCH_END &&
display->pointer_emulating_sequence == sequence)
display->pointer_emulating_sequence = NULL;
}
static gboolean
meta_display_handle_event (MetaDisplay *display,
const ClutterEvent *event)
{
MetaWindow *window;
gboolean bypass_clutter = FALSE;
G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
gboolean bypass_clutter = FALSE, bypass_wayland = FALSE;
MetaWaylandCompositor *compositor = NULL;
MetaGestureTracker *tracker;
meta_display_update_pointer_emulating_sequence (display, event);
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor = NULL;
if (meta_is_wayland_compositor ())
{
compositor = meta_wayland_compositor_get_default ();
meta_wayland_compositor_update (compositor, event);
}
#endif
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
{
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
}
#endif
handle_idletime_for_event (event);
@@ -228,11 +147,13 @@ meta_display_handle_event (MetaDisplay *display,
if (meta_gesture_tracker_handle_event (tracker, event))
{
bypass_wayland = bypass_clutter = TRUE;
bypass_wayland = TRUE;
bypass_clutter = meta_gesture_tracker_consumes_event (tracker, event);
goto out;
}
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
if (display->grab_window == window &&
meta_grab_op_is_moving_or_resizing (display->grab_op))
{
if (meta_window_handle_mouse_grab_op_event (window, event))
{
@@ -257,42 +178,29 @@ meta_display_handle_event (MetaDisplay *display,
if (window)
{
if (!clutter_event_get_event_sequence (event))
/* Swallow all events on windows that come our way. */
bypass_clutter = TRUE;
/* Under X11, we have a Sync grab and in order to send it back to
* clients, we have to explicitly replay it.
*
* Under Wayland, we retrieve all events and we have to make sure
* to filter them out from Wayland clients.
*/
if (meta_window_handle_ungrabbed_event (window, event))
{
/* Swallow all non-touch events on windows that come our way.
* Touch events that reach here aren't yet in an accepted state,
* so Clutter must see them to maybe trigger gestures into
* recognition.
*/
bypass_clutter = TRUE;
}
meta_window_handle_ungrabbed_event (window, event);
/* This might start a grab op. If it does, then filter out the
* event, and if it doesn't, replay the event to release our
* own sync grab. */
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
{
bypass_clutter = TRUE;
bypass_wayland = TRUE;
}
else
{
/* Only replay button press events, since that's where we
* have the synchronous grab. */
if (event->type == CLUTTER_BUTTON_PRESS)
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
meta_verbose ("Allowing events time %u\n",
(unsigned int)event->button.time);
XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
XIReplayDevice, event->button.time);
}
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
meta_verbose ("Allowing events time %u\n",
(unsigned int)event->button.time);
XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
XIReplayDevice, event->button.time);
}
}
@@ -301,20 +209,18 @@ meta_display_handle_event (MetaDisplay *display,
out:
/* If the compositor has a grab, don't pass that through to Wayland */
if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
bypass_wayland = TRUE;
/* If a Wayland client has a grab, don't pass that through to Clutter */
if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
if (display->grab_op == META_GRAB_OP_WAYLAND_POPUP)
bypass_clutter = TRUE;
#ifdef HAVE_WAYLAND
if (compositor && !bypass_wayland)
{
if (meta_wayland_compositor_handle_event (compositor, event))
bypass_clutter = TRUE;
}
#endif
display->current_time = CurrentTime;
return bypass_clutter;
@@ -332,6 +238,7 @@ event_callback (const ClutterEvent *event,
void
meta_display_init_events (MetaDisplay *display)
{
meta_display_init_events_x11 (display);
display->clutter_event_filter = clutter_event_add_filter (NULL,
event_callback,
NULL,
@@ -341,6 +248,7 @@ meta_display_init_events (MetaDisplay *display)
void
meta_display_free_events (MetaDisplay *display)
{
meta_display_free_events_x11 (display);
clutter_event_remove_filter (display->clutter_event_filter);
display->clutter_event_filter = 0;
}

View File

@@ -26,11 +26,14 @@
#include "bell.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include "backends/x11/meta-backend-x11.h"
#define EVENT_MASK (SubstructureRedirectMask | \
StructureNotifyMask | SubstructureNotifyMask | \
ExposureMask | FocusChangeMask)
ExposureMask | \
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | PointerMotionHintMask | \
EnterWindowMask | LeaveWindowMask | \
FocusChangeMask)
void
meta_window_ensure_frame (MetaWindow *window)
@@ -151,6 +154,7 @@ meta_window_ensure_frame (MetaWindow *window)
* style and background.
*/
meta_ui_update_frame_style (window->screen->ui, frame->xwindow);
meta_ui_reset_frame_bg (window->screen->ui, frame->xwindow);
if (window->title)
meta_ui_set_frame_title (window->screen->ui,
@@ -159,16 +163,10 @@ meta_window_ensure_frame (MetaWindow *window)
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
{
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
}
}
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
@@ -371,6 +369,15 @@ meta_frame_sync_to_window (MetaFrame *frame,
frame->rect.x + frame->rect.width,
frame->rect.y + frame->rect.height);
/* set bg to none to avoid flicker */
if (need_resize)
{
meta_ui_unflicker_frame_bg (frame->window->screen->ui,
frame->xwindow,
frame->rect.width,
frame->rect.height);
}
meta_ui_move_resize_frame (frame->window->screen->ui,
frame->xwindow,
frame->rect.x,
@@ -380,6 +387,9 @@ meta_frame_sync_to_window (MetaFrame *frame,
if (need_resize)
{
meta_ui_reset_frame_bg (frame->window->screen->ui,
frame->xwindow);
/* If we're interactively resizing the frame, repaint
* it immediately so we don't start to lag.
*/

View File

@@ -1,5 +1,12 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file gesture-tracker-private.h Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
/*
* Copyright (C) 2014 Red Hat
*
@@ -61,7 +68,7 @@ struct _MetaGestureTrackerClass
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
MetaGestureTracker * meta_gesture_tracker_new (void);
MetaGestureTracker * meta_gesture_tracker_new (guint autodeny_timeout);
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
@@ -70,6 +77,7 @@ gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker
MetaSequenceState state);
MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence);
gint meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker);
gboolean meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
#endif /* META_GESTURE_TRACKER_PRIVATE_H */

View File

@@ -19,17 +19,8 @@
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:gesture-tracker
* @Title: MetaGestureTracker
* @Short_Description: Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
#include "config.h"
#include "meta-gesture-tracker-private.h"
#include "gesture-tracker-private.h"
#include "meta-surface-actor.h"
#define DISTANCE_THRESHOLD 30
@@ -68,22 +59,18 @@ struct _MetaGestureTrackerPrivate
};
enum {
PROP_0,
PROP_AUTODENY_TIMEOUT,
LAST_PROP,
PROP_AUTODENY_TIMEOUT = 1
};
static GParamSpec *obj_props[LAST_PROP];
enum {
STATE_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
#define DEFAULT_AUTODENY_TIMEOUT 150
static guint signals[N_SIGNALS] = { 0 };
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
@@ -153,16 +140,14 @@ meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
object_class->set_property = meta_gesture_tracker_set_property;
object_class->get_property = meta_gesture_tracker_get_property;
obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
G_PARAM_STATIC_STRINGS |
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
g_object_class_install_property (object_class,
PROP_AUTODENY_TIMEOUT,
g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, 0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[STATE_CHANGED] =
g_signal_new ("state-changed",
G_TYPE_FROM_CLASS (klass),
@@ -195,7 +180,8 @@ meta_sequence_info_new (MetaGestureTracker *tracker,
guint ms;
priv = meta_gesture_tracker_get_instance_private (tracker);
ms = priv->autodeny_timeout;
ms = (priv->autodeny_timeout) ?
priv->autodeny_timeout : DEFAULT_AUTODENY_TIMEOUT;
info = g_slice_new0 (MetaSequenceInfo);
info->tracker = tracker;
@@ -351,9 +337,11 @@ meta_gesture_tracker_init (MetaGestureTracker *tracker)
}
MetaGestureTracker *
meta_gesture_tracker_new (void)
meta_gesture_tracker_new (guint autodeny_timeout)
{
return g_object_new (META_TYPE_GESTURE_TRACKER, NULL);
return g_object_new (META_TYPE_GESTURE_TRACKER,
"autodeny-timeout", autodeny_timeout,
NULL);
}
static void
@@ -413,7 +401,6 @@ meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
MetaSequenceState state;
MetaSequenceInfo *info;
ClutterActor *stage;
gfloat x, y;
@@ -447,7 +434,6 @@ meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
meta_gesture_tracker_set_sequence_state (tracker, sequence,
priv->stage_state);
}
state = info->state;
break;
case CLUTTER_TOUCH_END:
info = g_hash_table_lookup (priv->sequences, sequence);
@@ -462,7 +448,6 @@ meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
state = info->state;
g_hash_table_remove (priv->sequences, sequence);
if (g_hash_table_size (priv->sequences) == 0)
@@ -481,34 +466,13 @@ meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
ABS (info->start_y - y) > DISTANCE_THRESHOLD))
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
state = info->state;
break;
default:
return FALSE;
break;
}
/* As soon as a sequence is accepted, we replay it to
* the stage as a captured event, and make sure it's never
* propagated anywhere else. Since ClutterGestureAction does
* all its event handling from a captured-event handler on
* the stage, this effectively acts as a "sequence grab" on
* gesture actions.
*
* Sequences that aren't (yet or never) in an accepted state
* will go through, these events will get processed through
* the compositor, and eventually through clutter, still
* triggering the gestures capturing events on the stage, and
* possibly resulting in MetaSequenceState changes.
*/
if (state == META_SEQUENCE_ACCEPTED)
{
clutter_actor_event (CLUTTER_ACTOR (clutter_event_get_stage (event)),
event, TRUE);
return TRUE;
}
return FALSE;
return TRUE;
}
gboolean
@@ -570,13 +534,22 @@ meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
return info->state;
}
gint
meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker)
gboolean
meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
MetaSequenceState state;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), 0);
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
priv = meta_gesture_tracker_get_instance_private (tracker);
return g_hash_table_size (priv->sequences);
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
state = meta_gesture_tracker_get_sequence_state (tracker, sequence);
return (event->type != CLUTTER_TOUCH_END &&
(state == META_SEQUENCE_REJECTED || state == META_SEQUENCE_PENDING_END));
}

View File

@@ -29,7 +29,6 @@
#include <gio/gio.h>
#include <meta/keybindings.h>
#include <xkbcommon/xkbcommon.h>
typedef struct _MetaKeyHandler MetaKeyHandler;
struct _MetaKeyHandler
@@ -81,6 +80,9 @@ typedef struct
*/
GSList *combos;
/* for keybindings that can have shift or not like Alt+Tab */
gboolean add_shift:1;
/* for keybindings that apply only to a window */
gboolean per_window:1;
@@ -88,23 +90,6 @@ typedef struct
gboolean builtin:1;
} MetaKeyPref;
typedef struct
{
GHashTable *key_bindings;
GHashTable *key_bindings_index;
xkb_mod_mask_t ignored_modifier_mask;
xkb_mod_mask_t hyper_mask;
xkb_mod_mask_t super_mask;
xkb_mod_mask_t meta_mask;
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
MetaKeyCombo *iso_next_group_combos;
int n_iso_next_group_combos;
/* Alt+click button grabs */
ClutterModifierType window_grab_modifiers;
} MetaKeyBindingManager;
void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
@@ -118,8 +103,8 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
gboolean meta_keybindings_process_event (MetaDisplay *display,
MetaWindow *window,
const ClutterEvent *event);
ClutterModifierType meta_display_get_window_grab_modifiers (MetaDisplay *display);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);
gboolean meta_prefs_add_keybinding (const char *name,
GSettings *settings,

File diff suppressed because it is too large Load Diff

View File

@@ -52,7 +52,6 @@
#include "ui.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#include <meta/meta-backend.h>
#include <glib-object.h>
#include <glib-unix.h>
@@ -78,9 +77,8 @@
#include "x11/session.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
#endif
#include "backends/meta-backend.h"
/*
* The exit code we'll return to our parent process when we eventually die.
@@ -96,6 +94,26 @@ static GMainLoop *meta_main_loop = NULL;
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
/**
* log_handler:
* @log_domain: the domain the error occurred in (we ignore this)
* @log_level: the log level so that we can filter out less
* important messages
* @message: the message to log
* @user_data: arbitrary data (we ignore this)
*
* Prints log messages. If Mutter was compiled with backtrace support,
* also prints a backtrace (see meta_print_backtrace()).
*/
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
meta_warning ("Log level %d: %s\n", log_level, message);
}
/**
* meta_print_compilation_info:
*
@@ -162,9 +180,7 @@ static gchar *opt_client_id;
static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
#ifdef HAVE_WAYLAND
static gboolean opt_wayland;
#endif
#ifdef HAVE_NATIVE_BACKEND
static gboolean opt_display_server;
#endif
@@ -205,14 +221,12 @@ static GOptionEntry meta_options[] = {
N_("Make X calls synchronous"),
NULL
},
#ifdef HAVE_WAYLAND
{
"wayland", 0, 0, G_OPTION_ARG_NONE,
&opt_wayland,
N_("Run as a wayland compositor"),
NULL
},
#endif
#ifdef HAVE_NATIVE_BACKEND
{
"display-server", 0, 0, G_OPTION_ARG_NONE,
@@ -277,10 +291,8 @@ meta_finalize (void)
meta_display_close (display,
CurrentTime); /* I doubt correct timestamps matter here */
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
meta_wayland_finalize ();
#endif
}
static gboolean
@@ -327,13 +339,9 @@ meta_init (void)
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
else
#endif
clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
#ifdef HAVE_WAYLAND
meta_set_is_wayland_compositor (opt_wayland);
#endif
if (g_get_home_dir ())
if (chdir (g_get_home_dir ()) < 0)
@@ -346,24 +354,15 @@ meta_init (void)
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
meta_wayland_pre_clutter_init ();
#endif
/* NB: When running as a hybrid wayland compositor we run our own headless X
* server so the user can't control the X display to connect too. */
if (!meta_is_wayland_compositor ())
{
/* NB: When running as a hybrid wayland compositor we run our own headless X
* server so the user can't control the X display to connect too. */
meta_wayland_init ();
}
else
meta_select_display (opt_display_name);
meta_clutter_init ();
#ifdef HAVE_WAYLAND
/* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */
if (meta_is_wayland_compositor ())
meta_wayland_init ();
#endif
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
if (opt_replace_wm)
@@ -376,7 +375,17 @@ meta_init (void)
meta_ui_init ();
meta_restart_init ();
/* If we are running with wayland then we don't wait until we have
* an X connection before initializing clutter we instead initialize
* it earlier since we need to initialize the GL driver so the driver
* can register any needed wayland extensions. */
if (!meta_is_wayland_compositor ())
{
/*
* Clutter can only be initialized after the UI.
*/
meta_clutter_init ();
}
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
@@ -435,10 +444,24 @@ meta_register_with_session (void)
int
meta_run (void)
{
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
g_log_set_handler (log_domains[i],
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme ());
/* Try to find some theme that'll work if the theme preference

View File

@@ -309,16 +309,9 @@ accelerator_parse (const gchar *accelerator,
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
if (keyval == XKB_KEY_NoSymbol)
{
char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
g_free (with_xf86);
if (keyval == XKB_KEY_NoSymbol)
{
error = TRUE;
goto out;
}
}
error = TRUE;
goto out;
}
}
accelerator += len;

View File

@@ -28,6 +28,7 @@
#include <config.h>
#include <meta/prefs.h>
#include "ui.h"
#include "util-private.h"
#include "meta-plugin-manager.h"
#include <glib.h>
@@ -66,7 +67,6 @@
#define SCHEMA_INTERFACE "org.gnome.desktop.interface"
#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources"
#define SCHEMA_XSETTINGS "org.gnome.settings-daemon.plugins.xsettings"
#define SCHEMA_MOUSE "org.gnome.settings-daemon.peripherals.mouse"
#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
@@ -101,7 +101,6 @@ static gboolean gnome_animations = TRUE;
static char *cursor_theme = NULL;
static int cursor_size = 24;
static int draggable_border_width = 10;
static int drag_threshold;
static gboolean resize_with_right_button = FALSE;
static gboolean edge_tiling = FALSE;
static gboolean force_fullscreen = TRUE;
@@ -493,13 +492,6 @@ static MetaIntPreference preferences_int[] =
},
&draggable_border_width
},
{
{ "drag-threshold",
SCHEMA_MOUSE,
META_PREF_DRAG_THRESHOLD,
},
&drag_threshold
},
{ { NULL, 0, 0 }, NULL },
};
@@ -986,10 +978,6 @@ meta_prefs_init (void)
g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MUTTER), settings);
settings = g_settings_new (SCHEMA_MOUSE);
g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MOUSE), settings);
/* Individual keys we watch outside of our schemas */
settings = g_settings_new (SCHEMA_INTERFACE);
g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY,
@@ -1210,9 +1198,8 @@ settings_changed (GSettings *settings,
}
else
{
/* Unknown preference type. This quite likely simply isn't
* a preference we track changes to. */
return;
/* Someone added a preference of an unhandled type */
g_assert_not_reached ();
}
g_variant_unref (value);
@@ -1347,26 +1334,10 @@ meta_prefs_get_cursor_theme (void)
return cursor_theme;
}
static int
get_scale_factor (void)
{
GdkScreen *screen;
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_INT);
/* XXX: Should this be in ui/ ? Or MetaMonitorManager? */
screen = gdk_screen_get_default ();
if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &value))
return g_value_get_int (&value);
else
return 1;
}
int
meta_prefs_get_cursor_size (void)
{
return cursor_size * get_scale_factor ();
return cursor_size;
}
@@ -1697,43 +1668,43 @@ button_layout_handler (GVariant *value,
g_strfreev (sides);
/* Invert the button layout for RTL languages */
if (meta_get_locale_direction() == META_LOCALE_DIRECTION_RTL)
{
MetaButtonLayout rtl_layout;
int j;
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
{
MetaButtonLayout rtl_layout;
int j;
for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
for (j = 0; j < i; j++)
{
rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
if (j == 0)
rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
else
rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
}
for (; j < MAX_BUTTONS_PER_CORNER; j++)
{
rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
rtl_layout.right_buttons_has_spacer[j] = FALSE;
}
for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
for (j = 0; j < i; j++)
{
rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
if (j == 0)
rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
else
rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
}
for (; j < MAX_BUTTONS_PER_CORNER; j++)
{
rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
rtl_layout.right_buttons_has_spacer[j] = FALSE;
}
for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
for (j = 0; j < i; j++)
{
rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
if (j == 0)
rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
else
rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
}
for (; j < MAX_BUTTONS_PER_CORNER; j++)
{
rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
rtl_layout.left_buttons_has_spacer[j] = FALSE;
}
for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
for (j = 0; j < i; j++)
{
rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
if (j == 0)
rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
else
rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
}
for (; j < MAX_BUTTONS_PER_CORNER; j++)
{
rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
rtl_layout.left_buttons_has_spacer[j] = FALSE;
}
new_layout = rtl_layout;
}
new_layout = rtl_layout;
}
if (!button_layout_equal (&button_layout, &new_layout))
{
@@ -1937,9 +1908,6 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_DRAGGABLE_BORDER_WIDTH:
return "DRAGGABLE_BORDER_WIDTH";
case META_PREF_DRAG_THRESHOLD:
return "DRAG_TRHESHOLD";
case META_PREF_DYNAMIC_WORKSPACES:
return "DYNAMIC_WORKSPACES";
@@ -2033,6 +2001,23 @@ update_binding (MetaKeyPref *binding,
continue;
}
/* Bug 329676: Bindings which can be shifted must not have no modifiers,
* nor only SHIFT as a modifier.
*/
if (binding->add_shift &&
0 != keysym &&
(META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
{
meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
"such as Ctrl or Alt.\n",
binding->name, strokes[i]);
/* Value is kept and will thus be removed next time we save the key.
* Changing the key in response to a modification could lead to cyclic calls. */
continue;
}
combo = g_malloc0 (sizeof (MetaKeyCombo));
combo->keysym = keysym;
combo->keycode = keycode;
@@ -2208,6 +2193,7 @@ meta_prefs_add_keybinding (const char *name,
pref->settings = g_object_ref (settings);
pref->action = action;
pref->combos = NULL;
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
@@ -2387,12 +2373,6 @@ meta_prefs_get_draggable_border_width (void)
return draggable_border_width;
}
int
meta_prefs_get_drag_threshold (void)
{
return drag_threshold;
}
void
meta_prefs_set_force_fullscreen (gboolean whether)
{

View File

@@ -1,82 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* SECTION:restart-helper
* @short_description: helper program during a restart
*
* To smoothly restart Mutter, we want to keep the composite
* overlay window enabled during the restart. This is done by
* spawning this program, which keeps a reference to the the composite
* overlay window until Mutter picks it back up.
*/
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
int
main (int argc,
char **argv)
{
Display *display = XOpenDisplay (NULL);
Window selection_window;
XSetWindowAttributes xwa;
unsigned long mask = 0;
xwa.override_redirect = True;
mask |= CWOverrideRedirect;
XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
selection_window = XCreateWindow (display,
DefaultRootWindow (display),
-100, -100, 1, 1, 0,
0,
InputOnly,
DefaultVisual (display, DefaultScreen (display)),
mask, &xwa);
XSetSelectionOwner (display,
XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
selection_window,
CurrentTime);
/* Mutter looks for an (arbitrary) line printed to stdout to know that
* we have started and have a reference to the COW. XSync() so that
* everything is set on the X server before Mutter starts restarting.
*/
XSync (display, False);
printf ("STARTED\n");
fflush (stdout);
while (True)
{
XEvent xev;
XNextEvent (display, &xev);
/* Mutter restarted and unset the selection to indicate that
* it has a reference on the COW again */
if (xev.xany.type == SelectionClear)
return 0;
}
}

View File

@@ -1,212 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:restart
* @short_description: Smoothly restart the compositor
*
* There are some cases where we need to restart Mutter in order
* to deal with changes in state - the particular case inspiring
* this is enabling or disabling stereo output. To make this
* fairly smooth for the user, we need to do two things:
*
* - Display a message to the user and make sure that it is
* actually painted before we exit.
* - Use a helper program so that the Composite Overlay Window
* isn't unmapped and mapped.
*
* This handles both of these.
*/
#include <config.h>
#include <clutter/clutter.h>
#include <gio/gunixinputstream.h>
#include <meta/main.h>
#include "ui.h"
#include "util-private.h"
#include "display-private.h"
static gboolean restart_helper_started = FALSE;
static gboolean restart_message_shown = FALSE;
static gboolean is_restart = FALSE;
void
meta_restart_init (void)
{
Display *xdisplay = meta_ui_get_display ();
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
Window restart_helper_window = None;
restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
if (restart_helper_window)
is_restart = TRUE;
}
static void
restart_check_ready (void)
{
if (restart_helper_started && restart_message_shown)
meta_display_request_restart (meta_get_display ());
}
static void
restart_helper_read_line_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
gsize length;
char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
res,
&length, &error);
if (line == NULL)
{
meta_warning ("Failed to read output from restart helper%s%s\n",
error ? ": " : NULL,
error ? error->message : NULL);
}
else
g_free (line); /* We don't actually care what the restart helper outputs */
g_object_unref (source_object);
restart_helper_started = TRUE;
restart_check_ready ();
}
static gboolean
restart_message_painted (gpointer data)
{
restart_message_shown = TRUE;
restart_check_ready ();
return FALSE;
}
/**
* meta_restart:
* @message: message to display to the user.
*
* Starts the process of restarting the compositor. Note that Mutter's
* involvement here is to make the restart visually smooth for the
* user - it cannot itself safely reexec a program that embeds libmuttter.
* So in order for this to work, the compositor must handle two
* signals - MetaDisplay::show-restart-message, to display the
* message passed here on the Clutter stage, and ::restart to actually
* reexec the compositor.
*/
void
meta_restart (const char *message)
{
MetaDisplay *display = meta_get_display();
GInputStream *unix_stream;
GDataInputStream *data_stream;
GError *error = NULL;
int helper_out_fd;
static const char * const helper_argv[] = {
MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
};
if (meta_display_show_restart_message (display, message))
{
/* Wait until the stage was painted */
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
restart_message_painted,
NULL, NULL);
}
else
{
/* Can't show the message, show the message as soon as the
* restart helper starts
*/
restart_message_painted (NULL);
}
/* We also need to wait for the restart helper to get its
* reference to the Composite Overlay Window.
*/
if (!g_spawn_async_with_pipes (NULL, /* working directory */
(char **)helper_argv,
NULL, /* envp */
G_SPAWN_DEFAULT,
NULL, NULL, /* child_setup */
NULL, /* child_pid */
NULL, /* standard_input */
&helper_out_fd,
NULL, /* standard_error */
&error))
{
meta_warning ("Failed to start restart helper: %s\n", error->message);
goto error;
}
unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
data_stream = g_data_input_stream_new (unix_stream);
g_object_unref (unix_stream);
g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
NULL, restart_helper_read_line_callback,
&error);
if (error != NULL)
{
meta_warning ("Failed to read from restart helper: %s\n", error->message);
g_object_unref (data_stream);
goto error;
}
return;
error:
/* If starting the restart helper fails, then we just go ahead and restart
* immediately. We won't get a smooth transition, since the overlay window
* will be destroyed and recreated, but otherwise it will work fine.
*/
restart_helper_started = TRUE;
restart_check_ready ();
return;
}
void
meta_restart_finish (void)
{
if (is_restart)
{
Display *xdisplay = meta_display_get_xdisplay (meta_get_display ());
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
XSetSelectionOwner (xdisplay, atom_restart_helper, None, CurrentTime);
}
}
/**
* meta_is_restart:
*
* Returns %TRUE if this instance of Mutter comes from Mutter
* restarting itself (for example to enable/disable stereo.)
* See meta_restart(). If this is the case, any startup visuals
* or animations should be suppressed.
*/
gboolean
meta_is_restart (void)
{
return is_restart;
}

View File

@@ -38,8 +38,8 @@
#include "ui.h"
#include "meta-monitor-manager.h"
typedef void (* MetaScreenWindowFunc) (MetaWindow *window,
gpointer user_data);
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
gpointer user_data);
typedef enum
{
@@ -119,8 +119,6 @@ struct _MetaScreen
* and restack them below a guard window. When using a compositor
* this allows us to provide live previews of unmapped windows */
Window guard_window;
Window composite_overlay_window;
};
struct _MetaScreenClass
@@ -140,7 +138,6 @@ void meta_screen_free (MetaScreen *scree
void meta_screen_init_workspaces (MetaScreen *screen);
void meta_screen_manage_all_windows (MetaScreen *screen);
void meta_screen_foreach_window (MetaScreen *screen,
MetaListWindowsFlags flags,
MetaScreenWindowFunc func,
gpointer data);

View File

@@ -45,7 +45,6 @@
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/Xatom.h>
#include <locale.h>
@@ -56,13 +55,12 @@
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "backends/x11/meta-backend-x11.h"
static char* get_screen_name (MetaDisplay *display,
int number);
static void update_num_workspaces (MetaScreen *screen,
guint32 timestamp);
static void update_focus_mode (MetaScreen *screen);
static void set_workspace_names (MetaScreen *screen);
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
@@ -406,13 +404,17 @@ meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
static void
reload_monitor_infos (MetaScreen *screen)
{
GList *l;
GList *tmp;
MetaMonitorManager *manager;
for (l = screen->workspaces; l != NULL; l = l->next)
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = l->data;
MetaWorkspace *space = tmp->data;
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
@@ -467,24 +469,13 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
XStoreName (xdisplay, guard_window, "mutter guard window");
{
if (!meta_is_wayland_compositor ())
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
/* Sync on the connection we created the window on to
* make sure it's created before we select on it on the
* backend connection. */
XSync (xdisplay, False);
XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
}
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, guard_window, &mask, 1);
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
@@ -501,15 +492,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
return guard_window;
}
/* Set a black background on the root window so that we don't
* see confusing old copies of old windows when debugging
* and testing. */
static void
meta_screen_set_background (MetaScreen *screen)
{
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
}
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number,
@@ -629,15 +611,24 @@ meta_screen_new (MetaDisplay *display,
/* select our root window events */
meta_error_trap_push (display);
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
*/
{
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (xdisplay, xroot, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
#ifdef HAVE_XI23
if (META_DISPLAY_HAS_XINPUT_23 (display))
{
@@ -649,6 +640,9 @@ meta_screen_new (MetaDisplay *display,
event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
StructureNotifyMask | ColormapChangeMask | PropertyChangeMask);
if (XGetWindowAttributes (xdisplay, xroot, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xroot, event_mask);
}
@@ -662,9 +656,6 @@ meta_screen_new (MetaDisplay *display,
return NULL;
}
/* Select for cursor changes so the cursor tracker is up to date. */
XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
screen = g_object_new (META_TYPE_SCREEN, NULL);
screen->closing = 0;
@@ -705,16 +696,9 @@ meta_screen_new (MetaDisplay *display,
screen->starting_corner = META_SCREEN_TOPLEFT;
screen->guard_window = None;
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
/* Now that we've gotten taken a reference count on the COW, we
* can close the helper that is holding on to it */
meta_restart_finish ();
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
meta_screen_set_background (screen);
/* Handle creating a no_focus_window for this screen */
screen->no_focus_window =
@@ -792,6 +776,7 @@ meta_screen_init_workspaces (MetaScreen *screen)
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
meta_workspace_activate (screen->workspaces->data, timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
@@ -802,8 +787,6 @@ meta_screen_init_workspaces (MetaScreen *screen)
if (current_workspace != NULL)
meta_workspace_activate (current_workspace, timestamp);
else
meta_workspace_activate (screen->workspaces->data, timestamp);
}
void
@@ -816,6 +799,8 @@ meta_screen_free (MetaScreen *screen,
screen->closing += 1;
meta_display_grab (display);
meta_compositor_unmanage (screen->display->compositor);
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
@@ -872,6 +857,9 @@ meta_screen_free (MetaScreen *screen,
g_free (screen->screen_name);
g_object_unref (screen);
XFlush (display->xdisplay);
meta_display_ungrab (display);
}
void
@@ -921,6 +909,10 @@ prefs_changed_callback (MetaPreference pref,
meta_display_get_current_time_roundtrip (screen->display);
update_num_workspaces (screen, timestamp);
}
else if (pref == META_PREF_FOCUS_MODE)
{
update_focus_mode (screen);
}
else if (pref == META_PREF_WORKSPACE_NAMES)
{
set_workspace_names (screen);
@@ -958,23 +950,75 @@ get_screen_name (MetaDisplay *display,
return scr;
}
void
meta_screen_foreach_window (MetaScreen *screen,
MetaListWindowsFlags flags,
MetaScreenWindowFunc func,
gpointer data)
static gint
ptrcmp (gconstpointer a, gconstpointer b)
{
GSList *windows;
if (a < b)
return -1;
else if (a > b)
return 1;
else
return 0;
}
static void
listify_func (gpointer key, gpointer value, gpointer data)
{
GSList **listp;
listp = data;
*listp = g_slist_prepend (*listp, value);
}
/**
* meta_screen_foreach_window:
* @screen: a #MetaScreen
* @func: function to call for each window
* @data: user data to pass to @func
*
* Calls the specified function for each window on the screen,
* ignoring override-redirect windows.
*/
void
meta_screen_foreach_window (MetaScreen *screen,
MetaScreenWindowFunc func,
gpointer data)
{
GSList *winlist;
GSList *tmp;
/* If we end up doing this often, just keeping a list
* of windows might be sensible.
*/
windows = meta_display_list_windows (screen->display, flags);
winlist = NULL;
g_hash_table_foreach (screen->display->xids,
listify_func,
&winlist);
g_slist_foreach (windows, (GFunc) func, data);
winlist = g_slist_sort (winlist, ptrcmp);
g_slist_free (windows);
tmp = winlist;
while (tmp != NULL)
{
/* If the next node doesn't contain this window
* a second time, delete the window.
*/
if (tmp->next == NULL ||
(tmp->next && tmp->next->data != tmp->data))
{
MetaWindow *window = tmp->data;
if (META_IS_WINDOW (window) &&
window->screen == screen &&
!window->override_redirect)
(* func) (screen, window, data);
}
tmp = tmp->next;
}
g_slist_free (winlist);
}
int
@@ -999,7 +1043,27 @@ MetaWorkspace*
meta_screen_get_workspace_by_index (MetaScreen *screen,
int idx)
{
return g_list_nth_data (screen->workspaces, idx);
GList *tmp;
int i;
/* should be robust, idx is maybe from an app */
if (idx < 0)
return NULL;
i = 0;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *w = tmp->data;
if (i == idx)
return w;
++i;
tmp = tmp->next;
}
return NULL;
}
static void
@@ -1073,28 +1137,41 @@ meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace,
guint32 timestamp)
{
GList *l;
GList *next;
MetaWorkspace *neighbour = NULL;
GList *next = NULL;
int index;
gboolean active_index_changed;
int new_num;
l = g_list_find (screen->workspaces, workspace);
if (!l)
return;
next = l->next;
if (l->prev)
neighbour = l->prev->data;
else if (l->next)
neighbour = l->next->data;
else
l = screen->workspaces;
while (l)
{
/* Cannot remove the only workspace! */
return;
MetaWorkspace *w = l->data;
if (w == workspace)
{
if (l->next)
next = l->next;
if (l->prev)
neighbour = l->prev->data;
else if (l->next)
neighbour = l->next->data;
else
{
/* Cannot remove the only workspace! */
return;
}
break;
}
l = l->next;
}
if (!neighbour)
return;
meta_workspace_relocate_windows (workspace, neighbour);
if (workspace == screen->active_workspace)
@@ -1119,10 +1196,14 @@ meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace,
if (active_index_changed)
meta_screen_set_active_workspace_hint (screen);
for (l = next; l != NULL; l = l->next)
l = next;
while (l)
{
MetaWorkspace *w = l->data;
meta_workspace_index_changed (w);
meta_workspace_update_window_hints (w);
l = l->next;
}
meta_screen_queue_workarea_recalc (screen);
@@ -1182,7 +1263,7 @@ update_num_workspaces (MetaScreen *screen,
guint32 timestamp)
{
int new_num, old_num;
GList *l;
GList *tmp;
int i;
GList *extras;
MetaWorkspace *last_remaining;
@@ -1221,9 +1302,10 @@ update_num_workspaces (MetaScreen *screen,
last_remaining = NULL;
extras = NULL;
i = 0;
for (l = screen->workspaces; l != NULL; l = l->next)
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *w = l->data;
MetaWorkspace *w = tmp->data;
if (i >= new_num)
extras = g_list_prepend (extras, w);
@@ -1231,6 +1313,7 @@ update_num_workspaces (MetaScreen *screen,
last_remaining = w;
++i;
tmp = tmp->next;
}
old_num = i;
@@ -1243,26 +1326,32 @@ update_num_workspaces (MetaScreen *screen,
* is on a removed workspace ;-)
*/
need_change_space = FALSE;
for (l = extras; l != NULL; l = l->next)
tmp = extras;
while (tmp != NULL)
{
MetaWorkspace *w = l->data;
MetaWorkspace *w = tmp->data;
meta_workspace_relocate_windows (w, last_remaining);
if (w == screen->active_workspace)
need_change_space = TRUE;
tmp = tmp->next;
}
if (need_change_space)
meta_workspace_activate (last_remaining, timestamp);
/* Should now be safe to free the workspaces */
for (l = extras; l != NULL; l = l->next)
tmp = extras;
while (tmp != NULL)
{
MetaWorkspace *w = l->data;
MetaWorkspace *w = tmp->data;
g_assert (w->windows == NULL);
meta_workspace_remove (w);
tmp = tmp->next;
}
g_list_free (extras);
@@ -1280,6 +1369,12 @@ update_num_workspaces (MetaScreen *screen,
g_object_notify (G_OBJECT (screen), "n-workspaces");
}
static void
update_focus_mode (MetaScreen *screen)
{
/* nothing to do anymore */ ;
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
@@ -2004,25 +2099,31 @@ static void
set_work_area_hint (MetaScreen *screen)
{
int num_workspaces;
GList *l;
GList *tmp_list;
unsigned long *data, *tmp;
MetaRectangle area;
num_workspaces = meta_screen_get_n_workspaces (screen);
data = g_new (unsigned long, num_workspaces * 4);
tmp_list = screen->workspaces;
tmp = data;
for (l = screen->workspaces; l != NULL; l = l->next)
while (tmp_list != NULL)
{
MetaWorkspace *workspace = l->data;
MetaWorkspace *workspace = tmp_list->data;
meta_workspace_get_work_area_all_monitors (workspace, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
tmp[3] = area.height;
if (workspace->screen == screen)
{
meta_workspace_get_work_area_all_monitors (workspace, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
tmp[3] = area.height;
tmp += 4;
tmp += 4;
}
tmp_list = tmp_list->next;
}
meta_error_trap_push (screen->display);
@@ -2362,8 +2463,9 @@ meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout)
}
static void
meta_screen_resize_func (MetaWindow *window,
gpointer user_data)
meta_screen_resize_func (MetaScreen *screen,
MetaWindow *window,
void *user_data)
{
if (window->struts)
{
@@ -2378,6 +2480,8 @@ static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
{
GSList *tmp, *windows;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
@@ -2401,11 +2505,24 @@ on_monitors_changed (MetaMonitorManager *manager,
&changes);
}
meta_compositor_sync_screen_size (screen->display->compositor,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, META_LIST_DEFAULT, meta_screen_resize_func, 0);
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
/* Fix up monitor for all windows on this screen */
meta_screen_foreach_window (screen, META_LIST_INCLUDE_OVERRIDE_REDIRECT, (MetaScreenWindowFunc) meta_window_update_for_monitors_changed, 0);
windows = meta_display_list_windows (screen->display,
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
if (window->screen == screen)
meta_window_update_for_monitors_changed (window);
}
g_slist_free (windows);
meta_screen_queue_check_fullscreen (screen);
@@ -2430,7 +2547,8 @@ meta_screen_update_showing_desktop_hint (MetaScreen *screen)
static void
queue_windows_showing (MetaScreen *screen)
{
GSList *windows, *l;
GSList *windows;
GSList *tmp;
/* Must operate on all windows on display instead of just on the
* active_workspace's window list, because the active_workspace's
@@ -2438,10 +2556,15 @@ queue_windows_showing (MetaScreen *screen)
*/
windows = meta_display_list_windows (screen->display, META_LIST_DEFAULT);
for (l = windows; l != NULL; l = l->next)
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = l->data;
meta_window_queue (w, META_QUEUE_CALC_SHOWING);
MetaWindow *w = tmp->data;
if (w->screen == screen)
meta_window_queue (w, META_QUEUE_CALC_SHOWING);
tmp = tmp->next;
}
g_slist_free (windows);
@@ -2451,14 +2574,22 @@ void
meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
MetaWindow *keep)
{
GList *l;
GList *windows;
GList *tmp;
for (l = screen->active_workspace->windows; l != NULL; l = l->next)
windows = screen->active_workspace->windows;
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = l->data;
MetaWindow *w = tmp->data;
if (w->has_minimize_func && w != keep)
if (w->screen == screen &&
w->has_minimize_func &&
w != keep)
meta_window_minimize (w);
tmp = tmp->next;
}
}
@@ -2466,7 +2597,7 @@ void
meta_screen_show_desktop (MetaScreen *screen,
guint32 timestamp)
{
GList *l;
GList *windows;
if (screen->active_workspace->showing_desktop)
return;
@@ -2478,17 +2609,22 @@ meta_screen_show_desktop (MetaScreen *screen,
/* Focus the most recently used META_WINDOW_DESKTOP window, if there is one;
* see bug 159257.
*/
for (l = screen->active_workspace->mru_list; l != NULL; l = l->next)
windows = screen->active_workspace->mru_list;
while (windows != NULL)
{
MetaWindow *w = l->data;
MetaWindow *w = windows->data;
if (w->type == META_WINDOW_DESKTOP)
if (w->screen == screen &&
w->type == META_WINDOW_DESKTOP)
{
meta_window_focus (w, timestamp);
break;
}
windows = windows->next;
}
meta_screen_update_showing_desktop_hint (screen);
}
@@ -2617,7 +2753,7 @@ startup_sequence_timeout (void *data)
{
MetaScreen *screen = data;
CollectTimedOutData ctod;
GSList *l;
GSList *tmp;
ctod.list = NULL;
g_get_current_time (&ctod.now);
@@ -2625,15 +2761,18 @@ startup_sequence_timeout (void *data)
collect_timed_out_foreach,
&ctod);
for (l = ctod.list; l != NULL; l = l->next)
tmp = ctod.list;
while (tmp != NULL)
{
SnStartupSequence *sequence = l->data;
SnStartupSequence *sequence = tmp->data;
meta_topic (META_DEBUG_STARTUP,
"Timed out sequence %s\n",
sn_startup_sequence_get_id (sequence));
sn_startup_sequence_complete (sequence);
tmp = tmp->next;
}
g_slist_free (ctod.list);
@@ -2734,7 +2873,7 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
{
#ifdef HAVE_STARTUP_NOTIFICATION
const char *startup_id;
GSList *l;
GSList *tmp;
SnStartupSequence *sequence;
/* Does the window have a startup ID stored? */
@@ -2752,12 +2891,12 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
* startup-notification library whether there's anything
* stored for the resource name or resource class hints.
*/
for (l = screen->startup_sequences; l != NULL; l = l->next)
tmp = screen->startup_sequences;
while (tmp != NULL)
{
const char *wmclass;
SnStartupSequence *seq = l->data;
wmclass = sn_startup_sequence_get_wmclass (seq);
wmclass = sn_startup_sequence_get_wmclass (tmp->data);
if (wmclass != NULL &&
((window->res_class &&
@@ -2765,7 +2904,7 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
(window->res_name &&
strcmp (wmclass, window->res_name) == 0)))
{
sequence = seq;
sequence = tmp->data;
g_assert (window->startup_id == NULL);
window->startup_id = g_strdup (sn_startup_sequence_get_id (sequence));
@@ -2779,6 +2918,8 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
sn_startup_sequence_complete (sequence);
break;
}
tmp = tmp->next;
}
}
@@ -2792,18 +2933,20 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
*/
if (sequence == NULL)
{
for (l = screen->startup_sequences; l != NULL; l = l->next)
tmp = screen->startup_sequences;
while (tmp != NULL)
{
SnStartupSequence *seq = l->data;
const char *id;
id = sn_startup_sequence_get_id (seq);
id = sn_startup_sequence_get_id (tmp->data);
if (strcmp (id, startup_id) == 0)
{
sequence = seq;
sequence = tmp->data;
break;
}
tmp = tmp->next;
}
}

View File

@@ -234,36 +234,32 @@ meta_stack_op_dump (MetaStackOp *op,
g_free (window_id);
}
static void
stack_dump (GArray *stack)
{
guint i;
meta_push_no_msg_prefix ();
for (i = 0; i < stack->len; i++)
{
MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
static void
meta_stack_tracker_dump (MetaStackTracker *tracker)
{
guint i;
GList *l;
meta_topic (META_DEBUG_STACK, "MetaStackTracker state (screen=%d)\n", tracker->screen->number);
meta_push_no_msg_prefix ();
meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial);
meta_topic (META_DEBUG_STACK, " xserver_stack: ");
stack_dump (tracker->xserver_stack);
meta_topic (META_DEBUG_STACK, " verfied_stack: ");
stack_dump (tracker->verified_stack);
meta_topic (META_DEBUG_STACK, " unverified_predictions: [");
for (i = 0; i < tracker->xserver_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n verfied_stack: ");
for (i = 0; i < tracker->verified_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n unverified_predictions: [");
for (l = tracker->unverified_predictions->head; l; l = l->next)
{
MetaStackOp *op = l->data;
@@ -273,8 +269,15 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
if (tracker->predicted_stack)
{
meta_topic (META_DEBUG_STACK, "\n predicted_stack: ");
stack_dump (tracker->predicted_stack);
for (i = 0; i < tracker->predicted_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->predicted_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
@@ -482,12 +485,14 @@ requery_xserver_stack (MetaStackTracker *tracker)
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
tracker->xserver_stack =
g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
g_array_set_size (tracker->xserver_stack, n_children);
for (i = 0; i < n_children; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
MetaStackWindow *window =
&g_array_index (tracker->xserver_stack, MetaStackWindow, i);
window->any.type = META_WINDOW_CLIENT_TYPE_X11;
window->x11.xwindow = children[i];
}
@@ -709,10 +714,14 @@ meta_stack_tracker_record_lower (MetaStackTracker *tracker,
*
* Return value: %TRUE if the predicted state is consistent with
* receiving the given @op from X, else %FALSE.
*
* @modified will be set to %TRUE if tracker->verified_stack is
* changed by applying any newly validated operations, else %FALSE.
*/
static gboolean
stack_tracker_verify_predictions (MetaStackTracker *tracker,
MetaStackOp *op)
MetaStackOp *op,
gboolean *modified)
{
GArray *tmp_predicted_stack = NULL;
GArray *predicted_stack;
@@ -722,8 +731,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
* passed to this api. */
g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE);
meta_topic (META_DEBUG_STACK, "Verifying predictions:\n");
if (tracker->unverified_predictions->length)
{
GList *l;
@@ -743,9 +750,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
else
predicted_stack = tracker->verified_stack;
meta_topic (META_DEBUG_STACK, " predicted_stack: ");
stack_dump (predicted_stack);
switch (op->any.type)
{
case STACK_OP_ADD:
@@ -821,6 +825,7 @@ verified:
meta_stack_op_free (queued_op);
}
*modified = modified_stack;
if (modified_stack)
{
g_array_free (tracker->verified_stack, TRUE);
@@ -842,6 +847,8 @@ not_verified:
tracker->predicted_stack = NULL;
}
*modified = FALSE;
return FALSE;
}
@@ -874,17 +881,17 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* windows and free the queue of unverified_predictions.
*
* - Iterate through the x windows listed in verified_stack at the
* same time as iterating the windows in xserver_stack. (Stop
* when we reach the end of the xserver_stack)
* same time as iterating the windows in xserver_list. (Stop
* when we reach the end of the xserver_list)
* - If the window found doesn't match the window expected
* according to the order of xserver_stack then:
* according to the order of xserver_list then:
* - Look ahead for the window we were expecting and restack
* that above the previous X window. If we fail to find the
* expected window then create a new entry for it and stack
* that.
*
* - Continue to iterate through verified_stack for any remaining
* X windows that we now know aren't in the xserver_stack and
* X windows that we now know aren't in the xserver_list and
* remove them.
*
* - Free ->predicted_stack if any.
@@ -902,11 +909,15 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
g_queue_clear (tracker->unverified_predictions);
j = 0;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
for (i = 0; i < tracker->verified_stack->len; )
for (i = 0;
i < tracker->verified_stack->len;
)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type != META_WINDOW_CLIENT_TYPE_X11)
{
@@ -943,7 +954,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
/* Technically we only need to look forward from i if we
* wanted to optimize this a bit... */
expected_index = find_window (tracker->verified_stack, expected_xwindow);
expected_index =
find_window (tracker->verified_stack, expected_xwindow);
if (expected_index >= 0)
{
@@ -981,7 +993,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
i++;
j++;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
if (j >= tracker->xserver_stack->len)
break;
@@ -991,7 +1004,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* xserver_stack and so we can remove them. */
while (i < tracker->verified_stack->len)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type == META_WINDOW_CLIENT_TYPE_X11)
g_array_remove_index (tracker->verified_stack, i);
@@ -1002,10 +1016,11 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
}
/* If we get to the end of verified_list and there are any remaining
* entries in xserver_stack then append them all to the end */
* entries in xserver_list then append them all to the end */
for (; j < tracker->xserver_stack->len; j++)
{
MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
MetaStackWindow *current =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
g_array_append_val (tracker->verified_stack, *current);
modified_stack = TRUE;
@@ -1029,13 +1044,19 @@ static void
stack_tracker_event_received (MetaStackTracker *tracker,
MetaStackOp *op)
{
/* If the event is older than our latest requery, then it's
* already included in our tree. Just ignore it. */
if (op->any.serial < tracker->xserver_serial)
return;
gboolean need_sync = FALSE;
gboolean verified;
meta_stack_op_dump (op, "Stack op event received: ", "\n");
if (op->any.serial < tracker->xserver_serial)
{
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;
}
tracker->xserver_serial = op->any.serial;
/* XXX: With the design we have ended up with it looks like we've
@@ -1049,8 +1070,13 @@ stack_tracker_event_received (MetaStackTracker *tracker,
*/
meta_stack_op_apply (op, tracker->xserver_stack);
if (!stack_tracker_verify_predictions (tracker, op))
resync_verified_stack_with_xserver_stack (tracker);
verified = stack_tracker_verify_predictions (tracker, op, &need_sync);
if (!verified)
{
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;
}
meta_stack_tracker_dump (tracker);
}

View File

@@ -45,8 +45,10 @@
w->type == META_WINDOW_MENU || \
w->type == META_WINDOW_UTILITY)
#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
(WINDOW_HAS_TRANSIENT_TYPE (w) && w->transient_for == NULL)
#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
((w->xtransient_for == None || \
w->transient_parent_is_root_window) && \
WINDOW_HAS_TRANSIENT_TYPE (w))
#define WINDOW_IN_STACK(w) (w->stack_position >= 0)
@@ -412,7 +414,8 @@ compute_layer (MetaWindow *window)
*/
if (window->layer != META_LAYER_DESKTOP &&
WINDOW_HAS_TRANSIENT_TYPE(window) &&
window->transient_for == NULL)
(window->xtransient_for == None ||
window->transient_parent_is_root_window))
{
/* We only do the group thing if the dialog is NOT transient for
* a particular window. Imagine a group with a normal window, a dock,
@@ -633,13 +636,16 @@ create_constraints (Constraint **constraints,
g_slist_free (group_windows);
}
else if (w->transient_for != NULL)
else if (w->xtransient_for != None &&
!w->transient_parent_is_root_window)
{
MetaWindow *parent;
parent = w->transient_for;
parent =
meta_display_lookup_x_window (w->display, w->xtransient_for);
if (parent && WINDOW_IN_STACK (parent))
if (parent && WINDOW_IN_STACK (parent) &&
parent->screen == w->screen)
{
meta_topic (META_DEBUG_STACK, "Constraining %s above %s due to transiency\n",
w->desc, parent->desc);
@@ -919,7 +925,7 @@ stack_do_relayer (MetaStack *stack)
GList *tmp;
if (!stack->need_relayer)
return;
return;
meta_topic (META_DEBUG_STACK,
"Recomputing layers\n");
@@ -1169,16 +1175,16 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
*/
*/
meta_stack_tracker_record_lower (screen->stack_tracker,
window,
serial);
return;
}
}
/* window is the topmost managed child */
meta_topic (META_DEBUG_STACK,
"Moving 0x%lx above topmost managed child window 0x%lx\n",
meta_topic (META_DEBUG_STACK,
"Moving 0x%lx above topmost managed child window 0x%lx\n",
window->any.type == META_WINDOW_CLIENT_TYPE_X11 ? window->x11.xwindow: 0,
sibling->any.type == META_WINDOW_CLIENT_TYPE_X11 ? sibling->x11.xwindow: 0);
@@ -1191,26 +1197,26 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
if (x11_sibling)
{
changes.sibling = x11_sibling->x11.xwindow;
changes.stack_mode = Above;
changes.stack_mode = Above;
meta_error_trap_push (screen->display);
XConfigureWindow (screen->display->xdisplay,
meta_error_trap_push (screen->display);
XConfigureWindow (screen->display->xdisplay,
window->x11.xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (screen->display);
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (screen->display);
}
else
{
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
*/
meta_error_trap_push (screen->display);
XLowerWindow (screen->display->xdisplay,
{
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
*/
meta_error_trap_push (screen->display);
XLowerWindow (screen->display->xdisplay,
window->x11.xwindow);
meta_error_trap_pop (screen->display);
}
meta_error_trap_pop (screen->display);
}
}
meta_stack_tracker_record_raise_above (screen->stack_tracker,
window,
@@ -1351,7 +1357,7 @@ stack_sync_to_xserver (MetaStack *stack)
if (x11_root_children_stacked->len > 1)
{
serial = XNextRequest (stack->screen->display->xdisplay);
XRestackWindows (stack->screen->display->xdisplay,
XRestackWindows (stack->screen->display->xdisplay,
(Window *) x11_root_children_stacked->data,
x11_root_children_stacked->len);
}
@@ -1484,7 +1490,7 @@ stack_sync_to_xserver (MetaStack *stack)
/* Restack remaining windows */
meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
(int) (new_end - newp));
(int) (new_end - newp));
/* rewind until we find the last stacked X window that we can use
* as a reference point for re-stacking remaining X windows */

View File

@@ -946,19 +946,5 @@ meta_later_remove (guint later_id)
}
}
MetaLocaleDirection
meta_get_locale_direction (void)
{
switch (gtk_get_locale_direction ())
{
case GTK_TEXT_DIR_LTR:
return META_LOCALE_DIRECTION_LTR;
case GTK_TEXT_DIR_RTL:
return META_LOCALE_DIRECTION_RTL;
default:
g_assert_not_reached ();
}
}
/* eof util.c */

View File

@@ -43,6 +43,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include "x11/iconcache.h"
#include "x11/group-private.h"
#include "wayland/meta-wayland-types.h"
@@ -106,6 +107,9 @@ struct _MetaWindow
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
MetaWindowType type;
@@ -162,7 +166,7 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
int preferred_output_winsys_id;
int preferred_output_id;
/* Whether we're shaded */
guint shaded : 1;
@@ -329,6 +333,9 @@ struct _MetaWindow
*/
guint calc_placement : 1;
/* Transient parent is a root window */
guint transient_parent_is_root_window : 1;
/* if TRUE, window was maximized at start of current grab op */
guint shaken_loose : 1;
@@ -344,6 +351,10 @@ struct _MetaWindow
/* whether or not the window is from a program running on another machine */
guint is_remote : 1;
/* Used for Wayland -- surfaces can behave as if they were unmapped if
* they have a NULL buffer attached... */
guint surface_mapped;
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
@@ -477,9 +488,6 @@ struct _MetaWindowClass
void (*get_default_skip_hints) (MetaWindow *window,
gboolean *skip_taskbar_out,
gboolean *skip_pager_out);
gboolean (*update_icon) (MetaWindow *window,
GdkPixbuf **icon,
GdkPixbuf **mini_icon);
};
/* These differ from window->has_foo_func in that they consider
@@ -518,6 +526,7 @@ MetaWindow * _meta_window_shared_new (MetaDisplay *display,
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);
void meta_window_queue (MetaWindow *window,
guint queuebits);
void meta_window_tile (MetaWindow *window);
@@ -623,8 +632,10 @@ void meta_window_stack_just_below (MetaWindow *window,
void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp);
void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_on_all_workspaces_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
gboolean meta_window_should_attach_to_parent (MetaWindow *window);
gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
@@ -661,8 +672,11 @@ void meta_window_handle_enter (MetaWindow *window,
guint root_y);
void meta_window_handle_leave (MetaWindow *window);
void meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event);
gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event);
void meta_window_set_surface_mapped (MetaWindow *window,
gboolean surface_mapped);
void meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect);
@@ -674,6 +688,8 @@ void meta_window_activate_full (MetaWindow *window,
MetaClientType source_indication,
MetaWorkspace *workspace);
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window,
gboolean user_op);

File diff suppressed because it is too large Load Diff

View File

@@ -94,6 +94,4 @@ void meta_workspace_focus_default_window (MetaWorkspace *workspace,
const char* meta_workspace_get_name (MetaWorkspace *workspace);
void meta_workspace_index_changed (MetaWorkspace *workspace);
#endif

View File

@@ -47,6 +47,12 @@
#include <canberra-gtk.h>
#endif
enum {
PROP_0,
PROP_N_WINDOWS,
};
void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
static void focus_ancestor_or_top_window (MetaWorkspace *workspace,
MetaWindow *not_this_one,
@@ -56,17 +62,6 @@ static void free_this (gpointer candidate,
G_DEFINE_TYPE (MetaWorkspace, meta_workspace, G_TYPE_OBJECT);
enum {
PROP_0,
PROP_N_WINDOWS,
PROP_WORKSPACE_INDEX,
LAST_PROP,
};
static GParamSpec *obj_props[LAST_PROP];
enum
{
WINDOW_ADDED,
@@ -75,7 +70,7 @@ enum
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static guint signals [LAST_SIGNAL] = { 0 };
static void
meta_workspace_finalize (GObject *object)
@@ -115,9 +110,6 @@ meta_workspace_get_property (GObject *object,
*/
g_value_set_uint (value, g_list_length (ws->windows));
break;
case PROP_WORKSPACE_INDEX:
g_value_set_uint (value, meta_workspace_index (ws));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -128,6 +120,8 @@ static void
meta_workspace_class_init (MetaWorkspaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->finalize = meta_workspace_finalize;
object_class->get_property = meta_workspace_get_property;
object_class->set_property = meta_workspace_set_property;
@@ -147,18 +141,15 @@ meta_workspace_class_init (MetaWorkspaceClass *klass)
G_TYPE_NONE, 1,
META_TYPE_WINDOW);
obj_props[PROP_N_WINDOWS] = g_param_spec_uint ("n-windows",
"N Windows",
"Number of windows",
0, G_MAXUINT, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_props[PROP_WORKSPACE_INDEX] = g_param_spec_uint ("workspace-index",
"Workspace index",
"The workspace's index",
0, G_MAXUINT, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
pspec = g_param_spec_uint ("n-windows",
"N Windows",
"Number of windows",
0, G_MAXUINT, 0,
G_PARAM_READABLE);
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
g_object_class_install_property (object_class,
PROP_N_WINDOWS,
pspec);
}
static void
@@ -166,6 +157,15 @@ meta_workspace_init (MetaWorkspace *workspace)
{
}
static void
maybe_add_to_list (MetaScreen *screen, MetaWindow *window, gpointer data)
{
GList **mru_list = data;
if (window->on_all_workspaces)
*mru_list = g_list_prepend (*mru_list, window);
}
MetaWorkspace*
meta_workspace_new (MetaScreen *screen)
{
@@ -178,6 +178,7 @@ meta_workspace_new (MetaScreen *screen)
g_list_append (workspace->screen->workspaces, workspace);
workspace->windows = NULL;
workspace->mru_list = NULL;
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
workspace->work_areas_invalid = TRUE;
workspace->work_area_monitor = NULL;
@@ -241,28 +242,34 @@ workspace_free_builtin_struts (MetaWorkspace *workspace)
workspace->builtin_struts = NULL;
}
/* Ensure that the workspace is empty by making sure that
* all of our windows are on-all-workspaces. */
static void
assert_workspace_empty (MetaWorkspace *workspace)
{
GList *l;
for (l = workspace->windows; l != NULL; l = l->next)
{
MetaWindow *window = l->data;
g_assert (window->on_all_workspaces);
}
}
void
meta_workspace_remove (MetaWorkspace *workspace)
{
GList *tmp;
MetaScreen *screen;
int i;
g_return_if_fail (workspace != workspace->screen->active_workspace);
assert_workspace_empty (workspace);
/* Here we assume all the windows are already on another workspace
* as well, so they won't be "orphaned"
*/
tmp = workspace->windows;
while (tmp != NULL)
{
GList *next;
MetaWindow *window = tmp->data;
next = tmp->next;
/* pop front of list we're iterating over */
meta_workspace_remove_window (workspace, window);
g_assert (window->workspace != NULL);
tmp = next;
}
g_assert (workspace->windows == NULL);
screen = workspace->screen;
@@ -305,11 +312,38 @@ void
meta_workspace_add_window (MetaWorkspace *workspace,
MetaWindow *window)
{
g_assert (g_list_find (workspace->mru_list, window) == NULL);
workspace->mru_list = g_list_prepend (workspace->mru_list, window);
g_return_if_fail (window->workspace == NULL);
/* If the window is on all workspaces, we want to add it to all mru
* lists, otherwise just add it to this workspaces mru list
*/
if (window->on_all_workspaces)
{
if (window->workspace == NULL)
{
GList* tmp = window->screen->workspaces;
while (tmp)
{
MetaWorkspace* work = (MetaWorkspace*) tmp->data;
if (!g_list_find (work->mru_list, window))
work->mru_list = g_list_prepend (work->mru_list, window);
tmp = tmp->next;
}
}
}
else
{
g_assert (g_list_find (workspace->mru_list, window) == NULL);
workspace->mru_list = g_list_prepend (workspace->mru_list, window);
}
workspace->windows = g_list_prepend (workspace->windows, window);
window->workspace = workspace;
meta_window_current_workspace_changed (window);
if (window->struts)
{
meta_topic (META_DEBUG_WORKAREA,
@@ -318,18 +352,46 @@ meta_workspace_add_window (MetaWorkspace *workspace,
meta_workspace_invalidate_work_area (workspace);
}
/* queue a move_resize since changing workspaces may change
* the relevant struts
*/
meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);
g_signal_emit (workspace, signals[WINDOW_ADDED], 0, window);
g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_N_WINDOWS]);
g_object_notify (G_OBJECT (workspace), "n-windows");
}
void
meta_workspace_remove_window (MetaWorkspace *workspace,
MetaWindow *window)
{
workspace->windows = g_list_remove (workspace->windows, window);
g_return_if_fail (window->workspace == workspace);
workspace->mru_list = g_list_remove (workspace->mru_list, window);
g_assert (g_list_find (workspace->mru_list, window) == NULL);
workspace->windows = g_list_remove (workspace->windows, window);
window->workspace = NULL;
/* If the window is on all workspaces, we don't want to remove it
* from the MRU list unless this causes it to be removed from all
* workspaces
*/
if (window->on_all_workspaces)
{
GList* tmp = window->screen->workspaces;
while (tmp)
{
MetaWorkspace* work = (MetaWorkspace*) tmp->data;
work->mru_list = g_list_remove (work->mru_list, window);
tmp = tmp->next;
}
}
else
{
workspace->mru_list = g_list_remove (workspace->mru_list, window);
g_assert (g_list_find (workspace->mru_list, window) == NULL);
}
meta_window_current_workspace_changed (window);
if (window->struts)
{
@@ -339,6 +401,11 @@ meta_workspace_remove_window (MetaWorkspace *workspace,
meta_workspace_invalidate_work_area (workspace);
}
/* queue a move_resize since changing workspaces may change
* the relevant struts
*/
meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);
g_signal_emit (workspace, signals[WINDOW_REMOVED], 0, window);
g_object_notify (G_OBJECT (workspace), "n-windows");
}
@@ -347,33 +414,42 @@ void
meta_workspace_relocate_windows (MetaWorkspace *workspace,
MetaWorkspace *new_home)
{
GList *copy, *l;
GList *tmp;
GList *copy;
g_return_if_fail (workspace != new_home);
/* can't modify list we're iterating over */
copy = g_list_copy (workspace->windows);
for (l = copy; l != NULL; l = l->next)
tmp = copy;
while (tmp != NULL)
{
MetaWindow *window = l->data;
MetaWindow *window = tmp->data;
if (!window->override_redirect)
meta_window_change_workspace (window, new_home);
meta_workspace_remove_window (workspace, window);
meta_workspace_add_window (new_home, window);
tmp = tmp->next;
}
g_list_free (copy);
assert_workspace_empty (workspace);
g_assert (workspace->windows == NULL);
}
void
meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
{
GList *l;
GList *tmp;
for (l = workspace->windows; l != NULL; l = l->next)
meta_window_queue (l->data, META_QUEUE_CALC_SHOWING);
tmp = workspace->windows;
while (tmp != NULL)
{
meta_window_queue (tmp->data, META_QUEUE_CALC_SHOWING);
tmp = tmp->next;
}
}
static void
@@ -496,18 +572,22 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
* or the new one *but not both*, then update the
* _net_showing_desktop hint
*/
if (old && (old->showing_desktop != workspace->showing_desktop))
if (old && (old->showing_desktop ^ workspace->showing_desktop))
meta_screen_update_showing_desktop_hint (workspace->screen);
if (old == NULL)
return;
move_window = NULL;
if (meta_grab_op_is_moving (workspace->screen->display->grab_op))
if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
move_window = workspace->screen->display->grab_window;
if (move_window != NULL)
{
if (move_window->on_all_workspaces)
move_window = NULL; /* don't move it after all */
/* We put the window on the new workspace, flip spaces,
* then remove from old workspace, so the window
* never gets unmapped and we maintain the button grab
@@ -515,13 +595,21 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
*
* \bug This comment appears to be the reverse of what happens
*/
if (!meta_window_located_on_workspace (move_window, workspace))
meta_window_change_workspace (move_window, workspace);
if (move_window && (move_window->workspace != workspace))
{
meta_workspace_remove_window (old, move_window);
meta_workspace_add_window (workspace, move_window);
}
}
meta_workspace_queue_calc_showing (old);
meta_workspace_queue_calc_showing (workspace);
/* FIXME: Why do we need this?!? Isn't it handled in the lines above? */
if (move_window)
/* Removes window from other spaces */
meta_window_change_workspace (move_window, workspace);
/*
* Notify the compositor that the active workspace is changing.
*/
@@ -539,7 +627,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
new_space, &layout2);
if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
{
if (layout1.current_col > layout2.current_col)
direction = META_MOTION_RIGHT;
@@ -623,16 +711,17 @@ meta_workspace_index (MetaWorkspace *workspace)
}
void
meta_workspace_index_changed (MetaWorkspace *workspace)
meta_workspace_update_window_hints (MetaWorkspace *workspace)
{
GList *l;
for (l = workspace->windows; l != NULL; l = l->next)
GList *l = workspace->windows;
while (l)
{
MetaWindow *win = l->data;
meta_window_current_workspace_changed (win);
}
g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_WORKSPACE_INDEX]);
meta_window_current_workspace_changed (win);
l = l->next;
}
}
/**
@@ -647,20 +736,24 @@ meta_workspace_index_changed (MetaWorkspace *workspace)
GList*
meta_workspace_list_windows (MetaWorkspace *workspace)
{
GSList *display_windows, *l;
GSList *display_windows;
GSList *tmp;
GList *workspace_windows;
display_windows = meta_display_list_windows (workspace->screen->display,
META_LIST_DEFAULT);
workspace_windows = NULL;
for (l = display_windows; l != NULL; l = l->next)
tmp = display_windows;
while (tmp != NULL)
{
MetaWindow *window = l->data;
MetaWindow *window = tmp->data;
if (meta_window_located_on_workspace (window, workspace))
workspace_windows = g_list_prepend (workspace_windows,
window);
tmp = tmp->next;
}
g_slist_free (display_windows);
@@ -671,7 +764,8 @@ meta_workspace_list_windows (MetaWorkspace *workspace)
void
meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
{
GList *windows, *l;
GList *tmp;
GList *windows;
int i;
if (workspace->work_areas_invalid)
@@ -711,11 +805,14 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
/* redo the size/position constraints on all windows */
windows = meta_workspace_list_windows (workspace);
for (l = windows; l != NULL; l = l->next)
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = l->data;
MetaWindow *w = tmp->data;
meta_window_queue (w, META_QUEUE_MOVE_RESIZE);
tmp = tmp->next;
}
g_list_free (windows);
@@ -734,8 +831,11 @@ copy_strut_list(GSList *original)
{
GSList *result = NULL;
for (; original != NULL; original = original->next)
result = g_slist_prepend (result, copy_strut (original->data));
while (original)
{
result = g_slist_prepend (result, copy_strut (original->data));
original = original->next;
}
return g_slist_reverse (result);
}
@@ -1102,7 +1202,7 @@ meta_workspace_get_neighbor (MetaWorkspace *workspace,
meta_verbose ("Getting neighbor of %d in direction %s\n",
current_space, meta_motion_direction_to_string (direction));
ltr = (meta_get_locale_direction () == META_LOCALE_DIRECTION_LTR);
ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR;
switch (direction)
{

View File

@@ -111,75 +111,41 @@ typedef enum
* @META_GRAB_OP_COMPOSITOR: Compositor asked for grab
*/
/* The lower 16 bits of the grab operation is its type.
*
* Window grab operations have the following layout:
*
* 0000 0000 | 0000 0011
* NSEW flags | type
*
* Flags contains whether the operation is a keyboard operation,
* and whether the keyboard operation is "unknown".
*
* The rest of the flags tell you which direction the resize is
* going in.
*
* If the directions field is 0000, then the operation is a move,
* not a resize.
/* when changing this enum, there are various switch statements
* you have to update
*/
enum
{
META_GRAB_OP_WINDOW_FLAG_KEYBOARD = 0x0100,
META_GRAB_OP_WINDOW_FLAG_UNKNOWN = 0x0200,
META_GRAB_OP_WINDOW_DIR_WEST = 0x1000,
META_GRAB_OP_WINDOW_DIR_EAST = 0x2000,
META_GRAB_OP_WINDOW_DIR_SOUTH = 0x4000,
META_GRAB_OP_WINDOW_DIR_NORTH = 0x8000,
META_GRAB_OP_WINDOW_DIR_MASK = 0xF000,
/* WGO = "window grab op". shorthand for below */
_WGO_K = META_GRAB_OP_WINDOW_FLAG_KEYBOARD,
_WGO_U = META_GRAB_OP_WINDOW_FLAG_UNKNOWN,
_WGO_W = META_GRAB_OP_WINDOW_DIR_WEST,
_WGO_E = META_GRAB_OP_WINDOW_DIR_EAST,
_WGO_S = META_GRAB_OP_WINDOW_DIR_SOUTH,
_WGO_N = META_GRAB_OP_WINDOW_DIR_NORTH,
};
#define GRAB_OP_GET_BASE_TYPE(op) (op & 0x00FF)
typedef enum
{
META_GRAB_OP_NONE,
/* Mouse ops */
META_GRAB_OP_MOVING,
META_GRAB_OP_RESIZING_SE,
META_GRAB_OP_RESIZING_S,
META_GRAB_OP_RESIZING_SW,
META_GRAB_OP_RESIZING_N,
META_GRAB_OP_RESIZING_NE,
META_GRAB_OP_RESIZING_NW,
META_GRAB_OP_RESIZING_W,
META_GRAB_OP_RESIZING_E,
/* Keyboard ops */
META_GRAB_OP_KEYBOARD_MOVING,
META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
META_GRAB_OP_KEYBOARD_RESIZING_S,
META_GRAB_OP_KEYBOARD_RESIZING_N,
META_GRAB_OP_KEYBOARD_RESIZING_W,
META_GRAB_OP_KEYBOARD_RESIZING_E,
META_GRAB_OP_KEYBOARD_RESIZING_SE,
META_GRAB_OP_KEYBOARD_RESIZING_NE,
META_GRAB_OP_KEYBOARD_RESIZING_SW,
META_GRAB_OP_KEYBOARD_RESIZING_NW,
/* Special grab op when the compositor asked for a grab */
META_GRAB_OP_COMPOSITOR,
/* For when a Wayland client takes a popup grab */
META_GRAB_OP_WAYLAND_POPUP,
/* Window grab ops. */
META_GRAB_OP_WINDOW_BASE,
META_GRAB_OP_MOVING = META_GRAB_OP_WINDOW_BASE,
META_GRAB_OP_RESIZING_NW = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_W,
META_GRAB_OP_RESIZING_N = META_GRAB_OP_WINDOW_BASE | _WGO_N,
META_GRAB_OP_RESIZING_NE = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_E,
META_GRAB_OP_RESIZING_E = META_GRAB_OP_WINDOW_BASE | _WGO_E,
META_GRAB_OP_RESIZING_SW = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_W,
META_GRAB_OP_RESIZING_S = META_GRAB_OP_WINDOW_BASE | _WGO_S,
META_GRAB_OP_RESIZING_SE = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_E,
META_GRAB_OP_RESIZING_W = META_GRAB_OP_WINDOW_BASE | _WGO_W,
META_GRAB_OP_KEYBOARD_MOVING = META_GRAB_OP_WINDOW_BASE | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN = META_GRAB_OP_WINDOW_BASE | _WGO_K | _WGO_U,
META_GRAB_OP_KEYBOARD_RESIZING_NW = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_W | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_N = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_NE = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_E | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_E = META_GRAB_OP_WINDOW_BASE | _WGO_E | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_SW = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_W | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_S = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_SE = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_E | _WGO_K,
META_GRAB_OP_KEYBOARD_RESIZING_W = META_GRAB_OP_WINDOW_BASE | _WGO_W | _WGO_K,
} MetaGrabOp;
/**

View File

@@ -109,6 +109,9 @@ void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
void meta_compositor_sync_stack (MetaCompositor *compositor,
GList *stack);
void meta_compositor_sync_screen_size (MetaCompositor *compositor,
guint width,
guint height);
void meta_compositor_flash_screen (MetaCompositor *compositor,
MetaScreen *screen);

View File

@@ -66,6 +66,9 @@ GType meta_display_get_type (void) G_GNUC_CONST;
#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0)
void meta_display_get_compositor_version (MetaDisplay *display,
int *major,
int *minor);
int meta_display_get_xinput_opcode (MetaDisplay *display);
gboolean meta_display_supports_extended_barriers (MetaDisplay *display);
Display *meta_display_get_xdisplay (MetaDisplay *display);
@@ -179,7 +182,4 @@ void meta_display_ungrab_keyboard (MetaDisplay *display,
guint32 timestamp);
void meta_display_unfreeze_keyboard (MetaDisplay *display,
guint32 timestamp);
gboolean meta_display_is_pointer_emulating_sequence (MetaDisplay *display,
ClutterEventSequence *sequence);
#endif

View File

@@ -27,7 +27,6 @@ const char *meta_key_binding_get_name (MetaKeyBinding *binding);
MetaVirtualModifier meta_key_binding_get_modifiers (MetaKeyBinding *binding);
guint meta_key_binding_get_mask (MetaKeyBinding *binding);
gboolean meta_key_binding_is_builtin (MetaKeyBinding *binding);
gboolean meta_key_binding_is_reversed (MetaKeyBinding *binding);
gboolean meta_keybindings_set_custom_handler (const gchar *name,
MetaKeyHandlerFunc handler,

View File

@@ -34,9 +34,6 @@ gboolean meta_get_replace_current_wm (void); /* Actually defined in util
void meta_set_wm_name (const char *wm_name);
void meta_set_gnome_wm_keybindings (const char *wm_keybindings);
void meta_restart (const char *message);
gboolean meta_is_restart (void);
/**
* MetaExitCode:
* @META_EXIT_SUCCESS: Success

View File

@@ -94,15 +94,6 @@ struct _MetaPluginClass
void (*minimize) (MetaPlugin *plugin,
MetaWindowActor *actor);
/**
* MetaPluginClass::unminimize:
* @actor: a #MetaWindowActor
*
* Virtual function called when the window represented by @actor is unminimized.
*/
void (*unminimize) (MetaPlugin *plugin,
MetaWindowActor *actor);
/**
* MetaPluginClass::maximize:
* @actor: a #MetaWindowActor
@@ -381,10 +372,6 @@ void
meta_plugin_minimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_unminimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor);

View File

@@ -102,8 +102,7 @@ typedef enum
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
META_PREF_DRAGGABLE_BORDER_WIDTH,
META_PREF_AUTO_MAXIMIZE,
META_PREF_CENTER_NEW_WINDOWS,
META_PREF_DRAG_THRESHOLD,
META_PREF_CENTER_NEW_WINDOWS
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -167,7 +166,6 @@ void meta_prefs_set_force_fullscreen (gboolean whether);
gboolean meta_prefs_get_workspaces_only_on_primary (void);
int meta_prefs_get_draggable_border_width (void);
int meta_prefs_get_drag_threshold (void);
gboolean meta_prefs_get_ignore_request_hide_titlebar (void);
void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
@@ -369,6 +367,7 @@ typedef enum _MetaKeyBindingAction
* @META_KEY_BINDING_NONE: none
* @META_KEY_BINDING_PER_WINDOW: per-window
* @META_KEY_BINDING_BUILTIN: built-in
* @META_KEY_BINDING_REVERSES: reverses
* @META_KEY_BINDING_IS_REVERSED: is reversed
*/
typedef enum
@@ -376,7 +375,8 @@ typedef enum
META_KEY_BINDING_NONE,
META_KEY_BINDING_PER_WINDOW = 1 << 0,
META_KEY_BINDING_BUILTIN = 1 << 1,
META_KEY_BINDING_IS_REVERSED = 1 << 2,
META_KEY_BINDING_REVERSES = 1 << 2,
META_KEY_BINDING_IS_REVERSED = 1 << 3
} MetaKeyBindingFlags;
/**
@@ -405,3 +405,7 @@ gboolean meta_prefs_bell_is_audible (void);
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
#endif

View File

@@ -181,14 +181,6 @@ guint meta_later_add (MetaLaterType when,
GDestroyNotify notify);
void meta_later_remove (guint later_id);
typedef enum
{
META_LOCALE_DIRECTION_LTR,
META_LOCALE_DIRECTION_RTL,
} MetaLocaleDirection;
MetaLocaleDirection meta_get_locale_direction (void);
#endif /* META_UTIL_H */

View File

@@ -256,7 +256,6 @@ gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
gboolean meta_window_is_above (MetaWindow *window);
gboolean meta_window_allows_move (MetaWindow *window);
gboolean meta_window_allows_resize (MetaWindow *window);
gboolean meta_window_is_client_decorated (MetaWindow *window);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);

View File

@@ -49,6 +49,7 @@ void meta_workspace_activate_with_focus (MetaWorkspace *workspace,
MetaWindow *focus_this,
guint32 timestamp);
void meta_workspace_update_window_hints (MetaWorkspace *workspace);
void meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
GSList *struts);

View File

@@ -65,6 +65,9 @@ static void meta_frames_paint (MetaFrames *frames,
MetaUIFrame *frame,
cairo_t *cr);
static void meta_frames_set_window_background (MetaFrames *frames,
MetaUIFrame *frame);
static void meta_frames_calc_geometry (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameGeometry *fgeom);
@@ -297,6 +300,12 @@ queue_recalc_func (gpointer key, gpointer value, gpointer data)
frames = META_FRAMES (data);
frame = value;
/* If a resize occurs it will cause a redraw, but the
* resize may not actually be needed so we always redraw
* in case of color change.
*/
meta_frames_set_window_background (frames, frame);
invalidate_whole_window (frames, frame);
meta_core_queue_frame_resize (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
frame->xwindow);
@@ -336,6 +345,12 @@ queue_draw_func (gpointer key, gpointer value, gpointer data)
frames = META_FRAMES (data);
frame = value;
/* If a resize occurs it will cause a redraw, but the
* resize may not actually be needed so we always redraw
* in case of color change.
*/
meta_frames_set_window_background (frames, frame);
invalidate_whole_window (frames, frame);
}
@@ -574,6 +589,11 @@ meta_frames_manage_window (MetaFrames *frames,
frame->shape_applied = FALSE;
frame->prelit_control = META_FRAME_CONTROL_NONE;
/* Don't set the window background yet; we need frame->xwindow to be
* registered with its MetaWindow, which happens after this function
* and meta_ui_create_frame_window() return to meta_window_ensure_frame().
*/
meta_core_grab_buttons (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
g_hash_table_replace (frames->frames, &frame->xwindow, frame);
@@ -703,6 +723,42 @@ meta_ui_frame_get_corner_radiuses (MetaFrames *frames,
*bottom_right = fgeom.bottom_right_corner_rounded_radius + sqrt(fgeom.bottom_right_corner_rounded_radius);
}
void
meta_frames_reset_bg (MetaFrames *frames,
Window xwindow)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, xwindow);
meta_frames_set_window_background (frames, frame);
}
static void
set_background_none (Display *xdisplay,
Window xwindow)
{
XSetWindowAttributes attrs;
attrs.background_pixmap = None;
XChangeWindowAttributes (xdisplay, xwindow,
CWBackPixmap, &attrs);
}
void
meta_frames_unflicker_bg (MetaFrames *frames,
Window xwindow,
int target_width,
int target_height)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, xwindow);
g_return_if_fail (frame != NULL);
set_background_none (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
}
/* The client rectangle surrounds client window; it subtracts both
* the visible and invisible borders from the frame window's size.
*/
@@ -1523,6 +1579,7 @@ meta_frames_motion_notify_event (GtkWidget *widget,
MetaUIFrame *frame;
MetaFrames *frames;
MetaFrameControl control;
int x, y;
frames = META_FRAMES (widget);
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
@@ -1531,7 +1588,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
frames->last_motion_frame = frame;
control = get_control (frames, frame, event->x, event->y);
gdk_window_get_device_position (frame->window, event->device,
&x, &y, NULL);
control = get_control (frames, frame, x, y);
if (frame->button_state == META_BUTTON_STATE_PRESSED)
{
@@ -1845,6 +1904,52 @@ meta_frames_paint (MetaFrames *frames,
mini_icon, icon);
}
static void
meta_frames_set_window_background (MetaFrames *frames,
MetaUIFrame *frame)
{
MetaFrameFlags flags;
MetaFrameType type;
MetaFrameStyle *style = NULL;
gboolean frame_exists;
meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
META_CORE_WINDOW_HAS_FRAME, &frame_exists,
META_CORE_GET_FRAME_FLAGS, &flags,
META_CORE_GET_FRAME_TYPE, &type,
META_CORE_GET_END);
if (frame_exists)
{
style = meta_theme_get_frame_style (meta_theme_get_current (),
type, flags);
}
if (frame_exists && style->window_background_color != NULL)
{
GdkRGBA color;
GdkVisual *visual;
meta_color_spec_render (style->window_background_color,
frame->style,
&color);
/* Set A in ARGB to window_background_alpha, if we have ARGB */
visual = gtk_widget_get_visual (GTK_WIDGET (frames));
if (gdk_visual_get_depth (visual) == 32) /* we have ARGB */
{
color.alpha = style->window_background_alpha / 255.0;
}
gdk_window_set_background_rgba (frame->window, &color);
}
else
{
gtk_style_context_set_background (frame->style, frame->window);
}
}
static gboolean
meta_frames_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event)

View File

@@ -138,6 +138,13 @@ void meta_frames_get_borders (MetaFrames *frames,
Window xwindow,
MetaFrameBorders *borders);
void meta_frames_reset_bg (MetaFrames *frames,
Window xwindow);
void meta_frames_unflicker_bg (MetaFrames *frames,
Window xwindow,
int target_width,
int target_height);
cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
Window xwindow,
int window_width,

View File

@@ -65,7 +65,7 @@ free_buffer (guchar *pixels, gpointer data)
}
static GdkPixbuf*
blank_pixbuf (int width, int height)
blank_pixbuf (int width, int height, gboolean no_padding)
{
guchar *buf;
int rowstride;
@@ -73,15 +73,18 @@ blank_pixbuf (int width, int height)
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((4 * width + 4) / 4);
if (no_padding)
rowstride = width * 3;
else
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((3 * width + 3) / 4);
buf = g_try_malloc (height * rowstride);
if (!buf)
return NULL;
return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
TRUE, 8,
FALSE, 8,
width, height, rowstride,
free_buffer, NULL);
}
@@ -193,14 +196,14 @@ meta_gradient_create_interwoven (int width,
{
int i, j, k, l, ll;
long r1, g1, b1, a1, dr1, dg1, db1, da1;
long r2, g2, b2, a2, dr2, dg2, db2, da2;
long r1, g1, b1, dr1, dg1, db1;
long r2, g2, b2, dr2, dg2, db2;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -210,22 +213,18 @@ meta_gradient_create_interwoven (int width,
r1 = (long)(colors1[0].red*0xffffff);
g1 = (long)(colors1[0].green*0xffffff);
b1 = (long)(colors1[0].blue*0xffffff);
a1 = (long)(colors1[0].alpha*0xffffff);
r2 = (long)(colors2[0].red*0xffffff);
g2 = (long)(colors2[0].green*0xffffff);
b2 = (long)(colors2[0].blue*0xffffff);
a2 = (long)(colors2[0].alpha*0xffffff);
dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height;
dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
da2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height;
for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
{
@@ -236,19 +235,17 @@ meta_gradient_create_interwoven (int width,
ptr[0] = (unsigned char) (r1>>16);
ptr[1] = (unsigned char) (g1>>16);
ptr[2] = (unsigned char) (b1>>16);
ptr[3] = (unsigned char) (a1>>16);
}
else
{
ptr[0] = (unsigned char) (r2>>16);
ptr[1] = (unsigned char) (g2>>16);
ptr[2] = (unsigned char) (b2>>16);
ptr[3] = (unsigned char) (a2>>16);
}
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
if (++l == ll)
{
@@ -267,12 +264,10 @@ meta_gradient_create_interwoven (int width,
r1+=dr1;
g1+=dg1;
b1+=db1;
a1+=da1;
r2+=dr2;
g2+=dg2;
b2+=db2;
a2+=da2;
}
return pixbuf;
@@ -297,15 +292,15 @@ meta_gradient_create_horizontal (int width, int height,
const GdkRGBA *to)
{
int i;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -316,32 +311,26 @@ meta_gradient_create_horizontal (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0 << 16;
g = g0 << 16;
b = b0 << 16;
a = a0 << 16;
dr = ((rf-r0)<<16)/(int)width;
dg = ((gf-g0)<<16)/(int)width;
db = ((bf-b0)<<16)/(int)width;
da = ((af-a0)<<16)/(int)width;
/* render the first line */
for (i=0; i<width; i++)
{
*(ptr++) = (unsigned char)(r>>16);
*(ptr++) = (unsigned char)(g>>16);
*(ptr++) = (unsigned char)(b>>16);
*(ptr++) = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
}
/* copy the first line to the other lines */
@@ -371,15 +360,15 @@ meta_gradient_create_vertical (int width, int height,
const GdkRGBA *to)
{
int i, j;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
unsigned char *pixels;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -389,21 +378,17 @@ meta_gradient_create_vertical (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0<<16;
g = g0<<16;
b = b0<<16;
a = a0<<16;
dr = ((rf-r0)<<16)/(int)height;
dg = ((gf-g0)<<16)/(int)height;
db = ((bf-b0)<<16)/(int)height;
da = ((af-a0)<<16)/(int)height;
for (i=0; i<height; i++)
{
@@ -412,16 +397,14 @@ meta_gradient_create_vertical (int width, int height,
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
r+=dr;
g+=dg;
b+=db;
a+=da;
}
return pixbuf;
}
@@ -459,7 +442,7 @@ meta_gradient_create_diagonal (int width, int height,
else if (height == 1)
return meta_gradient_create_horizontal (width, height, from, to);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -476,12 +459,12 @@ meta_gradient_create_diagonal (int width, int height,
ptr = gdk_pixbuf_get_pixels (tmp);
a = ((float)(width - 1))/((float)(height - 1));
width = width * 4;
width = width * 3;
/* copy the first line to the other lines with corresponding offset */
for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
{
memcpy (&(pixels[j]), &ptr[4*(int)offset], width);
memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
offset += a;
}
@@ -496,7 +479,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
@@ -505,7 +488,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -526,7 +509,6 @@ meta_gradient_create_multi_horizontal (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
/* render the first line */
for (i=1; i<count; i++)
@@ -534,30 +516,25 @@ meta_gradient_create_multi_horizontal (int width, int height,
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)width2;
for (j=0; j<width2; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
for (j=k; j<width; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
}
/* copy the first line to the other lines */
@@ -574,7 +551,7 @@ meta_gradient_create_multi_vertical (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr, *tmp, *pixels;
int height2;
@@ -583,7 +560,7 @@ meta_gradient_create_multi_vertical (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -604,38 +581,33 @@ meta_gradient_create_multi_vertical (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
for (i=1; i<count; i++)
{
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)height2;
for (j=0; j<height2; j++)
{
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
if (k<height)
@@ -645,11 +617,10 @@ meta_gradient_create_multi_vertical (int width, int height,
ptr[0] = (unsigned char) (r>>16);
ptr[1] = (unsigned char) (g>>16);
ptr[2] = (unsigned char) (b>>16);
ptr[3] = (unsigned char) (a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;

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