Compare commits

..

26 Commits

Author SHA1 Message Date
Florian Müllner
17185452c6 Bump version to 3.8.4
Update NEWS.
2013-07-30 17:40:24 -04:00
Ray Strode
534774a72f NEWS 2013-07-30 17:30:45 -04:00
Jasper St. Pierre
efefb40e70 background: Allow using sliced textures
https://bugzilla.gnome.org/show_bug.cgi?id=702283
2013-07-30 17:19:58 -04:00
Jasper St. Pierre
ca4e1fd4c9 window: Eliminate a potential race condition with _NET_WM_MOVERESIZE
Clients using _NET_WM_MOVERESIZE to start a drag operation may encounter
a race condition if the user presses and releases a mouse button very
fast, getting "stuck" in a grab state. While this is easily fixed with
the user pressing the button or hitting Escape as the EWMH spec suggests,
its's still a bit of annoyance for users.

After starting a grab operation, check that the button is actually pressed
by the client, and if not, cancel the grab operation. This prevents the
stuck grab in a race-free way, although it requires an extra round-trip
to the server.

With client-side decorations becoming more popular, the use of
_NET_WM_MOVERESIZE is on the rise, thus this bug is seen more frequently
than before.

https://bugzilla.gnome.org/show_bug.cgi?id=699777
2013-07-30 17:19:20 -04:00
Jasper St. Pierre
74fb5a83dd display: Ignore _NET_WM_USER_TIME PropertyNotifies
These are spammy as well.

https://bugzilla.gnome.org/show_bug.cgi?id=703970
2013-07-15 12:47:23 -04:00
Jasper St. Pierre
02ecca502e display: Ignore XSyncAlarmNotify in meta_spew_event
https://bugzilla.gnome.org/show_bug.cgi?id=703970
2013-07-15 12:47:22 -04:00
Jasper St. Pierre
e36eb3e91a main: Don't select for touch events on the stage
GNOME Shell's actors aren't touch capable, so we need to make sure that
they get the fallback pointer emulated events for now. This fixes the top
bar and other elements not working on a touchscreen without a grab.

https://bugzilla.gnome.org/show_bug.cgi?id=697192
2013-07-15 12:46:06 -04:00
Adel Gadllah
de6d9591c4 window: Make sure override_redirect window have correct monitor info
We need to update window->monitor on override_redirect windows as well, other
wise they may end up with an invalid struct which triggers and assert when
meta_window_is_monitor_sized is called.

https://bugzilla.gnome.org/show_bug.cgi?id=702564
2013-06-24 17:33:07 +02:00
Adel Gadllah
a20401782e window: Reuse current pointer position for monitor checks
Avoid a round trip to the xserver we already have the current position
anyway. Querying from the server on every move can cause the compositor to
stall during movement.
2013-06-23 21:25:18 +02:00
Adel Gadllah
79ea9f0b0f screen: Allow reusing the current position when quering the monitor
Add new api (meta_screen_get_current_monitor_for_pos and
meta_screen_get_current_monitor_info_for_pos) that allow querying the monitor
without a roundtrip by reusing the passed in cursor position.
2013-06-23 21:25:10 +02:00
Adel Gadllah
7b36dcf4a0 compositor: Prevent an error in application code from keeping unredirect on permanently
We substract one from the unredirect counter when enable_unredirect_for_screen
gets called. It is an unsigned integer so substracting one from zero (which means enable) would overflow and thus keep it peramently enabled.

This should never happen because it means there is an unmatched
enable / disable pair somewhere. So in addition to fixing it add a
warning when this case gets triggered.

https://bugzilla.gnome.org/show_bug.cgi?id=701224
2013-06-18 22:19:53 +02:00
Florian Müllner
edfde6221f Bump version to 3.8.3
Update NEWS.
2013-06-07 20:40:50 +02:00
Owen W. Taylor
1ad1357745 Use new clutter_stage_set_paint_callback() function for after-paint notification
Commit 4f2bb583bf changed things so that the compositor used
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT
to get after-paint notification and send _NET_WM_FRAME_DRAWN, but this
doesn't actually work, since Clutter will already have blocked for
VBlank before calling post-paint functions.

The result is that frame synced toolkits like GTK 3.8 will normally
only be able to draw every other frame.

Since ::paint doesn't work either, a new function
clutter_stage_set_paint_callback() has been added to Clutter
(and will be included in the 1.14 branch)

https://bugzilla.gnome.org/show_bug.cgi?id=698794
2013-06-03 13:22:33 -04:00
Rui Matos
fb0999a1a9 keybindings: Make sure events are always reported to the grab window
We have no need for normally reported events during grabs. In fact, it
might be harmful. A plugin might grab the keyboard through
meta_begin_modal_for_plugin() and then expect events to be reported to
the grab window they provide. If meanwhile this XIGrabDevice is
issued, events might start being reported normally to one other of our
windows breaking the plugin event processing.

In particular, on an empty workspace, we set input focus to our
no_focus_window. Then, if gnome-shell calls
meta_begin_modal_for_plugin() and meta_display_freeze_keyboard(), in
that order, input events will start being reported to no_focus_window.

There are two issues with this. One is that no_focus_window isn't
selecting for XI input events and thus the server discards them
completely. But even if that is fixed, events being reported to any
window other than the one gnome-shell expects - the clutter stage
window - means that events will stop reaching it.

https://bugzilla.gnome.org/show_bug.cgi?id=701219
2013-05-29 21:46:52 +02:00
Rui Matos
7186ddff49 keybindings: Grab and emit a signal when XK_ISO_Next_Group is pressed
This will make it possible to implement input source switching in
gnome-shell using the popular modifiers-only keybinding that's
implemented on the X server through an XKB option.

https://bugzilla.gnome.org/show_bug.cgi?id=697002
2013-05-20 15:41:00 +02:00
Rui Matos
d664cfcc90 prefs: Track the XKB 'grp:' option in gsettings as a keybinding pref
We'll use the value of this option to establish a passive grab on the
keycode/modifier combos generating XK_ISO_Next_Group.

https://bugzilla.gnome.org/show_bug.cgi?id=697002
2013-05-20 15:41:00 +02:00
Rui Matos
056cc16b82 keybindings: Add API to freeze/unfreeze the keyboard
We'll use this in gnome-shell to freeze the keyboard right before
switching input source and unfreeze it after that's finished so that
we don't lose any key events to the wrong input source.

https://bugzilla.gnome.org/show_bug.cgi?id=697001
2013-05-20 15:41:00 +02:00
Stef Walter
6c4bcecc00 compositor: Fix regression of shaded windows
Fix issues drawing shaded window shadows.

https://bugzilla.gnome.org/show_bug.cgi?id=693714
2013-05-15 16:45:15 +02:00
Florian Müllner
f531960b6a prefs: Add support for string-array preferences
As we only had one string-array preference so far, we didn't bother
with adding a generic way to handle string-array preferences, and
just handled the preference in question explicitly. However we are
going to parse another string-array setting, so generalize the
existing code to make it reusable for that case.

https://bugzilla.gnome.org/show_bug.cgi?id=700223
2013-05-15 12:44:24 +02:00
Florian Müllner
e15792c983 Bump version to 3.8.2
Update NEWS.
2013-05-14 00:35:34 +02:00
Rui Matos
1627044c39 prefs: Fix binding remaining grabbed after clearing all strokes
If a binding is updated with a clear set of strokes (effectively
disabling it) we aren't signaling that the binding changed and thus
the previous strokes will continue to be grabbed.

This fixes that and tries to do a better effort at checking if the
binding changed or not.

https://bugzilla.gnome.org/show_bug.cgi?id=697000
2013-05-14 00:25:12 +02:00
Kjartan Maraas
5615e36112 Updated Norwegian bokmål translation 2013-05-13 10:30:13 +02:00
Pavel Vasin
2c210e0e25 window: Add missing chain-up for finalize()
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 15:56:03 +02:00
Pavel Vasin
1c06f0dc09 background: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 15:56:02 +02:00
Pavel Vasin
51d98be1f2 barrier: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 15:56:00 +02:00
Stef Walter
859d231129 Fix use of uninitialized variables
If mutter is going to -Werror by default, then it can play footloose
and fancy free with this sorta stuff.

https://bugzilla.gnome.org/show_bug.cgi?id=698179
2013-04-17 10:04:49 +02:00
123 changed files with 7497 additions and 17109 deletions

12
.gitignore vendored
View File

@@ -23,7 +23,7 @@ src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter-wm.desktop
src/mutter-wayland.desktop
src/mutter.desktop
*.o
*.a
*.lo
@@ -46,10 +46,11 @@ POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter-wayland.pc
mutter-wayland
inlinepixbufs.h
libmutter.pc
mutter
mutter-theme-viewer
mutter-wayland.desktop
mutter.desktop
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
testasyncgetprop
@@ -61,7 +62,6 @@ mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
@@ -74,8 +74,6 @@ src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/meta-dbus-idle-monitor.[ch]
src/mutter-plugins.pc
doc/reference/*.args
doc/reference/*.bak

View File

@@ -1,5 +1,5 @@
SUBDIRS=src protocol data po doc
SUBDIRS=src po doc
EXTRA_DIST = HACKING MAINTAINERS rationales.txt

91
NEWS
View File

@@ -1,87 +1,38 @@
3.9.90
======
* First release from the wayland branch, includes basic support for running
as a wayland compositor [Robert, Neil, Giovanni]
* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766]
* Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101]
* Work towards running as wayland compositor [Giovanni]
- Add DBus API for display configuration
[#705670, #706231, #706233, #706322, #706382]
- Add abstraction layer for cursor tracking [#705911]
- Add support for plugin modality under wayland [#705917]
* Disable GTK+ scaling [Alexander; #706388]
* Disable blending while updating tower [Robert]
* Misc bug fixes and cleanups [Adel, Jasper, Giovanni, Colin, Rico, Florian;
#703332, #704437, #706207]
3.8.4
=====
* Workaround failure to bring back shell interface after fullscreen game in some situations [Adel; #701224]
* Fix sluggish and stuck pointers moving windows [Adel, Jasper: #699777]
* Reduce log spew [Adel, Jasper; #702564, #703970]
* Touch screen fixes [Jasper: #697192]
* Fix rendering of large background images [Jasper, Ray: #702283]
Contributors:
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts,
Rico Tzschichholz, Colin Walters
Adel Gadllah, Jasper St. Pierre, Ray Strode
Translations:
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl],
Marek Černocký [cs], Daniel Mustieles [es], Rafael Ferreira [pt_BR],
Yaron Shahrabani [he], Ján Kyselica [sk]
3.9.5
=====
* Don't select for touch events on the stage [Jasper; #697192]
* Don't queue redraws for obscured regions [Adel; #703332]
* Export timestamp of global keybinding events [Bastien; #704858]
* Misc bug fixes and cleanups [Jasper, Rico; #703970]
Contributors:
Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
3.9.4
=====
* Tweak window shadows [Allan; #702141]
* Ignore our own focus events for focus prediction [Jasper; #701017]
* Add API to query if the stage is focused [Jasper; #700735]
* Add API to query the monitor for a given position [Adel]
* Don't force attached dialogs to be border-only [Florian; #702764]
* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283]
* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564]
Contributors:
Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode
3.9.3
3.8.3
=====
* Add support for string-array preferences [Florian; #700223]
* Fix shade window action [Stef; #693714]
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
* Ensure events are always reported to the grab window [Rui; #701219]
* Use new clutter_stage_set_paint_callback() function to prevent dropping
frames with frame synced toolkits [Owen; #698794]
Contributors:
Rui Matos, Owen W. Taylor
Rui Matos, Florian Müllner, Stef Walter, Owen W. Taylor
3.9.2
=====
* Add meta_window_can_close() function [Jasper; #699269]
* Add support for string-array preferences [Florian; #700223]
* Fix a potential race condition with _NET_WM_MOVERESIZE [Jasper; #699777]
* Fix shade window action [Stef; #693714]
* Remove overlay_group [Giovanni; #700735]
* Improve tracking of the focus window [Dan, Jasper; #647706]
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
* Misc bug fixes and cleanups [Dieter, Jasper, Rui; #699636, #700735, #697000]
Contributors:
Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre,
Dieter Verfaillie, Stef Walter, Dan Winship
Translations:
Kjartan Maraas [nb], Ján Kyselica [sk]
3.9.1
3.8.2
=====
* Fix miscellaneous memory leaks [Pavel; #698710]
* Misc fixes and cleanups [Stef, Simon; #698179, #697758]
* Fix binding remaining grabbed after clearing all strokes [Rui; #697000]
* Misc fixes [Stef; #698179]
Contributors:
Simon McVittie, Pavel Vasin, Stef Walter
Rui Matos, Pavel Vasin, Stef Walter
Translations:
Kjartan Maraas [nb]
3.8.1
=====

View File

@@ -5,7 +5,7 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="mutter"
REQUIRED_AUTOMAKE_VERSION=1.13
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {

View File

@@ -1,8 +1,8 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [9])
m4_define([mutter_micro_version], [90])
m4_define([mutter_minor_version], [8])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -15,14 +15,10 @@ AC_INIT([mutter], [mutter_version],
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable])
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
PACKAGE="mutter-wayland"
AC_SUBST([PACKAGE], [$PACKAGE])
MUTTER_MAJOR_VERSION=mutter_major_version
MUTTER_MINOR_VERSION=mutter_minor_version
MUTTER_MICRO_VERSION=mutter_micro_version
@@ -38,7 +34,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
# Honor aclocal flags
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
GETTEXT_PACKAGE=mutter-wayland
GETTEXT_PACKAGE=mutter
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
@@ -79,8 +75,6 @@ MUTTER_PC_MODULES="
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.14.3
cogl-1.0 >= 1.13.3
upower-glib > 0.9.11
gnome-desktop-3.0
"
GLIB_GSETTINGS
@@ -119,26 +113,14 @@ AC_ARG_ENABLE(shape,
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
## Wayland support requires the xserver.xml protocol extension found in the weston
## repository but since there aren't currently established conventions for
## installing and discovering these we simply require a location to be given
## explicitly...
AC_ARG_WITH([wayland-protocols],
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
[
],
[])
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xorg"])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# gtk_window_set_icon_name requires gtk2+-2.6.0
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -217,16 +199,6 @@ if test x$have_xcursor = xyes; then
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
fi
# We always build with wayland enabled
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES wayland-server"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
@@ -335,6 +307,9 @@ if test "x$found_xsync" = "xyes"; then
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
case "$MUTTER_LIBS" in
@@ -464,10 +439,11 @@ doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/libmutter-wayland.pc
src/wm-tester/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/tools/Makefile
src/compositor/plugins/Makefile
protocol/Makefile
data/Makefile
po/Makefile.in
])
@@ -483,7 +459,7 @@ fi
dnl ==========================================================================
echo "
mutter-wayland-$VERSION
mutter-$VERSION
prefix: ${prefix}
source code location: ${srcdir}

View File

@@ -1,3 +0,0 @@
defaultcursordir = $(pkgdatadir)/cursors
dist_defaultcursor_DATA = left_ptr.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 B

View File

@@ -140,7 +140,7 @@ expand_content_files= \
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

@@ -409,6 +409,7 @@ meta_prefs_get_theme
meta_prefs_get_titlebar_font
meta_prefs_get_num_workspaces
meta_prefs_get_dynamic_workspaces
meta_prefs_get_application_based
meta_prefs_get_disable_workarounds
meta_prefs_get_auto_raise
meta_prefs_get_auto_raise_delay

View File

@@ -12,7 +12,6 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
@@ -24,9 +23,12 @@ src/core/xprops.c
src/mutter.desktop.in
src/mutter-wm.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/tools/mutter-message.c
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/ui/theme-viewer.c

View File

@@ -12,8 +12,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-07-30 12:29+0000\n"
"PO-Revision-Date: 2013-07-30 23:01+0900\n"
"POT-Creation-Date: 2013-03-22 10:02+0000\n"
"PO-Revision-Date: 2013-03-25 17:02+0000\n"
"Last-Translator: Jiro Matsuzawa <jmatsuzawa@gnome.org>\n"
"Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n"
"Language: ja\n"
@@ -133,7 +133,7 @@ msgstr "コマンド実行プロンプトを表示する"
#: ../src/50-mutter-system.xml.in.h:3
msgid "Show the activities overview"
msgstr "アクティビティ画面を表示する"
msgstr "アクティビティを表示する"
#: ../src/50-mutter-windows.xml.in.h:1
msgid "Windows"
@@ -213,12 +213,12 @@ msgstr "画面右半分に表示する"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:568
#, c-format
msgid "Another compositing manager is already running on screen %i on display \"%s\"."
msgstr "既に別の合成マネージャーがディスプレイ \"%2$s\" 上のスクリーン %1$i で起動中です"
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1191
msgid "background texture could not be created from file"
msgstr ""
@@ -252,22 +252,22 @@ msgstr "待機する(_W)"
msgid "_Force Quit"
msgstr "強制終了する(_F)"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "ウィンドウの合成に必要な %s という拡張モジュールが存在しません"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "X Window System のディスプレイ '%s' のオープンに失敗しました\n"
#: ../src/core/keybindings.c:1138
#: ../src/core/keybindings.c:935
#, c-format
msgid "Some other program is already using the key %s with modifiers %x as a binding\n"
msgstr "既にバインディングとして別のプログラムでキー %s (修飾キー %x) を使っています\n"
#: ../src/core/keybindings.c:1335
#: ../src/core/keybindings.c:1135
#, fuzzy, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" はフォーカス属性のためには有効な値ではありません"
@@ -328,26 +328,26 @@ msgstr "バージョンを表示する"
msgid "Mutter plugin to use"
msgstr "使用する Mutter のプラグイン"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1095
msgid "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
msgstr "仕様に準拠していないアプリケーションに対する次善策は無効になっています。一部のアプリケーションは正常に動作しない可能性があります\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "GSettings の %2$s キーからフォント名 \"%1$s\" を解析できませんでした\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1236
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for mouse button modifier\n"
msgstr "設定データベース中の \"%s\" はマウスボタンの修飾キーとして妥当な値ではありません\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1788
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
msgstr "設定データベース中の \"%s\" はキーバインド \"%s\" に有効な値ではありません\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "ワークスペース %d"
@@ -465,7 +465,7 @@ msgid "Window manager error: "
msgstr "ウィンドウマネージャーのエラー: "
#. first time through
#: ../src/core/window.c:7513
#: ../src/core/window.c:7596
#, c-format
msgid "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"
msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT_LEADER ウィンドウの代わりに自分自身で SM_CLIENT_ID を設定しています\n"
@@ -477,7 +477,7 @@ msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8237
#: ../src/core/window.c:8320
#, c-format
msgid "Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr "ウィンドウ %s はリサイズ可能ではない MWM ヒント指示を設定していますが、最小サイズ %d x %d と最大サイズ %d x %dも設定しています。これはあまり意味がありません\n"

View File

@@ -4,10 +4,10 @@
#
msgid ""
msgstr ""
"Project-Id-Version: mutter 3.9.x\n"
"Project-Id-Version: mutter 3.8.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-08 22:14+0200\n"
"PO-Revision-Date: 2013-05-28 09:48+0200\n"
"POT-Creation-Date: 2013-05-13 10:30+0200\n"
"PO-Revision-Date: 2013-04-03 14:11+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
"Language: \n"
@@ -205,7 +205,7 @@ msgstr "Visning delt til høyre"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:568
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@@ -250,17 +250,17 @@ msgstr "_Vent"
msgid "_Force Quit"
msgstr "_Tvungen nedstenging"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Mangler utvidelsen %s som kreves for komposittfunksjon"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
#: ../src/core/keybindings.c:1138
#: ../src/core/keybindings.c:970
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@@ -269,7 +269,7 @@ msgstr ""
"Et annet program bruker allerede nøkkelen %s med modifikatorer %x som "
"binding\n"
#: ../src/core/keybindings.c:1335
#: ../src/core/keybindings.c:1151
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "«%s» er ikke en gyldig aksellerator\n"
@@ -333,7 +333,7 @@ msgstr "Skriv versjonsnummer"
msgid "Mutter plugin to use"
msgstr "Mutter-tillegg som skal brukes"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1095
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@@ -341,12 +341,12 @@ msgstr ""
"Funksjonalitet for å gå rundt ødelagte programmer er deaktivert. Noen "
"programmer vil kanskje ikke oppføre seg korrekt.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Kunne ikke tolke skriftbeskrivelsen «%s» fra GSettings-nøkkel %s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1236
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@@ -355,7 +355,7 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for endring av "
"musknapp\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1789
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@@ -364,7 +364,7 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for "
"tastaturbinding «%s»\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1888
#, c-format
msgid "Workspace %d"
msgstr "Arbeidsområde %d"
@@ -492,7 +492,7 @@ msgid "Window manager error: "
msgstr "Feil i vindushåndterer: "
#. first time through
#: ../src/core/window.c:7513
#: ../src/core/window.c:7598
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@@ -508,7 +508,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8237
#: ../src/core/window.c:8322
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "

480
po/sk.po

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
EXTRA_DIST = xserver.xml

View File

@@ -1,18 +0,0 @@
<protocol name="xserver">
<interface name="xserver" version="1">
<request name="set_window_id">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="uint"/>
</request>
<event name="client">
<arg name="fd" type="fd"/>
</event>
<event name="listen_socket">
<arg name="fd" type="fd"/>
</event>
</interface>
</protocol>

View File

@@ -1,16 +1,15 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter-wayland.la
lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
SUBDIRS=wm-tester tools compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
-I$(top_builddir) \
-I$(srcdir) \
-I$(srcdir)/core \
-I$(srcdir)/ui \
@@ -30,21 +29,11 @@ INCLUDES= \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
INCLUDES += \
-I$(srcdir)/wayland \
-I$(builddir)/wayland \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
wayland/xserver-protocol.c \
wayland/xserver-server-protocol.h \
wayland/xserver-client-protocol.h
mutter-enum-types.h \
mutter-enum-types.c
libmutter_wayland_la_SOURCES = \
libmutter_la_SOURCES = \
core/async-getprop.c \
core/async-getprop.h \
core/barrier.c \
@@ -73,7 +62,6 @@ libmutter_wayland_la_SOURCES = \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture-private.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -106,8 +94,6 @@ libmutter_wayland_la_SOURCES = \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
core/edid.h \
core/errors.c \
meta/errors.h \
core/frame.c \
@@ -124,15 +110,6 @@ libmutter_wayland_la_SOURCES = \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/meta-cursor-tracker.c \
core/meta-cursor-tracker-private.h \
core/meta-idle-monitor.c \
core/meta-idle-monitor-private.h \
core/meta-xrandr-shared.h \
core/monitor.c \
core/monitor-config.c \
core/monitor-private.h \
core/monitor-xrandr.c \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
@@ -162,6 +139,7 @@ libmutter_wayland_la_SOURCES = \
meta/common.h \
core/core.h \
ui/ui.h \
inlinepixbufs.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
@@ -179,26 +157,12 @@ libmutter_wayland_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
meta/preview-widget.h \
ui/preview-widget.c \
$(mutter_built_sources)
libmutter_wayland_la_SOURCES += \
wayland/meta-wayland.c \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-stage.h \
wayland/meta-wayland-stage.c
libmutter_wayland_la_LDFLAGS = -no-undefined
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
@@ -217,8 +181,6 @@ libmutterinclude_base_headers = \
meta/meta-background-actor.h \
meta/meta-background-group.h \
meta/meta-background.h \
meta/meta-cursor-tracker.h \
meta/meta-idle-monitor.h \
meta/meta-plugin.h \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
@@ -234,18 +196,22 @@ libmutterinclude_base_headers = \
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/preview-widget.h \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter-wayland/meta
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
bin_PROGRAMS=mutter-wayland
mutter_theme_viewer_SOURCES= \
ui/theme-viewer.c
mutter_wayland_SOURCES = core/mutter.c
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
bin_PROGRAMS=mutter mutter-theme-viewer
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@@ -267,36 +233,43 @@ typelib_DATA = Meta-$(api_version).typelib
INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter-wayland.la
Meta-$(api_version).gir: libmutter.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
@META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter-wayland.la
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_wayland_la_SOURCES))
$(filter %.c,$(libmutter_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
@INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter-wayland.desktop.in
desktopfiles_in_files=mutter.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
wmpropertiesdir=$(datadir)/gnome/wm-properties
wmproperties_in_files=mutter-wm.desktop.in
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
wmproperties_DATA = $(wmproperties_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
@@ -304,8 +277,6 @@ xml_in_files = \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
@@ -313,8 +284,15 @@ gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
stock_minimize_data $(srcdir)/stock_minimize.png \
stock_delete_data $(srcdir)/stock_delete.png
BUILT_SOURCES = inlinepixbufs.h
CLEANFILES = \
mutter-wayland.desktop \
inlinepixbufs.h \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
$(xml_DATA) \
@@ -322,9 +300,12 @@ CLEANFILES = \
$(typelib_DATA) \
$(gir_DATA)
inlinepixbufs.h: $(IMAGES)
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter-wayland.pc
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
@@ -334,11 +315,12 @@ EXTRA_DIST=$(desktopfiles_files) \
$(xml_in_files) \
org.gnome.mutter.gschema.xml.in \
mutter-schemas.convert \
libmutter-wayland.pc.in \
libmutter.pc.in \
mutter-plugins.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in
BUILT_SOURCES = $(mutter_built_sources)
BUILT_SOURCES += $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
@@ -360,32 +342,3 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-idle-monitor \
--c-generate-object-manager \
$(srcdir)/idle-monitor.xml
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@

View File

@@ -66,6 +66,8 @@ void meta_switch_workspace_completed (MetaScreen *screen);
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaScreen *screen,

View File

@@ -53,15 +53,17 @@
*
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
* There's three containers in the stage that can be used to place actors, here
* are listed in the order in which they are painted:
*
* - window group, accessible with meta_get_window_group_for_screen()
* - top window group, accessible with meta_get_top_window_group_for_screen()
* - overlay group, accessible with meta_get_overlay_group_for_screen()
*
* Mutter will place actors representing windows in the window group, except for
* override-redirect windows (ie. popups and menus) which will be placed in the
* top window group.
* top window group. Mutter won't put any actors in the overlay group, but it's
* intended for compositors to place there panel, dashes, status bars, etc.
*/
#include <config.h>
@@ -84,7 +86,6 @@
#include "meta-window-group.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "meta-wayland-private.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@@ -173,7 +174,7 @@ process_damage (MetaCompositor *compositor,
if (window_actor == NULL)
return;
meta_window_actor_process_x11_damage (window_actor, event);
meta_window_actor_process_damage (window_actor, event);
}
static void
@@ -254,6 +255,23 @@ meta_get_stage_for_screen (MetaScreen *screen)
return info->stage;
}
/**
* meta_get_overlay_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The overlay group corresponding to @screen
*/
ClutterActor *
meta_get_overlay_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->overlay_group;
}
/**
* meta_get_window_group_for_screen:
* @screen: a #MetaScreen
@@ -328,37 +346,29 @@ void
meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
/* As a wayland compositor we can simply ignore all this trickery
* for setting an input region on the stage for capturing events in
* clutter since all input comes to us first and we get to choose
* who else sees them.
*/
if (!meta_is_wayland_compositor ())
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
if (info->stage && info->output)
{
do_set_stage_input_region (screen, region);
}
else
{
/* Reset info->pending_input_region if one existed before and set the new
* one to use it later. */
if (info->pending_input_region)
{
XFixesDestroyRegion (xdpy, info->pending_input_region);
info->pending_input_region = None;
}
if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
if (info->stage && info->output)
{
do_set_stage_input_region (screen, region);
}
else
{
/* Reset info->pending_input_region if one existed before and set the new
* one to use it later. */
if (info->pending_input_region)
{
XFixesDestroyRegion (xdpy, info->pending_input_region);
info->pending_input_region = None;
}
if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
}
void
@@ -378,55 +388,11 @@ meta_empty_stage_input_region (MetaScreen *screen)
meta_set_stage_input_region (screen, region);
}
void
meta_focus_stage_window (MetaScreen *screen,
guint32 timestamp)
{
ClutterStage *stage;
Window window;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return;
if (!meta_is_wayland_compositor ())
{
window = clutter_x11_get_stage_window (stage);
if (window == None)
return;
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
window,
timestamp);
}
else
{
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
None,
timestamp);
}
}
gboolean
meta_stage_is_focused (MetaScreen *screen)
{
ClutterStage *stage;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
return (screen->display->focus_type == META_FOCUS_STAGE);
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
@@ -437,19 +403,10 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
ClutterStage *stage;
Window grab_window;
Cursor cursor = None;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
grab_window = clutter_x11_get_stage_window (stage);
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
@@ -584,11 +541,6 @@ redirect_windows (MetaCompositor *compositor,
guint n_retries;
guint max_retries;
/* If we're running with wayland, connected to a headless xwayland
* server then all the windows are implicitly redirected offscreen
* already and it would generate an error to try and explicitly
* redirect them via XCompositeRedirectSubwindows() */
if (meta_get_replace_current_wm ())
max_retries = 5;
else
@@ -631,7 +583,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwin;
gint width, height;
MetaWaylandCompositor *wayland_compositor;
/* Check if the screen is already managed */
if (meta_screen_get_compositor_data (screen))
@@ -644,14 +595,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
* We have to initialize info->pending_input_region to an empty region explicitly,
* because None value is used to mean that the whole screen is an input region.
*/
if (!meta_is_wayland_compositor ())
info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
else
{
/* Stage input region trickery isn't needed when we're running as a
* wayland compositor. */
info->pending_input_region = None;
}
info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
info->screen = screen;
@@ -662,56 +606,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
meta_screen_set_cm_selection (screen);
/* We will have already created a stage if running as a wayland
* compositor... */
if (meta_is_wayland_compositor ())
{
wayland_compositor = meta_wayland_compositor_get_default ();
info->stage = wayland_compositor->stage;
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (info->stage, width, height);
}
else
{
info->stage = clutter_stage_new ();
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (info->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
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, 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 (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xwin, event_mask);
}
}
info->stage = clutter_stage_new ();
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
after_stage_paint,
@@ -720,74 +615,101 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (info->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
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, 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 (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xwin, event_mask);
}
info->window_group = meta_window_group_new (screen);
info->top_window_group = meta_window_group_new (screen);
info->overlay_group = clutter_actor_new ();
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
clutter_actor_add_child (info->stage, info->overlay_group);
info->plugin_mgr = meta_plugin_manager_new (screen);
if (meta_is_wayland_compositor ())
/*
* Delay the creation of the overlay window as long as we can, to avoid
* blanking out the screen. This means that during the plugin loading, the
* overlay window is not accessible; if the plugin needs to access it
* directly, it should hook into the "show" signal on stage, and do
* its stuff there.
*/
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
*
* Note: there doesn't seem to be any real chance of that
* because the X server will destroy the overlay window
* when the last client using it exits.
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
do_set_stage_input_region (screen, info->pending_input_region);
if (info->pending_input_region != None)
{
/* NB: When running as a wayland compositor we don't need an X
* composite overlay window, and we don't need to play any input
* region tricks to redirect events into clutter. */
info->output = None;
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
else
{
/*
* Delay the creation of the overlay window as long as we can, to avoid
* blanking out the screen. This means that during the plugin loading, the
* overlay window is not accessible; if the plugin needs to access it
* directly, it should hook into the "show" signal on stage, and do
* its stuff there.
*/
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
*
* Note: there doesn't seem to be any real chance of that
* because the X server will destroy the overlay window
* when the last client using it exits.
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
clutter_actor_show (info->overlay_group);
do_set_stage_input_region (screen, info->pending_input_region);
if (info->pending_input_region != None)
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
redirect_windows (compositor, screen);
}
redirect_windows (compositor, screen);
}
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen)
{
if (!meta_is_wayland_compositor ())
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
/* This is the most important part of cleanup - we have to do this
* before giving up the window manager selection or the next
* window manager won't be able to redirect subwindows */
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
}
/* This is the most important part of cleanup - we have to do this
* before giving up the window manager selection or the next
* window manager won't be able to redirect subwindows */
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
}
/*
@@ -859,18 +781,15 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (!window_actor)
return;
if (!meta_is_wayland_compositor ())
{
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (window_actor == info->unredirected_window)
{
meta_window_actor_set_redirected (window_actor, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
info->unredirected_window = NULL;
}
if (window_actor == info->unredirected_window)
{
meta_window_actor_set_redirected (window_actor, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
info->unredirected_window = NULL;
}
meta_window_actor_destroy (window_actor);
@@ -1057,8 +976,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
break;
default:
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
@@ -1077,7 +995,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
/* Clutter needs to know about MapNotify events otherwise it will
think the stage is invisible */
if (!meta_is_wayland_compositor () && event->type == MapNotify)
if (event->type == MapNotify)
clutter_x11_handle_event (event);
/* The above handling is basically just "observing" the events, so we return
@@ -1421,38 +1339,20 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Display *xdisplay;
Window xwin;
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.
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
g_return_if_fail (info);
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.
*/
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
clutter_actor_set_size (info->stage, width, height);
}
else
{
Display *xdisplay;
Window xwin;
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
g_return_if_fail (info);
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
}
XResizeWindow (xdisplay, xwin, width, height);
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen),
width, height);
meta_screen_get_screen_number (screen),
width, height);
}
static void
@@ -1516,32 +1416,29 @@ pre_paint_windows (MetaCompScreen *info)
if (info->windows == NULL)
return;
if (!meta_is_wayland_compositor ())
top_window = g_list_last (info->windows)->data;
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
expected_unredirected_window = top_window;
if (info->unredirected_window != expected_unredirected_window)
{
top_window = g_list_last (info->windows)->data;
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
expected_unredirected_window = top_window;
if (info->unredirected_window != expected_unredirected_window)
if (info->unredirected_window != NULL)
{
if (info->unredirected_window != NULL)
{
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
}
if (expected_unredirected_window != NULL)
{
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
meta_window_actor_get_meta_window (top_window));
meta_window_actor_set_redirected (top_window, FALSE);
}
info->unredirected_window = expected_unredirected_window;
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
}
if (expected_unredirected_window != NULL)
{
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
meta_window_actor_get_meta_window (top_window));
meta_window_actor_set_redirected (top_window, FALSE);
}
info->unredirected_window = expected_unredirected_window;
}
for (l = info->windows; l; l = l->next)

View File

@@ -891,7 +891,7 @@ meta_background_load_gradient (MetaBackground *self,
pixels[7] = second_color->alpha;
texture = cogl_texture_new_from_data (width, height,
COGL_TEXTURE_NO_SLICING,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888,
COGL_PIXEL_FORMAT_ANY,
4,
@@ -1031,6 +1031,7 @@ meta_background_load_file_finish (MetaBackground *self,
GAsyncResult *result,
GError **error)
{
static CoglUserDataKey key;
GTask *task;
LoadFileTaskData *task_data;
CoglTexture *texture;
@@ -1059,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NO_ATLAS,
COGL_TEXTURE_NO_SLICING,
has_alpha ?
COGL_PIXEL_FORMAT_RGBA_8888 :
COGL_PIXEL_FORMAT_RGB_888,
@@ -1076,6 +1077,12 @@ meta_background_load_file_finish (MetaBackground *self,
goto out;
}
cogl_object_set_user_data (COGL_OBJECT (texture),
&key,
g_object_ref (pixbuf),
(CoglUserDataDestroyCallback)
g_object_unref);
ensure_pipeline (self);
unset_texture (self);
set_style (self, task_data->style);

View File

@@ -85,20 +85,12 @@ meta_plugin_manager_load (const gchar *plugin_name)
g_free (path);
}
static void
on_confirm_display_change (MetaMonitorManager *monitors,
MetaPluginManager *plugin_mgr)
{
meta_plugin_manager_confirm_display_change (plugin_mgr);
}
MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
MetaPluginClass *klass;
MetaPlugin *plugin;
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
@@ -109,10 +101,6 @@ meta_plugin_manager_new (MetaScreen *screen)
if (klass->start)
klass->start (plugin);
monitors = meta_monitor_manager_get ();
g_signal_connect (monitors, "confirm-display-change",
G_CALLBACK (on_confirm_display_change), plugin_mgr);
return plugin_mgr;
}
@@ -329,28 +317,6 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
*/
if (klass->xevent_filter)
return klass->xevent_filter (plugin, xev);
/* When mutter is running as a wayland compositor, things like input
* events just come directly from clutter so it won't have disabled
* clutter's event retrieval and won't need to forward it events (if
* it did it would lead to recursion). Also when running as a
* wayland compositor we shouldn't be assuming that we're running
* with the clutter x11 backend.
*/
if (meta_is_wayland_compositor ())
return FALSE;
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
}
void
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->confirm_display_change)
return klass->confirm_display_change (plugin);
else
return meta_plugin_complete_display_change (plugin, TRUE);
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
}

View File

@@ -73,6 +73,4 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
XEvent *xev);
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
#endif

View File

@@ -41,7 +41,6 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "monitor-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
@@ -267,6 +266,10 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
/**
* meta_plugin_begin_modal:
* @plugin: a #MetaPlugin
* @grab_window: the X window to grab the keyboard and mouse on
* @cursor: the cursor to use for the pointer grab, or None,
* to use the normal cursor for the grab window and
* its descendants.
* @options: flags that modify the behavior of the modal grab
* @timestamp: the timestamp used for establishing grabs
*
@@ -287,13 +290,15 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
*/
gboolean
meta_plugin_begin_modal (MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_begin_modal_for_plugin (priv->screen, plugin,
options, timestamp);
grab_window, cursor, options, timestamp);
}
/**
@@ -333,13 +338,3 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen;
}
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok)
{
MetaMonitorManager *manager;
manager = meta_monitor_manager_get ();
meta_monitor_manager_confirm_configuration (manager, ok);
}

View File

@@ -123,12 +123,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
/* The first element in this array also defines the default parameters
* for newly created classes */
MetaShadowClassInfo default_shadow_classes[] = {
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "normal", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "dialog", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "modal_dialog", { 6, -1, 0, 1, 255 }, { 3, -1, 0, 3, 128 } },
{ "utility", { 3, -1, 0, 1, 255 }, { 3, -1, 0, 1, 128 } },
{ "border", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "menu", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 0, 128 } },
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },

View File

@@ -1,44 +0,0 @@
/*
* shaped texture
*
* An actor to draw a texture clipped to a list of rectangles
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2008 Intel Corporation
* 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_SHAPED_TEXTURE_PRIVATE_H__
#define __META_SHAPED_TEXTURE_PRIVATE_H__
#include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h"
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface);
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface);
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap);
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer);
#endif

View File

@@ -30,13 +30,8 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include <meta/util.h>
#include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <cogl/cogl-texture-pixmap-x11.h>
@@ -60,13 +55,6 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
typedef enum _MetaShapedTextureType
{
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
} MetaShapedTextureType;
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_TYPE_ACTOR);
@@ -77,24 +65,13 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
MetaShapedTextureType type;
union {
struct {
Pixmap pixmap;
} x11;
struct {
MetaWaylandSurface *surface;
} wayland;
};
CoglTexture *texture;
Pixmap pixmap;
CoglTexturePixmapX11 *texture;
CoglTexture *mask_texture;
CoglPipeline *pipeline;
CoglPipeline *pipeline_unshaped;
cairo_region_t *clip_region;
cairo_region_t *input_shape_region;
cairo_region_t *opaque_region;
guint tex_width, tex_height;
@@ -126,10 +103,7 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->paint_tower = meta_texture_tower_new ();
priv->type = META_SHAPED_TEXTURE_TYPE_X11_PIXMAP;
priv->texture = NULL;
priv->mask_texture = NULL;
priv->create_mipmaps = TRUE;
}
@@ -144,6 +118,8 @@ meta_shaped_texture_dispose (GObject *object)
meta_texture_tower_free (priv->paint_tower);
priv->paint_tower = NULL;
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
g_clear_pointer (&priv->texture, cogl_object_unref);
meta_shaped_texture_set_mask_texture (self, NULL);
@@ -152,133 +128,19 @@ meta_shaped_texture_dispose (GObject *object)
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static CoglPipeline *
get_unmasked_pipeline (CoglContext *ctx)
{
return cogl_pipeline_new (ctx);
}
static CoglPipeline *
get_masked_pipeline (CoglContext *ctx)
{
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_combine (template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
return cogl_pipeline_copy (template);
}
static CoglPipeline *
get_unblended_pipeline (CoglContext *ctx)
{
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
CoglColor color;
template = cogl_pipeline_new (ctx);
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
cogl_pipeline_set_blend (template,
"RGBA = ADD (SRC_COLOR, 0)",
NULL);
cogl_pipeline_set_color (template, &color);
}
return cogl_pipeline_copy (template);
}
static void
paint_clipped_rectangle (CoglFramebuffer *fb,
CoglPipeline *pipeline,
cairo_rectangle_int_t *rect,
ClutterActorBox *alloc)
{
float coords[8];
float x1, y1, x2, y2;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
coords[0] = rect->x / (alloc->x2 - alloc->x1);
coords[1] = rect->y / (alloc->y2 - alloc->y1);
coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
x1, y1, x2, y2,
&coords[0], 8);
}
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex)
{
MetaShapedTexturePrivate *priv;
guint width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->texture)
cogl_object_unref (priv->texture);
priv->texture = cogl_tex;
if (cogl_tex != NULL)
{
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
{
/* size changed to 0 going to an invalid handle */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
/* NB: We don't queue a redraw of the actor here because we don't
* know how much of the buffer has changed with respect to the
* previous buffer. We only queue a redraw in response to surface
* damage. */
}
static void
meta_shaped_texture_paint (ClutterActor *actor)
{
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
guint tex_width, tex_height;
guchar opacity;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglPipeline *pipeline = NULL;
CoglTexture *paint_tex;
guint tex_width, tex_height;
ClutterActorBox alloc;
cairo_region_t *blended_region = NULL;
static CoglPipeline *pipeline_template = NULL;
static CoglPipeline *pipeline_unshaped_template = NULL;
CoglPipeline *pipeline;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
@@ -315,67 +177,38 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->opaque_region != NULL && opacity == 255)
{
CoglPipeline *opaque_pipeline;
cairo_region_t *region;
int n_rects;
int i;
region = cairo_region_copy (priv->clip_region);
cairo_region_intersect (region, priv->opaque_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);
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);
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);
}
if (blended_region == NULL && priv->clip_region != NULL)
blended_region = cairo_region_reference (priv->clip_region);
if (blended_region != NULL && cairo_region_is_empty (blended_region))
goto out;
if (priv->mask_texture == NULL)
{
pipeline = get_unmasked_pipeline (ctx);
/* Use a single-layer texture if we don't have a mask. */
if (priv->pipeline_unshaped == NULL)
{
if (G_UNLIKELY (pipeline_unshaped_template == NULL))
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
pipeline_unshaped_template = cogl_pipeline_new (ctx);
}
priv->pipeline_unshaped = cogl_pipeline_copy (pipeline_unshaped_template);
}
pipeline = priv->pipeline_unshaped;
}
else
{
pipeline = get_masked_pipeline (ctx);
if (priv->pipeline == NULL)
{
if (G_UNLIKELY (pipeline_template == NULL))
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_combine (pipeline_template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
priv->pipeline = cogl_pipeline_copy (pipeline_template);
}
pipeline = priv->pipeline;
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
}
@@ -383,13 +216,20 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
guchar opacity = clutter_actor_get_paint_opacity (actor);
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (pipeline, &color);
}
if (blended_region != NULL)
cogl_set_source (pipeline);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->clip_region)
{
int n_rects;
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
@@ -398,8 +238,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
n_rects = cairo_region_num_rectangles (priv->clip_region);
if (n_rects <= MAX_RECTS)
{
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
float coords[8];
float x1, y1, x2, y2;
for (i = 0; i < n_rects; i++)
{
@@ -410,23 +250,32 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
x1 = rect.x;
y1 = rect.y;
x2 = rect.x + rect.width;
y2 = rect.y + rect.height;
coords[0] = rect.x / (alloc.x2 - alloc.x1);
coords[1] = rect.y / (alloc.y2 - alloc.y1);
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
&coords[0], 8);
}
goto out;
return;
}
}
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);
cogl_rectangle (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
static void
@@ -436,62 +285,38 @@ meta_shaped_texture_pick (ClutterActor *actor,
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
if (!clutter_actor_should_pick_paint (actor) ||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
return;
/* If there is no region then use the regular pick */
if (priv->input_shape_region == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
else
if (priv->mask_texture == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
{
int n_rects;
float *rectangles;
int i;
CoglTexture *paint_tex;
ClutterActorBox alloc;
CoglPipeline *pipeline;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglColor cogl_color;
guint tex_width, tex_height;
/* Note: We don't bother trying to intersect the pick and clip regions
* since needing to copy the region, do the intersection, and probably
* increase the number of rectangles seems more likely to have a negative
* effect.
*
* NB: Most of the time when just using rectangles for picking then
* picking shouldn't involve any rendering, and minimizing the number of
* rectangles has more benefit than reducing the area of the pick
* region.
*/
paint_tex = COGL_TEXTURE (priv->texture);
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
if (paint_tex == NULL)
return;
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
int pos = i * 4;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
rectangles[pos] = rect.x;
rectangles[pos + 1] = rect.y;
rectangles[pos + 2] = rect.x + rect.width;
rectangles[pos + 3] = rect.y + rect.height;
}
cogl_set_source_color4ub (color->red, color->green, color->blue,
color->alpha);
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
clutter_actor_get_allocation_box (actor, &alloc);
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color (pipeline, &cogl_color);
cogl_framebuffer_draw_rectangles (fb, pipeline,
rectangles, n_rects);
cogl_object_unref (pipeline);
/* Paint the mask rectangle in the given color */
cogl_set_source_texture (priv->mask_texture);
cogl_rectangle_with_texture_coords (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1,
0, 0, 1, 1);
}
}
@@ -541,45 +366,11 @@ meta_shaped_texture_get_paint_volume (ClutterActor *self,
}
ClutterActor *
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
meta_shaped_texture_new (void)
{
ClutterActor *actor = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (actor)->priv;
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
/* XXX: it could probably be better to have a "type" construct-only
* property or create wayland/x11 subclasses */
priv->type = META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE;
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (actor),
surface);
return actor;
}
void
meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface)
{
MetaShapedTexturePrivate *priv = stex->priv;
priv->wayland.surface = surface;
if (surface && surface->buffer_ref.buffer)
meta_shaped_texture_attach_wayland_buffer (stex,
surface->buffer_ref.buffer);
}
MetaWaylandSurface *
meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
return priv->wayland.surface;
}
ClutterActor *
meta_shaped_texture_new_with_xwindow (Window xwindow)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
return self;
}
void
@@ -598,7 +389,8 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
{
CoglTexture *base_texture;
priv->create_mipmaps = create_mipmaps;
base_texture = create_mipmaps ? priv->texture : NULL;
base_texture = create_mipmaps ?
COGL_TEXTURE (priv->texture) : NULL;
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
}
}
@@ -624,142 +416,74 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
static void
wayland_surface_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
{
MetaShapedTexturePrivate *priv;
MetaWaylandBuffer *buffer;
priv = stex->priv;
g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE);
g_return_if_fail (priv->texture != NULL);
buffer = priv->wayland.surface->buffer_ref.buffer;
if (buffer)
{
struct wl_resource *resource = buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglPixelFormat format;
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888;
break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888;
break;
#endif
default:
g_warn_if_reached ();
format = COGL_PIXEL_FORMAT_ARGB_8888;
}
cogl_texture_set_region (priv->texture,
x, y,
x, y,
width, height,
width, height,
format,
wl_shm_buffer_get_stride (shm_buffer),
wl_shm_buffer_get_data (shm_buffer));
}
}
}
static void
queue_damage_redraw_with_clip (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
{
ClutterActor *self = CLUTTER_ACTOR (stex);
MetaShapedTexturePrivate *priv;
ClutterActorBox allocation;
float scale_x;
float scale_y;
cairo_rectangle_int_t clip;
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's
* coordinate space so we need to convert from surface coordinates to
* actor coordinates...
*/
/* Calling clutter_actor_get_allocation_box() is enormously expensive
* if the actor has an out-of-date allocation, since it triggers
* a full redraw. clutter_actor_queue_redraw_with_clip() would redraw
* the whole stage anyways in that case, so just go ahead and do
* it here.
*/
if (!clutter_actor_has_allocation (self))
{
clutter_actor_queue_redraw (self);
return;
}
priv = stex->priv;
if (priv->tex_width == 0 || priv->tex_height == 0)
return;
clutter_actor_get_allocation_box (self, &allocation);
scale_x = (allocation.x2 - allocation.x1) / priv->tex_width;
scale_y = (allocation.y2 - allocation.y1) / priv->tex_height;
clip.x = x * scale_x;
clip.y = y * scale_y;
clip.width = width * scale_x;
clip.height = height * scale_y;
clutter_actor_queue_redraw_with_clip (self, &clip);
}
void
meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
int x,
int y,
int width,
int height)
{
MetaShapedTexturePrivate *priv;
const cairo_rectangle_int_t clip = { x, y, width, height };
priv = stex->priv;
if (priv->texture == NULL)
return;
switch (priv->type)
{
case META_SHAPED_TEXTURE_TYPE_X11_PIXMAP:
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
x, y, width, height);
break;
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
wayland_surface_update_area (stex, x, y, width, height);
break;
}
cogl_texture_pixmap_x11_update_area (priv->texture,
x, y, width, height);
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
queue_damage_redraw_with_clip (stex, x, y, width, height);
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
}
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexturePixmapX11 *cogl_tex)
{
MetaShapedTexturePrivate *priv;
guint width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->texture != NULL)
cogl_object_unref (priv->texture);
priv->texture = cogl_tex;
if (priv->pipeline != NULL)
cogl_pipeline_set_layer_texture (priv->pipeline, 0, COGL_TEXTURE (cogl_tex));
if (priv->pipeline_unshaped != NULL)
cogl_pipeline_set_layer_texture (priv->pipeline_unshaped, 0, COGL_TEXTURE (cogl_tex));
if (cogl_tex != NULL)
{
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
{
/* size changed to 0 going to an inavlid texture */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
@@ -777,64 +501,16 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
priv = stex->priv;
if (priv->x11.pixmap == pixmap)
if (priv->pixmap == pixmap)
return;
priv->x11.pixmap = pixmap;
priv->pixmap = pixmap;
if (pixmap != None)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglTexture *texture =
COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
set_cogl_texture (stex, texture);
}
else
set_cogl_texture (stex, NULL);
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower,
COGL_TEXTURE (priv->texture));
}
void
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
/* TODO: we should change this api to be something like
* meta_shaped_texture_notify_buffer_attach() since we now maintain
* a reference to the MetaWaylandSurface where we can access the
* buffer without it being explicitly passed as an argument.
*/
g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
if (buffer)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglError *catch_error = NULL;
CoglTexture *texture =
COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
buffer->resource,
&catch_error));
if (!texture)
{
cogl_error_free (catch_error);
}
else
{
buffer->width = cogl_texture_get_width (texture);
buffer->height = cogl_texture_get_height (texture);
}
set_cogl_texture (stex, texture);
set_cogl_texture (stex, cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
}
else
set_cogl_texture (stex, NULL);
@@ -857,41 +533,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
return COGL_TEXTURE (stex->priv->texture);
}
/**
* meta_shaped_texture_set_input_shape_region:
* @stex: a #MetaShapedTexture
* @shape_region: the region of the texture that should respond to
* input.
*
* Determines what region of the texture should accept input. For
* X based windows this is defined by the ShapeInput region of the
* window.
*/
void
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
cairo_region_t *shape_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->input_shape_region != NULL)
{
cairo_region_destroy (priv->input_shape_region);
priv->input_shape_region = NULL;
}
if (shape_region != NULL)
{
cairo_region_reference (shape_region);
priv->input_shape_region = shape_region;
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* meta_shaped_texture_set_clip_region:
* @stex: a #MetaShapedTexture
@@ -928,36 +569,6 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
priv->clip_region = NULL;
}
/**
* meta_shaped_texture_set_opaque_region:
* @stex: a #MetaShapedTexture
* @opaque_region: (transfer full): the region of the texture that
* can have blending turned off.
*
* As most windows have a large portion that does not require blending,
* we can easily turn off blending if we know the areas that do not
* require blending. This sets the region where we will not blend for
* optimization purposes.
*/
void
meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
cairo_region_t *opaque_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->opaque_region)
cairo_region_destroy (priv->opaque_region);
if (opaque_region)
priv->opaque_region = cairo_region_reference (opaque_region);
else
priv->opaque_region = NULL;
}
/**
* meta_shaped_texture_get_image:
* @stex: A #MetaShapedTexture

View File

@@ -5,9 +5,6 @@
#include <config.h>
#include <wayland-server.h>
#include <meta-wayland-private.h>
#include <X11/extensions/Xdamage.h>
#include <meta/compositor-mutter.h>
@@ -27,18 +24,8 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
int x,
int y,
int width,
int height);
void meta_window_actor_set_wayland_surface (MetaWindowActor *self,
MetaWaylandSurface *surface);
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
MetaWaylandBuffer *buffer);
void meta_window_actor_process_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_pre_paint (MetaWindowActor *self);
void meta_window_actor_post_paint (MetaWindowActor *self);

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,6 @@
#include "meta-window-group.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include "window-private.h"
struct _MetaWindowGroupClass
{
@@ -92,15 +91,14 @@ meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *visible_region;
ClutterActor *stage;
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect;
GList *children, *l;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
MetaCompScreen *info;
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
/* Normally we expect an actor to be drawn at it's position on the screen.
* However, if we're inside the paint of a ClutterClone, that won't be the
@@ -125,6 +123,13 @@ meta_window_group_paint (ClutterActor *actor)
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
children = clutter_actor_get_children (actor);
children = g_list_reverse (children);
/* Get the clipped redraw bounds from Clutter so that we can avoid
* painting shadows on windows that don't need to be painted in this
* frame. In the case of a multihead setup with mismatched monitor
@@ -137,32 +142,21 @@ meta_window_group_paint (ClutterActor *actor)
visible_region = cairo_region_create_rectangle (&visible_rect);
if (!meta_is_wayland_compositor ())
if (info->unredirected_window != NULL)
{
info = meta_screen_get_compositor_data (window_group->screen);
if (info->unredirected_window != NULL)
{
cairo_rectangle_int_t unredirected_rect;
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
cairo_rectangle_int_t unredirected_rect;
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
}
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
}
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
for (l = children; l; l = l->next)
{
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
continue;
if (!meta_is_wayland_compositor () &&
info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
if (l->data == info->unredirected_window)
continue;
/* If an actor has effects applied, then that can change the area
@@ -181,12 +175,12 @@ meta_window_group_paint (ClutterActor *actor)
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (child))
if (clutter_actor_has_effects (l->data))
continue;
if (META_IS_WINDOW_ACTOR (child))
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
MetaWindowActor *window_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
@@ -210,12 +204,13 @@ meta_window_group_paint (ClutterActor *actor)
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
else if (META_IS_BACKGROUND_ACTOR (l->data) ||
META_IS_BACKGROUND_GROUP (l->data))
{
ClutterActor *background_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (child, &x, &y))
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
continue;
x += paint_x_offset;
@@ -223,10 +218,10 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_translate (visible_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
if (META_IS_BACKGROUND_GROUP (background_actor))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
else
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
cairo_region_translate (visible_region, x, y);
}
}
@@ -238,20 +233,21 @@ meta_window_group_paint (ClutterActor *actor)
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
for (l = children; l; l = l->next)
{
if (META_IS_WINDOW_ACTOR (child))
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
MetaWindowActor *window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (child))
else if (META_IS_BACKGROUND_ACTOR (l->data))
{
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, NULL);
}
}
g_list_free (children);
}
static gboolean

View File

@@ -24,8 +24,6 @@
#include <meta/meta-plugin.h>
#include <meta/window.h>
#include <meta/util.h>
#include <meta/meta-background-group.h>
#include <meta/meta-background-actor.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
@@ -100,8 +98,6 @@ static void kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *actor);
static void kill_switch_workspace (MetaPlugin *plugin);
static void confirm_display_change (MetaPlugin *plugin);
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
@@ -117,8 +113,6 @@ struct _MetaDefaultPluginPrivate
ClutterActor *desktop1;
ClutterActor *desktop2;
ClutterActor *background_group;
MetaPluginInfo info;
};
@@ -209,7 +203,6 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
plugin_class->plugin_info = plugin_info;
plugin_class->kill_window_effects = kill_window_effects;
plugin_class->kill_switch_workspace = kill_switch_workspace;
plugin_class->confirm_display_change = confirm_display_change;
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
}
@@ -306,58 +299,9 @@ show_stage (MetaPlugin *plugin)
return FALSE;
}
static void
on_monitors_changed (MetaScreen *screen,
MetaPlugin *plugin)
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
int i, n;
clutter_actor_destroy_all_children (self->priv->background_group);
n = meta_screen_get_n_monitors (screen);
for (i = 0; i < n; i++)
{
MetaRectangle rect;
ClutterActor *background;
ClutterColor color;
meta_screen_get_monitor_geometry (screen, i, &rect);
background = meta_background_actor_new ();
clutter_actor_set_position (background, rect.x, rect.y);
clutter_actor_set_size (background, rect.width, rect.height);
/* Don't use rand() here, mesa calls srand() internally when
parsing the driconf XML, but it's nice if the colors are
reproducible.
*/
clutter_color_init (&color,
g_random_int () % 255,
g_random_int () % 255,
g_random_int () % 255,
255);
clutter_actor_set_background_color (background, &color);
clutter_actor_add_child (self->priv->background_group, background);
}
}
static void
start (MetaPlugin *plugin)
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
MetaScreen *screen = meta_plugin_get_screen (plugin);
self->priv->background_group = meta_background_group_new ();
clutter_actor_insert_child_below (meta_get_window_group_for_screen (screen),
self->priv->background_group, NULL);
g_signal_connect (screen, "monitors-changed",
G_CALLBACK (on_monitors_changed), plugin);
on_monitors_changed (screen, plugin);
meta_later_add (META_LATER_BEFORE_REDRAW,
(GSourceFunc) show_stage,
plugin,
@@ -838,33 +782,3 @@ plugin_info (MetaPlugin *plugin)
return &priv->info;
}
static void
on_dialog_closed (GPid pid,
gint status,
gpointer user_data)
{
MetaPlugin *plugin = user_data;
gboolean ok;
ok = g_spawn_check_exit_status (status, NULL);
meta_plugin_complete_display_change (plugin, ok);
}
static void
confirm_display_change (MetaPlugin *plugin)
{
GPid pid;
pid = meta_show_dialog ("--question",
"Does the display look OK?",
"20",
NULL,
"_Keep This Configuration",
"_Restore Previous Configuration",
"preferences-desktop-display",
0,
NULL, NULL);
g_child_watch_add (pid, on_dialog_closed, plugin);
}

View File

@@ -269,8 +269,6 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
MetaDisplay *display;
MetaScreen *screen;
MetaWindow *grab_window;
MetaStackWindow stack_window;
MetaStackWindow stack_sibling;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, xwindow);
@@ -283,13 +281,9 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
changes.sibling = grab_window->frame ? grab_window->frame->xwindow
: grab_window->xwindow;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_sibling.x11.xwindow = changes.sibling;
meta_stack_tracker_record_lower_below (screen->stack_tracker,
&stack_window,
&stack_sibling,
xwindow,
changes.sibling,
XNextRequest (screen->display->xdisplay));
meta_error_trap_push (display);

View File

@@ -86,14 +86,6 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
typedef enum {
META_FOCUS_NONE = 0,
META_FOCUS_X_CLIENT = 1,
META_FOCUS_WAYLAND_CLIENT = 2,
META_FOCUS_NO_FOCUS_WINDOW = 3,
META_FOCUS_STAGE = 4
} MetaFocusType;
struct _MetaDisplay
{
GObject parent_instance;
@@ -111,21 +103,19 @@ struct _MetaDisplay
#include <meta/atomnames.h>
#undef item
/* The window and serial of the most recent FocusIn event. */
Window server_focus_window;
gulong server_focus_serial;
/* Our best guess as to the "currently" focused window (that is, the
* window that we expect will be focused at the point when the X
* server processes our next request), and the serial of the request
* or event that caused this.
/* This is the actual window from focus events,
* not the one we last set
*/
MetaWindow *focus_window;
/* For windows we've focused that don't necessarily have an X window,
* like the no_focus_window or the stage X window. */
Window focus_xwindow;
gulong focus_serial;
MetaFocusType focus_type;
/* window we are expecting a FocusIn event for or the current focus
* window if we are not expecting any FocusIn/FocusOut events; not
* perfect because applications can call XSetInputFocus directly.
* (It could also be messed up if a timestamp later than current
* time is sent to meta_display_set_input_focus_window, though that
* would be a programming error). See bug 154598 for more info.
*/
MetaWindow *expected_focus_window;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
@@ -469,25 +459,15 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp);
guint deviceid);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
gboolean meta_display_handle_event (MetaDisplay *display,
XEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp);
#endif

View File

@@ -53,7 +53,6 @@
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include "mutter-enum-types.h"
#include "meta-idle-monitor-private.h"
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@@ -75,8 +74,6 @@
#include <string.h>
#include <unistd.h>
#include "meta-xwayland-private.h"
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
@@ -257,7 +254,7 @@ meta_display_class_init (MetaDisplayClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
/**
* MetaDisplay::modifiers-accelerator-activated:
@@ -518,9 +515,6 @@ meta_display_open (void)
return FALSE;
}
if (meta_is_wayland_compositor ())
meta_xwayland_complete_init ();
if (meta_is_syncing ())
XSynchronize (xdisplay, True);
@@ -545,9 +539,7 @@ meta_display_open (void)
the_display->autoraise_timeout_id = 0;
the_display->autoraise_window = NULL;
the_display->focus_window = NULL;
the_display->focus_serial = 0;
the_display->server_focus_window = None;
the_display->server_focus_serial = 0;
the_display->expected_focus_window = NULL;
the_display->grab_old_window_stacking = NULL;
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
@@ -937,24 +929,8 @@ meta_display_open (void)
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (meta_is_wayland_compositor ())
{
/* Instead of explicitly enumerating all windows during
* initialization, when we run as a wayland compositor we can rely on
* xwayland notifying us of all top level windows so we create
* MetaWindows when we get those notifications.
*
* We still want a guard window so we can avoid
* unmapping/withdrawing minimized windows for live
* thumbnails...
*/
if (screen->guard_window == None)
screen->guard_window =
meta_screen_create_guard_window (screen->display->xdisplay, screen);
}
else
meta_screen_manage_all_windows (screen);
meta_screen_manage_all_windows (screen);
tmp = tmp->next;
}
@@ -996,10 +972,8 @@ meta_display_open (void)
meta_error_trap_pop (the_display);
}
meta_idle_monitor_init_dbus ();
meta_display_ungrab (the_display);
meta_display_ungrab (the_display);
/* Done opening new display */
the_display->display_opening = FALSE;
@@ -1491,17 +1465,6 @@ meta_display_get_current_time (MetaDisplay *display)
return display->current_time;
}
static Bool
find_timestamp_predicate (Display *xdisplay,
XEvent *ev,
XPointer arg)
{
MetaDisplay *display = (MetaDisplay *) arg;
return (ev->type == PropertyNotify &&
ev->xproperty.atom == display->atom__MUTTER_TIMESTAMP_PING);
}
/* Get a timestamp, even if it means a roundtrip */
guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
@@ -1513,13 +1476,17 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
XEvent property_event;
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_TIMESTAMP_PING,
XA_STRING, 8, PropModeAppend, NULL, 0);
XIfEvent (display->xdisplay,
&property_event,
find_timestamp_predicate,
(XPointer) display);
/* Using the property XA_PRIMARY because it's safe; nothing
* would use it as a property. The type doesn't matter.
*/
XChangeProperty (display->xdisplay,
display->timestamp_pinging_window,
XA_PRIMARY, XA_STRING, 8,
PropModeAppend, NULL, 0);
XWindowEvent (display->xdisplay,
display->timestamp_pinging_window,
PropertyChangeMask,
&property_event);
timestamp = property_event.xproperty.time;
}
@@ -1685,12 +1652,12 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
* alternative mechanism works great.
*/
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
display->focus_window != NULL)
display->expected_focus_window != NULL)
{
meta_topic (META_DEBUG_FOCUS,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window\n",
display->focus_window->desc);
display->expected_focus_window->desc);
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
@@ -1904,285 +1871,11 @@ get_input_event (MetaDisplay *display,
return NULL;
}
static void
update_focus_window (MetaDisplay *display,
MetaFocusType type,
MetaWindow *window,
Window xwindow,
gulong serial)
{
MetaWaylandCompositor *compositor;
display->focus_serial = serial;
if (display->focus_xwindow == xwindow &&
display->focus_type == type &&
display->focus_window == window)
return;
if (display->focus_window)
{
MetaWindow *previous;
meta_topic (META_DEBUG_FOCUS,
"%s is now the previous focus window due to being focused out or unmapped\n",
display->focus_window->desc);
/* Make sure that signals handlers invoked by
* meta_window_set_focused_internal() don't see
* display->focus_window->has_focus == FALSE
*/
previous = display->focus_window;
display->focus_window = NULL;
display->focus_xwindow = None;
meta_window_set_focused_internal (previous, FALSE);
}
display->focus_type = type;
display->focus_window = window;
display->focus_xwindow = xwindow;
if (display->focus_window)
{
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
display->focus_window->desc, serial);
meta_window_set_focused_internal (display->focus_window, TRUE);
}
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
if (meta_is_wayland_compositor ())
{
compositor = meta_wayland_compositor_get_default ();
if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW ||
display->focus_type == META_FOCUS_STAGE)
meta_wayland_compositor_set_input_focus (compositor, NULL);
else if (window && window->surface)
meta_wayland_compositor_set_input_focus (compositor, window);
else
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
}
g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display);
}
static gboolean
timestamp_too_old (MetaDisplay *display,
guint32 *timestamp)
{
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
* us to sanity check the timestamp here and ensure it doesn't correspond to
* a future time (though we would want to rename to
* timestamp_too_old_or_in_future).
*/
if (*timestamp == CurrentTime)
{
*timestamp = meta_display_get_current_time_roundtrip (display);
return FALSE;
}
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
{
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
return TRUE;
else
{
*timestamp = display->last_focus_time;
return FALSE;
}
}
return FALSE;
}
static void
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
MetaWindow *meta_window,
Window xwindow,
guint32 timestamp)
{
gulong serial;
if (timestamp_too_old (display, &timestamp))
return;
meta_error_trap_push (display);
/* In order for mutter to know that the focus request succeeded, we track
* the serial of the "focus request" we made, but if we take the serial
* of the XSetInputFocus request, then there's no way to determine the
* difference between focus events as a result of the SetInputFocus and
* focus events that other clients send around the same time. Ensure that
* we know which is which by making two requests that the server will
* process at the same time.
*/
meta_display_grab (display);
serial = XNextRequest (display->xdisplay);
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
meta_display_ungrab (display);
update_focus_window (display,
type,
meta_window,
xwindow,
serial);
meta_error_trap_pop (display);
display->last_focus_time = timestamp;
display->active_screen = screen;
if (meta_window == NULL || meta_window != display->autoraise_window)
meta_display_remove_autoraise_callback (display);
}
static void
handle_window_focus_event (MetaDisplay *display,
MetaWindow *window,
XIEnterEvent *event,
unsigned long serial)
{
MetaWindow *focus_window;
MetaFocusType type;
#ifdef WITH_VERBOSE_MODE
const char *window_type;
type = META_FOCUS_NONE;
/* Note the event can be on either the window or the frame,
* we focus the frame for shaded windows
*/
if (window)
{
if (event->event == window->xwindow)
window_type = "client window";
else if (window->frame && event->event == window->frame->xwindow)
window_type = "frame window";
else
window_type = "unknown client window";
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
type = META_FOCUS_WAYLAND_CLIENT;
else
type = META_FOCUS_X_CLIENT;
}
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
{
window_type = "no_focus_window";
type = META_FOCUS_NO_FOCUS_WINDOW;
}
else if (meta_display_screen_for_root (display, event->event))
window_type = "root window";
else
window_type = "unknown window";
/* Don't change type if we don't know the new window */
if (type == META_FOCUS_NONE)
type = display->focus_type;
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on %s 0x%lx (%s) "
"mode %s detail %s serial %lu\n",
event->evtype == XI_FocusIn ? "in" :
event->evtype == XI_FocusOut ? "out" :
"???",
window ? window->desc : "",
event->event, window_type,
meta_event_mode_to_string (event->mode),
meta_event_detail_to_string (event->mode),
event->serial);
#endif
/* FIXME our pointer tracking is broken; see how
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
* for how to handle it the correct way. In brief you need to track
* pointer focus and regular focus, and handle EnterNotify in
* PointerRoot mode with no window manager. However as noted above,
* accurate focus tracking will break things because we want to keep
* windows "focused" when using keybindings on them, and also we
* sometimes "focus" a window by focusing its frame or
* no_focus_window; so this all needs rethinking massively.
*
* My suggestion is to change it so that we clearly separate
* actual keyboard focus tracking using the xterm algorithm,
* and mutter's "pretend" focus window, and go through all
* the code and decide which one should be used in each place;
* a hard bit is deciding on a policy for that.
*
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
*/
/* We ignore grabs, though this is questionable. It may be better to
* increase the intelligence of the focus window tracking.
*
* The problem is that keybindings for windows are done with
* XGrabKey, which means focus_window disappears and the front of
* the MRU list gets confused from what the user expects once a
* keybinding is used.
*/
if (event->mode == XINotifyGrab ||
event->mode == XINotifyUngrab ||
/* From WindowMaker, ignore all funky pointer root events */
event->detail > XINotifyNonlinearVirtual)
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus event generated by a grab or other weirdness\n");
return;
}
if (event->evtype == XI_FocusIn)
{
display->server_focus_window = event->event;
display->server_focus_serial = serial;
focus_window = window;
}
else if (event->evtype == XI_FocusOut)
{
if (event->detail == XINotifyInferior)
{
/* This event means the client moved focus to a subwindow */
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus out with NotifyInferior\n");
return;
}
display->server_focus_window = None;
display->server_focus_serial = serial;
focus_window = NULL;
}
else
g_return_if_reached ();
if (display->server_focus_serial > display->focus_serial)
{
update_focus_window (display,
type,
focus_window,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial);
}
}
/**
* meta_display_handle_event:
* @display: The MetaDisplay that events are coming from
* event_callback:
* @event: The event that just happened
* @data: The #MetaDisplay that events are coming from, cast to a gpointer
* so that it can be sent to a callback
*
* This is the most important function in the whole program. It is the heart,
* it is the nexus, it is the Grand Central Station of Mutter's world.
@@ -2192,20 +1885,21 @@ handle_window_focus_event (MetaDisplay *display,
* busy around here. Most of this function is a ginormous switch statement
* dealing with all the kinds of events that might turn up.
*/
gboolean
meta_display_handle_event (MetaDisplay *display,
XEvent *event)
static gboolean
event_callback (XEvent *event,
gpointer data)
{
MetaWindow *window;
MetaWindow *property_for_window;
MetaDisplay *display;
Window modified;
gboolean frame_was_receiver;
gboolean bypass_compositor;
gboolean filter_out_event;
XIEvent *input_event;
MetaMonitorManager *monitor;
MetaScreen *screen;
display = data;
#ifdef WITH_VERBOSE_MODE
if (dump_events)
meta_spew_event (display, event);
@@ -2214,40 +1908,12 @@ meta_display_handle_event (MetaDisplay *display,
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_process_event (display->sn_display, event);
#endif
/* Intercept XRandR events early and don't attempt any
processing for them. We still let them through to Gdk though,
so it can update its own internal state.
*/
monitor = meta_monitor_manager_get ();
if (meta_monitor_manager_handle_xevent (monitor, event))
return FALSE;
bypass_compositor = FALSE;
filter_out_event = FALSE;
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
{
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc);
update_focus_window (display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
}
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
{
if (meta_screen_handle_xevent (screen, event))
return TRUE;
}
modified = event_get_modified_window (display, event);
input_event = get_input_event (display, event);
@@ -2320,8 +1986,6 @@ meta_display_handle_event (MetaDisplay *display,
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
filter_out_event = TRUE; /* GTK doesn't want to see this really */
}
else
meta_idle_monitor_handle_xevent_all (event);
}
#endif /* HAVE_XSYNC */
@@ -2336,9 +2000,32 @@ meta_display_handle_event (MetaDisplay *display,
XShapeEvent *sev = (XShapeEvent*) event;
if (sev->kind == ShapeBounding)
meta_window_update_shape_region_x11 (window);
else if (sev->kind == ShapeInput)
meta_window_update_input_region_x11 (window);
{
if (sev->shaped && !window->has_shape)
{
window->has_shape = TRUE;
meta_topic (META_DEBUG_SHAPES,
"Window %s now has a shape\n",
window->desc);
}
else if (!sev->shaped && window->has_shape)
{
window->has_shape = FALSE;
meta_topic (META_DEBUG_SHAPES,
"Window %s no longer has a shape\n",
window->desc);
}
else
{
meta_topic (META_DEBUG_SHAPES,
"Window %s shape changed\n",
window->desc);
}
if (display->compositor)
meta_compositor_window_shape_changed (display->compositor,
window);
}
}
else
{
@@ -2546,12 +2233,30 @@ meta_display_handle_event (MetaDisplay *display,
/* This is from our synchronous grab since
* it has no modifiers and was on the client window
*/
int mode;
/* When clicking a different app in click-to-focus
* in application-based mode, and the different
* app is not a dock or desktop, eat the focus click.
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
meta_prefs_get_application_based () &&
!window->has_focus &&
window->type != META_WINDOW_DOCK &&
window->type != META_WINDOW_DESKTOP &&
(display->focus_window == NULL ||
!meta_window_same_application (window,
display->focus_window)))
mode = XIAsyncDevice; /* eat focus click */
else
mode = XIReplayDevice; /* give event back */
meta_verbose ("Allowing events time %u\n",
meta_verbose ("Allowing events mode %s time %u\n",
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
(unsigned int)device_event->time);
XIAllowEvents (display->xdisplay, device_event->deviceid,
XIReplayDevice, device_event->time);
mode, device_event->time);
}
if (begin_move && window->has_move_func)
@@ -2665,19 +2370,40 @@ meta_display_handle_event (MetaDisplay *display,
break;
case XI_FocusIn:
case XI_FocusOut:
/* libXi does not properly copy the serial to the XIEnterEvent, so pull it
* from the parent XAnyEvent.
* See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
*/
handle_window_focus_event (display, window, enter_event, event->xany.serial);
if (!window)
if (window)
{
meta_window_notify_focus (window, enter_event);
}
else if (meta_display_xwindow_is_a_no_focus_window (display,
enter_event->event))
{
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on no_focus_window 0x%lx "
"mode %s detail %s\n",
enter_event->evtype == XI_FocusIn ? "in" :
enter_event->evtype == XI_FocusOut ? "out" :
"???",
enter_event->event,
meta_event_mode_to_string (enter_event->mode),
meta_event_detail_to_string (enter_event->detail));
}
else
{
/* Check if the window is a root window. */
MetaScreen *screen =
meta_display_screen_for_root(display,
enter_event->event);
if (screen == NULL)
break;
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on root window 0x%lx "
"mode %s detail %s\n",
enter_event->evtype == XI_FocusIn ? "in" :
enter_event->evtype == XI_FocusOut ? "out" :
"???",
enter_event->event,
meta_event_mode_to_string (enter_event->mode),
meta_event_detail_to_string (enter_event->detail));
if (enter_event->evtype == XI_FocusIn &&
enter_event->mode == XINotifyDetailNone)
@@ -2815,6 +2541,13 @@ meta_display_handle_event (MetaDisplay *display,
window->unmaps_pending);
}
}
/* Unfocus on UnmapNotify, do this after the possible
* window_free above so that window_free can see if window->has_focus
* and move focus to another window
*/
if (window)
meta_window_lost_focus (window);
}
break;
case MapNotify:
@@ -2874,10 +2607,32 @@ meta_display_handle_event (MetaDisplay *display,
meta_stack_tracker_configure_event (screen->stack_tracker,
&event->xconfigure);
}
if (window && window->override_redirect)
meta_window_configure_notify (window, &event->xconfigure);
else
/* Handle screen resize */
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.window);
if (screen != NULL)
{
#ifdef HAVE_RANDR
/* do the resize the official way */
XRRUpdateConfiguration (event);
#else
/* poke around in Xlib */
screen->xscreen->width = event->xconfigure.width;
screen->xscreen->height = event->xconfigure.height;
#endif
meta_screen_resize (screen,
event->xconfigure.width,
event->xconfigure.height);
}
}
break;
case ConfigureRequest:
/* This comment and code is found in both twm and fvwm */
@@ -3072,6 +2827,27 @@ meta_display_handle_event (MetaDisplay *display,
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
}
}
else if (event->xclient.message_type ==
display->atom__MUTTER_RELOAD_THEME_MESSAGE)
{
meta_verbose ("Received reload theme request\n");
meta_ui_set_current_theme (meta_prefs_get_theme (),
TRUE);
meta_display_retheme_all ();
}
else if (event->xclient.message_type ==
display->atom__MUTTER_SET_KEYBINDINGS_MESSAGE)
{
meta_verbose ("Received set keybindings request = %d\n",
(int) event->xclient.data.l[0]);
meta_set_keybindings_disabled (!event->xclient.data.l[0]);
}
else if (event->xclient.message_type ==
display->atom__MUTTER_TOGGLE_VERBOSE)
{
meta_verbose ("Received toggle verbose message\n");
meta_set_verbose (!meta_is_verbose ());
}
else if (event->xclient.message_type ==
display->atom_WM_PROTOCOLS)
{
@@ -3168,30 +2944,6 @@ meta_display_handle_event (MetaDisplay *display,
return filter_out_event;
}
static gboolean
event_callback (XEvent *event,
gpointer data)
{
MetaDisplay *display = data;
/* Under Wayland we want to filter out mouse motion events so we can
synthesize them from the Clutter events instead. This is
necessary because the position in the mouse events is passed to
the X server relative to the position of the surface. The X
server then translates these back to screen coordinates based on
the window position. If we rely on this translatation when
dragging a window around then the window will jump around
erratically because of the lag between updating the window
position from the surface position. Instead we bypass the
translation altogether by directly using the Clutter events */
if (meta_is_wayland_compositor () &&
event->type == GenericEvent &&
event->xcookie.evtype == XI_Motion)
return FALSE;
return meta_display_handle_event (display, event);
}
/* Return the window this has to do with, if any, rather
* than the frame or root window that was selecting
* for substructure
@@ -5835,82 +5587,98 @@ sanity_check_timestamps (MetaDisplay *display,
}
}
static gboolean
timestamp_too_old (MetaDisplay *display,
MetaWindow *window,
guint32 *timestamp)
{
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
* us to sanity check the timestamp here and ensure it doesn't correspond to
* a future time (though we would want to rename to
* timestamp_too_old_or_in_future).
*/
if (*timestamp == CurrentTime)
{
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
"shouldn't happen!\n",
window ? window->desc : "the no_focus_window");
*timestamp = meta_display_get_current_time_roundtrip (display);
return FALSE;
}
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
{
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus request for %s since %u "
"is less than %u and %u.\n",
window ? window->desc : "the no_focus_window",
*timestamp,
display->last_user_time,
display->last_focus_time);
return TRUE;
}
else
{
meta_topic (META_DEBUG_FOCUS,
"Received focus request for %s which is newer than most "
"recent user_time, but less recent than "
"last_focus_time (%u < %u < %u); adjusting "
"accordingly. (See bug 167358)\n",
window ? window->desc : "the no_focus_window",
display->last_user_time,
*timestamp,
display->last_focus_time);
*timestamp = display->last_focus_time;
return FALSE;
}
}
return FALSE;
}
void
meta_display_set_input_focus_window (MetaDisplay *display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp)
{
request_xserver_input_focus_change (display,
window->screen,
window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ?
META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT,
window,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
void
meta_display_request_take_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp)
{
if (timestamp_too_old (display, &timestamp))
if (timestamp_too_old (display, window, &timestamp))
return;
meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
window->desc, timestamp);
meta_error_trap_push (display);
XSetInputFocus (display->xdisplay,
focus_frame ? window->frame->xwindow : window->xwindow,
RevertToPointerRoot,
timestamp);
meta_error_trap_pop (display);
if (window != display->focus_window)
{
/* The "Globally Active Input" window case, where the window
* doesn't want us to call XSetInputFocus on it, but does
* want us to send a WM_TAKE_FOCUS.
*
* We can't just set display->focus_window to @window, since we
* we don't know when (or even if) the window will actually take
* focus, so we could end up being wrong for arbitrarily long.
* But we also can't leave it set to the current window, or else
* bug #597352 would come back. So we focus the no_focus_window
* now (and set display->focus_window to that), send the
* WM_TAKE_FOCUS, and then just forget about @window
* until/unless we get a FocusIn.
*/
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
}
meta_window_send_icccm_message (window,
display->atom_WM_TAKE_FOCUS,
timestamp);
display->expected_focus_window = window;
display->last_focus_time = timestamp;
display->active_screen = window->screen;
if (window != display->autoraise_window)
meta_display_remove_autoraise_callback (window->display);
}
void
meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp)
{
request_xserver_input_focus_change (display,
screen,
type,
NULL,
window,
timestamp);
}
void
meta_display_focus_the_no_focus_window (MetaDisplay *display,
meta_display_focus_the_no_focus_window (MetaDisplay *display,
MetaScreen *screen,
guint32 timestamp)
{
request_xserver_input_focus_change (display,
screen,
META_FOCUS_NO_FOCUS_WINDOW,
NULL,
screen->no_focus_window,
timestamp);
if (timestamp_too_old (display, NULL, &timestamp))
return;
XSetInputFocus (display->xdisplay,
screen->no_focus_window,
RevertToPointerRoot,
timestamp);
display->expected_focus_window = NULL;
display->last_focus_time = timestamp;
display->active_screen = screen;
meta_display_remove_autoraise_callback (display);
}
void
@@ -5933,11 +5701,10 @@ meta_display_overlay_key_activate (MetaDisplay *display)
void
meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp)
guint deviceid)
{
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
0, action, deviceid, timestamp);
0, action, deviceid);
}
gboolean
@@ -6031,9 +5798,11 @@ meta_display_has_shape (MetaDisplay *display)
* meta_display_get_focus_window:
* @display: a #MetaDisplay
*
* Get our best guess as to the "currently" focused window (that is,
* the window that we expect will be focused at the point when the X
* server processes our next request).
* Get the window that, according to events received from X server,
* currently has the input focus. We may have already sent a request
* to the X server to move the focus window elsewhere. (The
* expected_focus_window records where we've last set the input
* focus.)
*
* Return Value: (transfer none): The current focus window
*/

View File

@@ -1,539 +0,0 @@
/*
* Copyright 2007 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Author: Soren Sandmann <sandmann@redhat.com> */
#include "edid.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <glib.h>
static int
get_bit (int in, int bit)
{
return (in & (1 << bit)) >> bit;
}
static int
get_bits (int in, int begin, int end)
{
int mask = (1 << (end - begin + 1)) - 1;
return (in >> begin) & mask;
}
static int
decode_header (const uchar *edid)
{
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
return TRUE;
return FALSE;
}
static int
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
{
int is_model_year;
/* Manufacturer Code */
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
info->manufacturer_code[3] = '\0';
info->manufacturer_code[0] += 'A' - 1;
info->manufacturer_code[1] += 'A' - 1;
info->manufacturer_code[2] += 'A' - 1;
/* Product Code */
info->product_code = edid[0x0b] << 8 | edid[0x0a];
/* Serial Number */
info->serial_number =
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
/* Week and Year */
is_model_year = FALSE;
switch (edid[0x10])
{
case 0x00:
info->production_week = -1;
break;
case 0xff:
info->production_week = -1;
is_model_year = TRUE;
break;
default:
info->production_week = edid[0x10];
break;
}
if (is_model_year)
{
info->production_year = -1;
info->model_year = 1990 + edid[0x11];
}
else
{
info->production_year = 1990 + edid[0x11];
info->model_year = -1;
}
return TRUE;
}
static int
decode_edid_version (const uchar *edid, MonitorInfo *info)
{
info->major_version = edid[0x12];
info->minor_version = edid[0x13];
return TRUE;
}
static int
decode_display_parameters (const uchar *edid, MonitorInfo *info)
{
/* Digital vs Analog */
info->is_digital = get_bit (edid[0x14], 7);
if (info->is_digital)
{
int bits;
static const int bit_depth[8] =
{
-1, 6, 8, 10, 12, 14, 16, -1
};
static const Interface interfaces[6] =
{
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
};
bits = get_bits (edid[0x14], 4, 6);
info->connector.digital.bits_per_primary = bit_depth[bits];
bits = get_bits (edid[0x14], 0, 3);
if (bits <= 5)
info->connector.digital.interface = interfaces[bits];
else
info->connector.digital.interface = UNDEFINED;
}
else
{
int bits = get_bits (edid[0x14], 5, 6);
static const double levels[][3] =
{
{ 0.7, 0.3, 1.0 },
{ 0.714, 0.286, 1.0 },
{ 1.0, 0.4, 1.4 },
{ 0.7, 0.0, 0.7 },
};
info->connector.analog.video_signal_level = levels[bits][0];
info->connector.analog.sync_signal_level = levels[bits][1];
info->connector.analog.total_signal_level = levels[bits][2];
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
}
/* Screen Size / Aspect Ratio */
if (edid[0x15] == 0 && edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = -1.0;
}
else if (edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
}
else if (edid[0x15] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
}
else
{
info->width_mm = 10 * edid[0x15];
info->height_mm = 10 * edid[0x16];
}
/* Gamma */
if (edid[0x17] == 0xFF)
info->gamma = -1.0;
else
info->gamma = (edid[0x17] + 100.0) / 100.0;
/* Features */
info->standby = get_bit (edid[0x18], 7);
info->suspend = get_bit (edid[0x18], 6);
info->active_off = get_bit (edid[0x18], 5);
if (info->is_digital)
{
info->connector.digital.rgb444 = TRUE;
if (get_bit (edid[0x18], 3))
info->connector.digital.ycrcb444 = 1;
if (get_bit (edid[0x18], 4))
info->connector.digital.ycrcb422 = 1;
}
else
{
int bits = get_bits (edid[0x18], 3, 4);
ColorType color_type[4] =
{
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
};
info->connector.analog.color_type = color_type[bits];
}
info->srgb_is_standard = get_bit (edid[0x18], 2);
/* In 1.3 this is called "has preferred timing" */
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
info->continuous_frequency = get_bit (edid[0x18], 0);
return TRUE;
}
static double
decode_fraction (int high, int low)
{
double result = 0.0;
int i;
high = (high << 2) | low;
for (i = 0; i < 10; ++i)
result += get_bit (high, i) * pow (2, i - 10);
return result;
}
static int
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
{
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
return TRUE;
}
static int
decode_established_timings (const uchar *edid, MonitorInfo *info)
{
static const Timing established[][8] =
{
{
{ 800, 600, 60 },
{ 800, 600, 56 },
{ 640, 480, 75 },
{ 640, 480, 72 },
{ 640, 480, 67 },
{ 640, 480, 60 },
{ 720, 400, 88 },
{ 720, 400, 70 }
},
{
{ 1280, 1024, 75 },
{ 1024, 768, 75 },
{ 1024, 768, 70 },
{ 1024, 768, 60 },
{ 1024, 768, 87 },
{ 832, 624, 75 },
{ 800, 600, 75 },
{ 800, 600, 72 }
},
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1152, 870, 75 }
},
};
int i, j, idx;
idx = 0;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 8; ++j)
{
int byte = edid[0x23 + i];
if (get_bit (byte, j) && established[i][j].frequency != 0)
info->established[idx++] = established[i][j];
}
}
return TRUE;
}
static int
decode_standard_timings (const uchar *edid, MonitorInfo *info)
{
int i;
for (i = 0; i < 8; i++)
{
int first = edid[0x26 + 2 * i];
int second = edid[0x27 + 2 * i];
if (first != 0x01 && second != 0x01)
{
int w = 8 * (first + 31);
int h = 0;
switch (get_bits (second, 6, 7))
{
case 0x00: h = (w / 16) * 10; break;
case 0x01: h = (w / 4) * 3; break;
case 0x02: h = (w / 5) * 4; break;
case 0x03: h = (w / 16) * 9; break;
}
info->standard[i].width = w;
info->standard[i].height = h;
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
}
}
return TRUE;
}
static void
decode_lf_string (const uchar *s, int n_chars, char *result)
{
int i;
for (i = 0; i < n_chars; ++i)
{
if (s[i] == 0x0a)
{
*result++ = '\0';
break;
}
else if (s[i] == 0x00)
{
/* Convert embedded 0's to spaces */
*result++ = ' ';
}
else
{
*result++ = s[i];
}
}
}
static void
decode_display_descriptor (const uchar *desc,
MonitorInfo *info)
{
switch (desc[0x03])
{
case 0xFC:
decode_lf_string (desc + 5, 13, info->dsc_product_name);
break;
case 0xFF:
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
break;
case 0xFE:
decode_lf_string (desc + 5, 13, info->dsc_string);
break;
case 0xFD:
/* Range Limits */
break;
case 0xFB:
/* Color Point */
break;
case 0xFA:
/* Timing Identifications */
break;
case 0xF9:
/* Color Management */
break;
case 0xF8:
/* Timing Codes */
break;
case 0xF7:
/* Established Timings */
break;
case 0x10:
break;
}
}
static void
decode_detailed_timing (const uchar *timing,
DetailedTiming *detailed)
{
int bits;
StereoType stereo[] =
{
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
};
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
detailed->v_front_porch =
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
detailed->v_sync =
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
detailed->right_border = timing[0x0f];
detailed->top_border = timing[0x10];
detailed->interlaced = get_bit (timing[0x11], 7);
/* Stereo */
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
detailed->stereo = stereo[bits];
/* Sync */
bits = timing[0x11];
detailed->digital_sync = get_bit (bits, 4);
if (detailed->digital_sync)
{
detailed->connector.digital.composite = !get_bit (bits, 3);
if (detailed->connector.digital.composite)
{
detailed->connector.digital.serrations = get_bit (bits, 2);
detailed->connector.digital.negative_vsync = FALSE;
}
else
{
detailed->connector.digital.serrations = FALSE;
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
}
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
}
else
{
detailed->connector.analog.bipolar = get_bit (bits, 3);
detailed->connector.analog.serrations = get_bit (bits, 2);
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
}
}
static int
decode_descriptors (const uchar *edid, MonitorInfo *info)
{
int i;
int timing_idx;
timing_idx = 0;
for (i = 0; i < 4; ++i)
{
int index = 0x36 + i * 18;
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
{
decode_display_descriptor (edid + index, info);
}
else
{
decode_detailed_timing (edid + index, &(info->detailed_timings[timing_idx++]));
}
}
info->n_detailed_timings = timing_idx;
return TRUE;
}
static void
decode_check_sum (const uchar *edid,
MonitorInfo *info)
{
int i;
uchar check = 0;
for (i = 0; i < 128; ++i)
check += edid[i];
info->checksum = check;
}
MonitorInfo *
decode_edid (const uchar *edid)
{
MonitorInfo *info = g_new0 (MonitorInfo, 1);
decode_check_sum (edid, info);
if (decode_header (edid)
&& decode_vendor_and_product_identification (edid, info)
&& decode_edid_version (edid, info)
&& decode_display_parameters (edid, info)
&& decode_color_characteristics (edid, info)
&& decode_established_timings (edid, info)
&& decode_standard_timings (edid, info)
&& decode_descriptors (edid, info))
{
return info;
}
else
{
g_free (info);
return NULL;
}
}

View File

@@ -1,195 +0,0 @@
/* edid.h
*
* Copyright 2007, 2008, Red Hat, Inc.
*
* This file is part of the Gnome Library.
*
* The Gnome Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The Gnome Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Gnome Library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* Author: Soren Sandmann <sandmann@redhat.com>
*/
#ifndef EDID_H
#define EDID_H
typedef unsigned char uchar;
typedef struct MonitorInfo MonitorInfo;
typedef struct Timing Timing;
typedef struct DetailedTiming DetailedTiming;
typedef enum
{
UNDEFINED,
DVI,
HDMI_A,
HDMI_B,
MDDI,
DISPLAY_PORT
} Interface;
typedef enum
{
UNDEFINED_COLOR,
MONOCHROME,
RGB,
OTHER_COLOR
} ColorType;
typedef enum
{
NO_STEREO,
FIELD_RIGHT,
FIELD_LEFT,
TWO_WAY_RIGHT_ON_EVEN,
TWO_WAY_LEFT_ON_EVEN,
FOUR_WAY_INTERLEAVED,
SIDE_BY_SIDE
} StereoType;
struct Timing
{
int width;
int height;
int frequency;
};
struct DetailedTiming
{
int pixel_clock;
int h_addr;
int h_blank;
int h_sync;
int h_front_porch;
int v_addr;
int v_blank;
int v_sync;
int v_front_porch;
int width_mm;
int height_mm;
int right_border;
int top_border;
int interlaced;
StereoType stereo;
int digital_sync;
union
{
struct
{
int bipolar;
int serrations;
int sync_on_green;
} analog;
struct
{
int composite;
int serrations;
int negative_vsync;
int negative_hsync;
} digital;
} connector;
};
struct MonitorInfo
{
int checksum;
char manufacturer_code[4];
int product_code;
unsigned int serial_number;
int production_week; /* -1 if not specified */
int production_year; /* -1 if not specified */
int model_year; /* -1 if not specified */
int major_version;
int minor_version;
int is_digital;
union
{
struct
{
int bits_per_primary;
Interface interface;
int rgb444;
int ycrcb444;
int ycrcb422;
} digital;
struct
{
double video_signal_level;
double sync_signal_level;
double total_signal_level;
int blank_to_black;
int separate_hv_sync;
int composite_sync_on_h;
int composite_sync_on_green;
int serration_on_vsync;
ColorType color_type;
} analog;
} connector;
int width_mm; /* -1 if not specified */
int height_mm; /* -1 if not specified */
double aspect_ratio; /* -1.0 if not specififed */
double gamma; /* -1.0 if not specified */
int standby;
int suspend;
int active_off;
int srgb_is_standard;
int preferred_timing_includes_native;
int continuous_frequency;
double red_x;
double red_y;
double green_x;
double green_y;
double blue_x;
double blue_y;
double white_x;
double white_y;
Timing established[24]; /* Terminated by 0x0x0 */
Timing standard[8];
int n_detailed_timings;
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
* mode, it is the first one
* (whether it has, is
* determined by the
* preferred_timing_includes
* bit.
*/
/* Optional product description */
char dsc_serial_number[14];
char dsc_product_name[14];
char dsc_string[14]; /* Unspecified ASCII data */
};
MonitorInfo *decode_edid (const uchar *data);
char *make_display_name (const MonitorInfo *info);
char *make_display_size_string (int width_mm, int height_mm);
#endif

View File

@@ -47,7 +47,6 @@ meta_window_ensure_frame (MetaWindow *window)
XSetWindowAttributes attrs;
Visual *visual;
gulong create_serial;
MetaStackWindow stack_window;
if (window->frame)
return;
@@ -106,10 +105,8 @@ meta_window_ensure_frame (MetaWindow *window)
frame->rect.height,
frame->window->screen->number,
&create_serial);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = frame->xwindow;
meta_stack_tracker_record_add (window->screen->stack_tracker,
&stack_window,
frame->xwindow,
create_serial);
meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
@@ -141,9 +138,8 @@ meta_window_ensure_frame (MetaWindow *window)
window->rect.x = 0;
window->rect.y = 0;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_remove (window->screen->stack_tracker,
&stack_window,
window->xwindow,
XNextRequest (window->display->xdisplay));
XReparentWindow (window->display->xdisplay,
window->xwindow,
@@ -178,7 +174,6 @@ meta_window_destroy_frame (MetaWindow *window)
{
MetaFrame *frame;
MetaFrameBorders borders;
MetaStackWindow stack_window;
if (window->frame == NULL)
return;
@@ -205,10 +200,8 @@ meta_window_destroy_frame (MetaWindow *window)
"Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
window->unmaps_pending += 1;
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_add (window->screen->stack_tracker,
&stack_window,
window->xwindow,
XNextRequest (window->display->xdisplay));
XReparentWindow (window->display->xdisplay,
window->xwindow,
@@ -339,6 +332,19 @@ meta_frame_calc_borders (MetaFrame *frame,
borders);
}
void
meta_frame_get_corner_radiuses (MetaFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
meta_ui_get_corner_radiuses (frame->window->screen->ui,
frame->xwindow,
top_left, top_right,
bottom_left, bottom_right);
}
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
@@ -394,14 +400,6 @@ meta_frame_get_frame_bounds (MetaFrame *frame)
frame->rect.height);
}
void
meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr)
{
meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
frame->rect.width, frame->rect.height, cr);
}
void
meta_frame_queue_draw (MetaFrame *frame)
{

View File

@@ -63,6 +63,12 @@ Window meta_frame_get_xwindow (MetaFrame *frame);
void meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders);
void meta_frame_get_corner_radiuses (MetaFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
gboolean meta_frame_sync_to_window (MetaFrame *frame,
int gravity,
gboolean need_move,
@@ -70,9 +76,6 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr);
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor);

View File

@@ -69,6 +69,7 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XIDeviceEvent *event);
void meta_set_keybindings_disabled (gboolean setting);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);

View File

@@ -56,6 +56,8 @@
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
static gboolean all_bindings_disabled = FALSE;
static gboolean add_builtin_keybinding (MetaDisplay *display,
const char *name,
GSettings *settings,
@@ -1310,7 +1312,7 @@ handle_external_grab (MetaDisplay *display,
guint action = meta_display_get_keybinding_action (display,
binding->keycode,
binding->mask);
meta_display_accelerator_activate (display, action, event->deviceid, event->time);
meta_display_accelerator_activate (display, action, event->deviceid);
}
@@ -1965,23 +1967,6 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
meta_display_overlay_key_activate (display);
}
else
{
/* In some rare race condition, mutter might not receive the Super_L
* KeyRelease event because:
* - the compositor might end the modal mode and call XIUngrabDevice
* while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease.
*
* In this case, display->overlay_key_only_pressed might be wrong.
* Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIAsyncDevice, event->time);
}
return TRUE;
}
@@ -2061,6 +2046,21 @@ meta_display_process_key_event (MetaDisplay *display,
const char *str;
MetaScreen *screen;
if (all_bindings_disabled)
{
/* In this mode, we try to pretend we don't have grabs, so we
* immediately replay events and drop the grab. (This still
* messes up global passive grabs from other clients.) The
* FALSE return here is a little suspect, but we don't really
* know if we'll see the event again or not, and it's pretty
* poorly defined how this mode is supposed to interact with
* plugins.
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIReplayDevice, event->time);
return FALSE;
}
/* if key event was on root window, we have a shortcut */
screen = meta_display_screen_for_root (display, event->event);
@@ -4098,6 +4098,14 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
void
meta_set_keybindings_disabled (gboolean setting)
{
all_bindings_disabled = setting;
meta_topic (META_DEBUG_KEYBINDINGS,
"Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
}
/**
* meta_keybindings_set_custom_handler:
* @name: The name of the keybinding to set

View File

@@ -55,7 +55,6 @@
#include "session.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#include "meta-wayland-private.h"
#include <glib-object.h>
#include <gdk/gdkx.h>
@@ -347,64 +346,28 @@ meta_finalize (void)
if (display)
meta_display_close (display,
CurrentTime); /* I doubt correct timestamps matter here */
if (meta_is_wayland_compositor ())
meta_wayland_finalize ();
}
static int signal_pipe_fds[2] = { -1, -1 };
static int sigterm_pipe_fds[2] = { -1, -1 };
static void
signal_handler (int signum)
sigterm_handler (int signum)
{
if (signal_pipe_fds[1] >= 0)
if (sigterm_pipe_fds[1] >= 0)
{
switch (signum)
{
case SIGTERM:
write (signal_pipe_fds[1], "T", 1);
break;
default:
break;
}
int G_GNUC_UNUSED dummy;
dummy = write (sigterm_pipe_fds[1], "", 1);
close (sigterm_pipe_fds[1]);
sigterm_pipe_fds[1] = -1;
}
}
static gboolean
on_signal (GIOChannel *source,
GIOCondition condition,
void *data)
on_sigterm (void)
{
char signal;
int count;
for (;;)
{
count = read (signal_pipe_fds[0], &signal, 1);
if (count == EINTR)
continue;
if (count < 0)
{
const char *msg = strerror (errno);
g_warning ("Error handling signal: %s", msg);
}
if (count != 1)
{
g_warning ("Unexpectedly failed to read byte from signal pipe\n");
return TRUE;
}
break;
}
switch (signal)
{
case 'T': /* SIGTERM */
meta_quit (META_EXIT_SUCCESS);
break;
default:
g_warning ("Spurious character '%c' read from signal pipe", signal);
}
return TRUE;
meta_quit (META_EXIT_SUCCESS);
return FALSE;
}
/**
@@ -433,17 +396,17 @@ meta_init (void)
g_strerror (errno));
#endif
if (pipe (signal_pipe_fds) != 0)
g_printerr ("Failed to create signal pipe: %s\n",
if (pipe (sigterm_pipe_fds) != 0)
g_printerr ("Failed to create SIGTERM pipe: %s\n",
g_strerror (errno));
channel = g_io_channel_unix_new (signal_pipe_fds[0]);
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_signal, NULL);
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
g_io_channel_set_close_on_unref (channel, TRUE);
g_io_channel_unref (channel);
act.sa_handler = &signal_handler;
act.sa_handler = &sigterm_handler;
if (sigaction (SIGTERM, &act, NULL) < 0)
g_printerr ("Failed to register SIGTERM handler: %s\n",
g_strerror (errno));
@@ -464,16 +427,9 @@ meta_init (void)
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif
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_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
meta_select_display (opt_display_name);
if (opt_replace_wm)
meta_set_replace_current_wm (TRUE);
@@ -485,17 +441,10 @@ meta_init (void)
meta_ui_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 ();
}
/*
* Clutter can only be initialized after the UI.
*/
meta_clutter_init ();
}
/**
@@ -565,14 +514,14 @@ meta_run (void)
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 ());
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
/* Try to find some theme that'll work if the theme preference
* doesn't exist. First try Simple (the default theme) then just
* try anything in the themes directory.
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Simple");
meta_ui_set_current_theme ("Simple", FALSE);
if (!meta_ui_have_a_theme ())
{
@@ -590,7 +539,7 @@ meta_run (void)
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
(!meta_ui_have_a_theme ()))
{
meta_ui_set_current_theme (dir_entry);
meta_ui_set_current_theme (dir_entry, FALSE);
}
g_dir_close (themes_dir);
@@ -649,7 +598,7 @@ prefs_changed_callback (MetaPreference pref,
{
case META_PREF_THEME:
case META_PREF_DRAGGABLE_BORDER_WIDTH:
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
meta_display_retheme_all ();
break;

View File

@@ -1,47 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_PRIVATE_H
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <clutter/clutter.h>
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_revert_root (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
CoglTexture2D *texture,
int hot_x,
int hot_y);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage);
#endif

View File

@@ -1,458 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
/**
* SECTION:cursor-tracker
* @title: MetaCursorTracker
* @short_description: Mutter cursor tracking helper
*/
#include <config.h>
#include <meta/main.h>
#include <meta/util.h>
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <clutter/clutter.h>
#include <X11/extensions/Xfixes.h>
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#ifdef HAVE_WAYLAND
#include "meta-wayland-private.h"
#endif
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
gboolean is_showing;
CoglTexture2D *sprite;
int hot_x, hot_y;
CoglTexture2D *root_cursor;
int root_hot_x, root_hot_y;
CoglTexture2D *default_cursor;
int current_x, current_y;
cairo_rectangle_int_t current_rect;
cairo_rectangle_int_t previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
};
struct _MetaCursorTrackerClass {
GObjectClass parent_class;
};
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
detecting if the system mouse cursor is showing or not.
On wayland we start with the cursor showing
*/
self->is_showing = TRUE;
}
static void
meta_cursor_tracker_finalize (GObject *object)
{
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
if (self->sprite)
cogl_object_unref (self->sprite);
if (self->root_cursor)
cogl_object_unref (self->root_cursor);
if (self->default_cursor)
cogl_object_unref (self->default_cursor);
if (self->pipeline)
cogl_object_unref (self->pipeline);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
static void
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_cursor_tracker_finalize;
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
#ifdef HAVE_WAYLAND
static MetaCursorTracker *
make_wayland_cursor_tracker (MetaScreen *screen)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = self;
return self;
}
#endif
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
/**
* meta_cursor_tracker_get_for_screen:
* @screen: the #MetaScreen
*
* Retrieves the cursor tracker object for @screen.
*
* Returns: (transfer none):
*/
MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
MetaCursorTracker *self;
if (screen->cursor_tracker)
return screen->cursor_tracker;
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
self = make_wayland_cursor_tracker (screen);
else
#endif
self = make_x11_cursor_tracker (screen);
screen->cursor_tracker = self;
return self;
}
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->sprite, cogl_object_unref);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
return TRUE;
}
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
gboolean free_cursor_data;
CoglContext *ctx;
if (tracker->sprite)
return;
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
* quantities as arrays of long; we need to convert on 64 bit */
if (sizeof(long) == 4)
{
cursor_data = (guint8 *)cursor_image->pixels;
free_cursor_data = FALSE;
}
else
{
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
cursor_data = (guint8 *)cursor_words;
p = cursor_image->pixels;
q = cursor_words;
for (j = 0; j < cursor_image->height; j++)
for (i = 0; i < cursor_image->width; i++)
*(q++) = *(p++);
free_cursor_data = TRUE;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
sprite = cogl_texture_2d_new_from_data (ctx,
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
COGL_PIXEL_FORMAT_ANY,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
if (free_cursor_data)
g_free (cursor_data);
if (sprite != NULL)
{
tracker->sprite = sprite;
tracker->hot_x = cursor_image->xhot;
tracker->hot_y = cursor_image->yhot;
}
XFree (cursor_image);
}
/**
* meta_cursor_tracker_get_sprite:
*
* Returns: (transfer none):
*/
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
return COGL_TEXTURE (tracker->sprite);
}
/**
* meta_cursor_tracker_get_hot:
* @tracker:
* @x: (out):
* @y: (out):
*
*/
void
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y)
{
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (x)
*x = tracker->hot_x;
if (y)
*y = tracker->hot_y;
}
static void
ensure_wayland_cursor (MetaCursorTracker *tracker)
{
CoglBitmap *bitmap;
char *filename;
if (tracker->default_cursor)
return;
filename = g_build_filename (MUTTER_PKGDATADIR,
"cursors/left_ptr.png",
NULL);
bitmap = cogl_bitmap_new_from_file (filename, NULL);
tracker->default_cursor = cogl_texture_2d_new_from_bitmap (bitmap,
COGL_PIXEL_FORMAT_ANY,
NULL);
cogl_object_unref (bitmap);
g_free (filename);
}
void
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor)
{
Cursor xcursor;
MetaDisplay *display = tracker->screen->display;
/* First create a cursor for X11 applications that don't specify their own */
xcursor = meta_display_create_x_cursor (display, cursor);
XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
XFlush (display->xdisplay);
XFreeCursor (display->xdisplay, xcursor);
/* Now update the real root cursor */
if (meta_is_wayland_compositor ())
{
/* FIXME! We need to load all the other cursors too */
ensure_wayland_cursor (tracker);
g_clear_pointer (&tracker->root_cursor, cogl_object_unref);
tracker->root_cursor = cogl_object_ref (tracker->default_cursor);
tracker->root_hot_x = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X;
tracker->root_hot_y = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y;
}
}
void
meta_cursor_tracker_revert_root (MetaCursorTracker *tracker)
{
meta_cursor_tracker_set_sprite (tracker,
tracker->root_cursor,
tracker->root_hot_x,
tracker->root_hot_y);
}
void
meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
CoglTexture2D *sprite,
int hot_x,
int hot_y)
{
g_assert (meta_is_wayland_compositor ());
g_clear_pointer (&tracker->sprite, cogl_object_unref);
if (sprite)
{
tracker->sprite = cogl_object_ref (sprite);
tracker->hot_x = hot_x;
tracker->hot_y = hot_y;
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (tracker->sprite));
}
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
meta_cursor_tracker_update_position (tracker, tracker->current_x, tracker->current_y);
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
tracker->current_x = new_x;
tracker->current_y = new_y;
tracker->current_rect.x = tracker->current_x - tracker->hot_x;
tracker->current_rect.y = tracker->current_y - tracker->hot_y;
if (tracker->sprite)
{
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (tracker->sprite));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (tracker->sprite));
}
else
{
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->sprite == NULL)
return;
/* FIXME: try to use a DRM cursor when possible */
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->previous_is_valid)
{
clutter_actor_queue_redraw_with_clip (stage, &tracker->previous_rect);
tracker->previous_is_valid = FALSE;
}
if (tracker->sprite == NULL)
return;
clutter_actor_queue_redraw_with_clip (stage, &tracker->current_rect);
}

View File

@@ -1,31 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include <meta/meta-idle-monitor.h>
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
void meta_idle_monitor_init_dbus (void);

View File

@@ -1,965 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
/**
* SECTION:idle-monitor
* @title: MetaIdleMonitor
* @short_description: Mutter idle counter (similar to X's IDLETIME)
*/
#include "config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include "meta-idle-monitor-private.h"
#include "meta-dbus-idle-monitor.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
struct _MetaIdleMonitor
{
GObject parent_instance;
GHashTable *watches;
GHashTable *alarms;
int device_id;
/* X11 implementation */
Display *display;
int sync_event_base;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
/* Wayland implementation */
guint64 last_event_time;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
};
typedef struct
{
MetaIdleMonitor *monitor;
guint id;
MetaIdleMonitorWatchFunc callback;
gpointer user_data;
GDestroyNotify notify;
guint64 timeout_msec;
/* x11 */
XSyncAlarm xalarm;
/* wayland */
GSource *timeout_source;
} MetaIdleMonitorWatch;
enum
{
PROP_0,
PROP_DEVICE_ID,
PROP_LAST,
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static void
fire_watch (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
guint id;
gboolean is_user_active_watch;
monitor = watch->monitor;
g_object_ref (monitor);
id = watch->id;
is_user_active_watch = (watch->timeout_msec == 0);
if (watch->callback)
watch->callback (monitor, id, watch->user_data);
if (is_user_active_watch)
meta_idle_monitor_remove_watch (monitor, id);
g_object_unref (monitor);
}
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitor *monitor,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = data;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch->xalarm != alarm)
return;
fire_watch (watch);
}
static void
meta_idle_monitor_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor->user_active_alarm)
{
set_alarm_enabled (monitor->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
}
void
meta_idle_monitor_handle_xevent_all (XEvent *xevent)
{
int i;
for (i = 0; i < device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitor *monitor)
{
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
if (watch == NULL)
return;
monitor = watch->monitor;
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch->xalarm != monitor->user_active_alarm &&
watch->xalarm != None)
{
XSyncDestroyAlarm (monitor->display, watch->xalarm);
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
}
if (watch->timeout_source != NULL)
g_source_destroy (watch->timeout_source);
g_slice_free (MetaIdleMonitorWatch, watch);
}
static void
init_xsync (MetaIdleMonitor *monitor)
{
monitor->counter = find_idletime_counter (monitor);
/* IDLETIME counter not found? */
if (monitor->counter == None)
{
meta_warning ("IDLETIME counter not found\n");
return;
}
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_dispose (GObject *object)
{
MetaIdleMonitor *monitor;
monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
if (monitor->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
monitor->user_active_alarm = None;
}
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
static void
meta_idle_monitor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value, monitor->device_id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
monitor->device_id = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_constructed (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
if (!meta_is_wayland_compositor ())
{
monitor->display = meta_get_display ()->xdisplay;
init_xsync (monitor);
}
}
static void
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_idle_monitor_dispose;
object_class->constructed = meta_idle_monitor_constructed;
object_class->get_property = meta_idle_monitor_get_property;
object_class->set_property = meta_idle_monitor_set_property;
/**
* MetaIdleMonitor:device_id:
*
* The device to listen to idletime on.
*/
obj_props[PROP_DEVICE_ID] =
g_param_spec_int ("device-id",
"Device ID",
"The device to listen to idletime on",
0, 255, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
monitor->watches = g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify)idle_monitor_watch_free);
monitor->alarms = g_hash_table_new (NULL, NULL);
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (META_TYPE_IDLE_MONITOR, "device-id", device_id, NULL);
device_id_max = MAX (device_id_max, device_id);
}
/**
* meta_idle_monitor_get_core:
*
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
* idletime for all devices. To track device-specific idletime,
* use meta_idle_monitor_get_for_device().
*/
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
ensure_device_monitor (0);
return device_monitors[0];
}
/**
* meta_idle_monitor_get_for_device:
* @device_id: the device to get the idle time for.
*
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
* device-specific idletime for @device. To track server-global idletime
* for all devices, use meta_idle_monitor_get_core().
*/
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
ensure_device_monitor (device_id);
return device_monitors[device_id];
}
static gboolean
wayland_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = user_data;
fire_watch (watch);
g_source_set_ready_time (watch->timeout_source, -1);
return TRUE;
}
static GSourceFuncs wayland_source_funcs = {
NULL, /* prepare */
NULL, /* check */
wayland_dispatch_timeout,
NULL, /* finalize */
};
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
watch = g_slice_new0 (MetaIdleMonitorWatch);
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (meta_is_wayland_compositor ())
{
if (timeout_msec != 0)
{
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch->timeout_source = source;
}
}
else
{
if (timeout_msec != 0)
{
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
}
else
{
watch->xalarm = monitor->user_active_alarm;
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
}
}
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
watch);
return watch;
}
/**
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Adds a watch for a specific idle time. The callback will be called
* when the user has accumulated @interval_msec milliseconds of idle time.
* This function will return an ID that can either be passed to
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
* watches apart if you have more than one.
*
* Also note that this function will only care about positive transitions
* (user's idle time exceeding a certain time). If you want to know about
* when the user has become active, use
* meta_idle_monitor_add_user_active_watch().
*/
guint
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);
watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Add a one-time watch to know when the user is active again.
* Note that this watch is one-time and will de-activate after the
* function is called, for efficiency purposes. It's most convenient
* to call this when an idle watch, as added by
* meta_idle_monitor_add_idle_watch(), has triggered.
*/
guint
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
watch = make_watch (monitor,
0,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_remove_watch:
* @monitor: A #MetaIdleMonitor
* @id: A watch ID
*
* Removes an idle time watcher, previously added by
* meta_idle_monitor_add_idle_watch() or
* meta_idle_monitor_add_user_active_watch().
*/
void
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id)
{
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
g_hash_table_remove (monitor->watches,
GUINT_TO_POINTER (id));
}
/**
* meta_idle_monitor_get_idletime:
* @monitor: A #MetaIdleMonitor
*
* Returns: The current idle time, in milliseconds, or -1 for not supported
*/
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
XSyncValue value;
if (meta_is_wayland_compositor ())
{
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
}
else
{
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
}
typedef struct {
MetaIdleMonitor *monitor;
GList *fired_watches;
} CheckWaylandClosure;
static gboolean
check_wayland_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = value;
CheckWaylandClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch->timeout_source,
closure->monitor->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_wayland_watch (gpointer watch,
gpointer data)
{
fire_watch (watch);
}
void
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
{
CheckWaylandClosure closure;
monitor->last_event_time = g_get_monotonic_time ();
closure.monitor = monitor;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
g_list_free (closure.fired_watches);
}
static gboolean
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
guint64 idletime;
idletime = meta_idle_monitor_get_idletime (monitor);
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
char *dbus_name;
guint watch_id;
guint name_watcher_id;
} DBusWatch;
static void
destroy_dbus_watch (gpointer data)
{
DBusWatch *watch = data;
g_object_unref (watch->dbus_monitor);
g_object_unref (watch->monitor);
g_free (watch->dbus_name);
g_bus_unwatch_name (watch->name_watcher_id);
g_slice_free (DBusWatch, watch);
}
static void
dbus_idle_callback (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
DBusWatch *watch = user_data;
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
watch->dbus_name,
g_dbus_interface_skeleton_get_object_path (skeleton),
"org.gnome.Mutter.IdleMonitor",
"WatchFired",
g_variant_new ("(u)", watch_id),
NULL);
}
static void
name_vanished_callback (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
DBusWatch *watch = user_data;
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
}
static DBusWatch *
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = g_slice_new (DBusWatch);
watch->dbus_monitor = g_object_ref (skeleton);
watch->monitor = g_object_ref (monitor);
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
watch->dbus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL, /* appeared */
name_vanished_callback,
watch, NULL);
return watch;
}
static gboolean
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint64 interval,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
dbus_idle_callback, watch, destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
dbus_idle_callback, watch,
destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint id,
MetaIdleMonitor *monitor)
{
meta_idle_monitor_remove_watch (monitor, id);
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
return TRUE;
}
static void
create_monitor_skeleton (GDBusObjectManagerServer *manager,
MetaIdleMonitor *monitor,
const char *path)
{
MetaDBusIdleMonitor *skeleton;
MetaDBusObjectSkeleton *object;
skeleton = meta_dbus_idle_monitor_skeleton_new ();
g_signal_connect_object (skeleton, "handle-add-idle-watch",
G_CALLBACK (handle_add_idle_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);
object = meta_dbus_object_skeleton_new (path);
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
MetaIdleMonitor *monitor;
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
monitor = meta_idle_monitor_get_for_device (device_id);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
create_monitor_skeleton (manager, monitor, path);
g_free (path);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
g_dbus_object_manager_server_unexport (manager, path);
g_free (path);
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
GDBusObjectManagerServer *manager;
ClutterDeviceManager *device_manager;
MetaIdleMonitor *monitor;
GSList *devices, *iter;
char *path;
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
/* We never clear the core monitor, as that's supposed to cumulate idle times from
all devices */
monitor = meta_idle_monitor_get_core ();
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
create_monitor_skeleton (manager, monitor, path);
g_free (path);
device_manager = clutter_device_manager_get_default ();
devices = clutter_device_manager_list_devices (device_manager);
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",
G_CALLBACK (on_device_removed), manager, 0);
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Acquired name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Lost or failed to acquire name %s\n", name);
}
void
meta_idle_monitor_init_dbus (void)
{
static int dbus_name_id;
if (dbus_name_id > 0)
return;
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gnome.Mutter.IdleMonitor",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
(meta_get_replace_current_wm () ?
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL, NULL);
}

View File

@@ -1,40 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
The canonical place for all changes is mutter.
There should be no includes in this file.
*/
#ifndef META_XRANDR_SHARED_H
#define META_XRANDR_SHARED_H
typedef enum {
META_POWER_SAVE_UNKNOWN = -1,
META_POWER_SAVE_ON = 0,
META_POWER_SAVE_STANDBY,
META_POWER_SAVE_SUSPEND,
META_POWER_SAVE_OFF,
} MetaPowerSave;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,390 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file screen-private.h Handling of monitor configuration
*
* Managing multiple monitors
* This file contains structures and functions that handle
* multiple monitors, including reading the current configuration
* and available hardware, and applying it.
*
* This interface is private to mutter, API users should look
* at MetaScreen instead.
*/
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_MONITOR_PRIVATE_H
#define META_MONITOR_PRIVATE_H
#include <cogl/cogl.h>
#include <libgnome-desktop/gnome-pnp-ids.h>
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
#endif
#include "meta-xrandr-shared.h"
#include "meta-dbus-xrandr.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager;
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
typedef struct _MetaMonitorConfig MetaMonitorConfig;
#ifndef HAVE_WAYLAND
enum wl_output_transform {
WL_OUTPUT_TRANSFORM_NORMAL,
WL_OUTPUT_TRANSFORM_90,
WL_OUTPUT_TRANSFORM_180,
WL_OUTPUT_TRANSFORM_270,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
#endif
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaMonitorMode MetaMonitorMode;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong output_id;
char *name;
char *vendor;
char *product;
char *serial;
int width_mm;
int height_mm;
CoglSubpixelOrder subpixel_order;
MetaMonitorMode *preferred_mode;
MetaMonitorMode **modes;
unsigned int n_modes;
MetaCRTC **possible_crtcs;
unsigned int n_possible_crtcs;
MetaOutput **possible_clones;
unsigned int n_possible_clones;
int backlight;
int backlight_min;
int backlight_max;
/* Used when changing configuration */
gboolean is_dirty;
/* The low-level bits used to build the high-level info
in MetaMonitorInfo
XXX: flags maybe?
There is a lot of code that uses MonitorInfo->is_primary,
but nobody uses MetaOutput yet
*/
gboolean is_primary;
gboolean is_presentation;
};
struct _MetaCRTC
{
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
from the HW one
*/
MetaMonitorInfo *logical_monitor;
/* Used when changing configuration */
gboolean is_dirty;
};
struct _MetaMonitorMode
{
/* The low-level ID of this mode, used to apply back configuration */
glong mode_id;
int width;
int height;
float refresh_rate;
};
/**
* MetaMonitorInfo:
*
* A structure with high-level information about monitors.
* This corresponds to a subset of the compositor coordinate space.
* Clones are only reported once, irrespective of the way
* they're implemented (two CRTCs configured for the same
* coordinates or one CRTCs driving two outputs). Inactive CRTCs
* are ignored, and so are disabled outputs.
*/
struct _MetaMonitorInfo
{
int number;
int xinerama_index;
MetaRectangle rect;
gboolean is_primary;
gboolean is_presentation; /* XXX: not yet used */
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong output_id;
};
/*
* MetaCRTCInfo:
* This represents the writable part of a CRTC, as deserialized from DBus
* or built by MetaMonitorConfig
*
* Note: differently from the other structures in this file, MetaCRTCInfo
* is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
*/
struct _MetaCRTCInfo {
MetaCRTC *crtc;
MetaMonitorMode *mode;
int x;
int y;
enum wl_output_transform transform;
GPtrArray *outputs;
};
/*
* MetaOutputInfo:
* this is the same as MetaOutputInfo, but for CRTCs
*/
struct _MetaOutputInfo {
MetaOutput *output;
gboolean is_primary;
gboolean is_presentation;
};
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
#define META_IS_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER))
#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER))
#define META_MONITOR_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
struct _MetaMonitorManager
{
MetaDBusDisplayConfigSkeleton parent_instance;
/* XXX: this structure is very badly
packed, but I like the logical organization
of fields */
gboolean in_init;
unsigned int serial;
MetaPowerSave power_save_mode;
int max_screen_width;
int max_screen_height;
int screen_width;
int screen_height;
/* Outputs refer to physical screens,
CRTCs refer to stuff that can drive outputs
(like encoders, but less tied to the HW),
while monitor_infos refer to logical ones.
See also the comment in monitor-private.h
*/
MetaOutput *outputs;
unsigned int n_outputs;
MetaMonitorMode *modes;
unsigned int n_modes;
MetaCRTC *crtcs;
unsigned int n_crtcs;
MetaMonitorInfo *monitor_infos;
unsigned int n_monitor_infos;
int primary_monitor_index;
int dbus_name_id;
int persistent_timeout_id;
MetaMonitorConfig *config;
GnomePnpIds *pnp_ids;
};
struct _MetaMonitorManagerClass
{
MetaDBusDisplayConfigSkeletonClass parent_class;
void (*read_current) (MetaMonitorManager *);
char* (*get_edid_file) (MetaMonitorManager *,
MetaOutput *);
GBytes* (*read_edid) (MetaMonitorManager *,
MetaOutput *);
void (*apply_configuration) (MetaMonitorManager *,
MetaCRTCInfo **,
unsigned int ,
MetaOutputInfo **,
unsigned int);
void (*set_power_save_mode) (MetaMonitorManager *,
MetaPowerSave);
void (*change_backlight) (MetaMonitorManager *,
MetaOutput *,
int);
void (*get_crtc_gamma) (MetaMonitorManager *,
MetaCRTC *,
gsize *,
unsigned short **,
unsigned short **,
unsigned short **);
void (*set_crtc_gamma) (MetaMonitorManager *,
MetaCRTC *,
gsize ,
unsigned short *,
unsigned short *,
unsigned short *);
gboolean (*handle_xevent) (MetaMonitorManager *,
XEvent *);
};
GType meta_monitor_manager_get_type (void);
void meta_monitor_manager_initialize (void);
MetaMonitorManager *meta_monitor_manager_get (void);
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
unsigned int *n_infos);
MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
unsigned int *n_outputs);
void meta_monitor_manager_get_resources (MetaMonitorManager *manager,
MetaMonitorMode **modes,
unsigned int *n_modes,
MetaCRTC **crtcs,
unsigned int *n_crtcs,
MetaOutput **outputs,
unsigned int *n_outputs);
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event);
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
int *width,
int *height);
void meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
int *width,
int *height);
void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs);
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
gboolean ok);
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void);
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_default (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_update_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,15 +46,8 @@ print_version (const gchar *option_name,
}
static gchar *plugin = "default";
static gboolean opt_nested = FALSE;
GOptionEntry mutter_options[] = {
{
"nested", 0, 0, G_OPTION_ARG_NONE,
&opt_nested,
N_("Run nested as an application for testing"),
NULL,
},
{
"version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
print_version,
@@ -84,8 +77,6 @@ main (int argc, char **argv)
exit (1);
}
meta_set_is_wayland_compositor (opt_nested);
if (plugin)
meta_plugin_manager_load (plugin);

View File

@@ -89,6 +89,7 @@ static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_
static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU;
static gboolean dynamic_workspaces = FALSE;
static gboolean application_based = FALSE;
static gboolean disable_workarounds = FALSE;
static gboolean auto_raise = FALSE;
static gboolean auto_raise_delay = 500;
@@ -297,6 +298,13 @@ static MetaBoolPreference preferences_bool[] =
},
&dynamic_workspaces,
},
{
{ "application-based",
SCHEMA_GENERAL,
META_PREF_APPLICATION_BASED,
},
NULL, /* feature is known but disabled */
},
{
{ "disable-workarounds",
SCHEMA_GENERAL,
@@ -1715,6 +1723,14 @@ meta_prefs_get_dynamic_workspaces (void)
return dynamic_workspaces;
}
gboolean
meta_prefs_get_application_based (void)
{
return FALSE; /* For now, we never want this to do anything */
return application_based;
}
gboolean
meta_prefs_get_disable_workarounds (void)
{
@@ -1752,6 +1768,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_NUM_WORKSPACES:
return "NUM_WORKSPACES";
case META_PREF_APPLICATION_BASED:
return "APPLICATION_BASED";
case META_PREF_KEYBINDINGS:
return "KEYBINDINGS";

View File

@@ -38,7 +38,17 @@
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "ui.h"
#include "monitor-private.h"
typedef struct _MetaMonitorInfo MetaMonitorInfo;
struct _MetaMonitorInfo
{
int number;
MetaRectangle rect;
gboolean is_primary;
gboolean in_fullscreen;
XID output; /* The primary or first output for this crtc, None if no xrandr */
};
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
gpointer user_data);
@@ -83,7 +93,6 @@ struct _MetaScreen
MetaStack *stack;
MetaStackTracker *stack_tracker;
MetaCursorTracker *cursor_tracker;
MetaCursor current_cursor;
Window flash_window;
@@ -91,11 +100,10 @@ struct _MetaScreen
Window wm_sn_selection_window;
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
MetaMonitorInfo *monitor_infos;
int n_monitor_infos;
int primary_monitor_index;
gboolean has_xinerama_indices;
int n_monitor_infos;
/* Cache the current monitor */
int last_monitor_index;
@@ -223,6 +231,10 @@ void meta_screen_calc_workspace_layout (MetaScreen *screen,
MetaWorkspaceLayout *layout);
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
void meta_screen_resize (MetaScreen *screen,
int width,
int height);
void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
MetaWindow *keep);
@@ -245,14 +257,4 @@ void meta_screen_workspace_switched (MetaScreen *screen,
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
Window meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen);
gboolean meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent);
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index);
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index);
#endif

View File

@@ -45,11 +45,13 @@
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include "core.h"
#include "meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <X11/Xatom.h>
#include <locale.h>
#include <string.h>
@@ -74,9 +76,6 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
void *user_data);
#endif
static void on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen);
enum
{
PROP_N_WORKSPACES = 1,
@@ -351,93 +350,250 @@ set_wm_icon_size_hint (MetaScreen *screen)
#undef N_VALS
}
/* The list of monitors reported by the windowing system might include
* mirrored monitors with identical bounds. Since mirrored monitors
* shouldn't be treated as separate monitors for most purposes, we
* filter them out here. (We ignore the possibility of partially
* overlapping monitors because they are rare and it's hard to come
* up with any sensible interpretation.)
*/
static void
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
filter_mirrored_monitors (MetaScreen *screen)
{
XineramaScreenInfo *infos;
int n_infos, i, j;
int i, j;
if (screen->has_xinerama_indices)
return;
/* Currently always true and simplifies things */
g_assert (screen->primary_monitor_index == 0);
screen->has_xinerama_indices = TRUE;
if (!XineramaIsActive (screen->display->xdisplay))
return;
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
if (n_infos <= 0 || infos == NULL)
for (i = 1; i < screen->n_monitor_infos; i++)
{
meta_XFree (infos);
return;
}
/* In case we've filtered previous monitors */
screen->monitor_infos[i].number = i;
for (i = 0; i < screen->n_monitor_infos; ++i)
{
for (j = 0; j < n_infos; ++j)
for (j = 0; j < i; j++)
{
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
screen->monitor_infos[i].rect.y == infos[j].y_org &&
screen->monitor_infos[i].rect.width == infos[j].width &&
screen->monitor_infos[i].rect.height == infos[j].height)
screen->monitor_infos[i].xinerama_index = j;
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
&screen->monitor_infos[j].rect))
{
memmove (&screen->monitor_infos[i],
&screen->monitor_infos[i + 1],
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
screen->n_monitor_infos--;
i--;
continue;
}
}
}
meta_XFree (infos);
}
int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
}
int
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index)
#ifdef HAVE_RANDR
static MetaMonitorInfo *
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
{
MetaMonitorInfo *info;
int i;
meta_screen_ensure_xinerama_indices (screen);
for (i = 0; i < screen->n_monitor_infos; i++)
if (screen->monitor_infos[i].xinerama_index == index)
return i;
return -1;
{
info = &screen->monitor_infos[i];
if (x == info->rect.x &&
y == info->rect.y &&
w == info->rect.width &&
h == info->rect.height)
return info;
}
return NULL;
}
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
* outputs the "main". This is the one we consider "owning" the windows, so if
* the mirroring is changed to a dual monitor setup then the windows are moved to the
* crtc that now has that main output. If one of the outputs is the primary that is
* always the main, otherwise we just use the first.
*/
static XID
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
{
XRROutputInfo *output;
RROutput primary_output;
int i;
XID res;
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
res = None;
for (i = 0; i < crtc->noutput; i++)
{
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
if (output->connection != RR_Disconnected &&
(res == None || crtc->outputs[i] == primary_output))
res = crtc->outputs[i];
XRRFreeOutputInfo (output);
}
return res;
}
#endif
static void
reload_monitor_infos (MetaScreen *screen)
{
GList *tmp;
MetaMonitorManager *manager;
MetaDisplay *display;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
{
GList *tmp;
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
}
display = screen->display;
/* Any previous screen->monitor_infos is freed by the caller */
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
screen->has_xinerama_indices = FALSE;
/* Xinerama doesn't have a concept of primary monitor, however XRandR
* does. However, the XRandR xinerama compat code always sorts the
* primary output first, so we rely on that here. We could use the
* native XRandR calls instead of xinerama, but that would be
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
* that is defined in terms of xinerama monitor indexes.
* So, since we don't need anything in xrandr except the primary
* we can keep using xinerama and use the first monitor as the
* primary.
*/
screen->primary_monitor_index = 0;
screen->display->monitor_cache_invalidated = TRUE;
manager = meta_monitor_manager_get ();
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
{
meta_topic (META_DEBUG_XINERAMA,
"Pretending a single monitor has two Xinerama screens\n");
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
(unsigned*)&screen->n_monitor_infos);
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
screen->n_monitor_infos = 2;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
screen->monitor_infos[1].number = 1;
screen->monitor_infos[1].rect = screen->rect;
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
}
if (screen->n_monitor_infos == 0 &&
XineramaIsActive (display->xdisplay))
{
XineramaScreenInfo *infos;
int n_infos;
int i;
n_infos = 0;
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
meta_topic (META_DEBUG_XINERAMA,
"Found %d Xinerama screens on display %s\n",
n_infos, display->name);
if (n_infos > 0)
{
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
screen->n_monitor_infos = n_infos;
i = 0;
while (i < n_infos)
{
screen->monitor_infos[i].number = infos[i].screen_number;
screen->monitor_infos[i].rect.x = infos[i].x_org;
screen->monitor_infos[i].rect.y = infos[i].y_org;
screen->monitor_infos[i].rect.width = infos[i].width;
screen->monitor_infos[i].rect.height = infos[i].height;
screen->monitor_infos[i].in_fullscreen = -1;
meta_topic (META_DEBUG_XINERAMA,
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
}
meta_XFree (infos);
#ifdef HAVE_RANDR
{
XRRScreenResources *resources;
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
if (resources)
{
for (i = 0; i < resources->ncrtc; i++)
{
XRRCrtcInfo *crtc;
MetaMonitorInfo *info;
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
if (info)
info->output = find_main_output_for_crtc (screen, resources, crtc);
XRRFreeCrtcInfo (crtc);
}
XRRFreeScreenResources (resources);
}
}
#endif
}
else if (screen->n_monitor_infos > 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama extension or Xinerama inactive on display %s\n",
display->name);
}
/* If no Xinerama, fill in the single screen info so
* we can use the field unconditionally
*/
if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama screens, using default screen info\n");
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
screen->n_monitor_infos = 1;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].in_fullscreen = -1;
}
filter_mirrored_monitors (screen);
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
g_assert (screen->n_monitor_infos > 0);
g_assert (screen->monitor_infos != NULL);
}
/* The guard window allows us to leave minimized windows mapped so
@@ -447,13 +603,12 @@ reload_monitor_infos (MetaScreen *screen)
* should effectively be forwarded to events on the background actor,
* providing that the scene graph is set up correctly.
*/
Window
meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen)
static Window
create_guard_window (Display *xdisplay, MetaScreen *screen)
{
XSetWindowAttributes attributes;
Window guard_window;
gulong create_serial;
MetaStackWindow stack_window;
attributes.event_mask = NoEventMask;
attributes.override_redirect = True;
@@ -486,14 +641,12 @@ meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen)
XISelectEvents (xdisplay, guard_window, &mask, 1);
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = guard_window;
meta_stack_tracker_record_add (screen->stack_tracker,
&stack_window,
guard_window,
create_serial);
meta_stack_tracker_record_lower (screen->stack_tracker,
&stack_window,
guard_window,
XNextRequest (xdisplay));
XLowerWindow (xdisplay, guard_window);
XMapWindow (xdisplay, guard_window);
@@ -515,7 +668,6 @@ meta_screen_new (MetaDisplay *display,
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@@ -674,18 +826,8 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
if (!meta_is_wayland_compositor ())
meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), screen);
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
@@ -710,9 +852,12 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
reload_monitor_infos (screen);
meta_cursor_tracker_get_for_screen (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
/* Handle creating a no_focus_window for this screen */
@@ -796,7 +941,7 @@ meta_screen_new (MetaDisplay *display,
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
@@ -937,8 +1082,8 @@ meta_screen_manage_all_windows (MetaScreen *screen)
meta_display_grab (screen->display);
if (screen->guard_window == None)
screen->guard_window =
meta_screen_create_guard_window (screen->display->xdisplay, screen);
screen->guard_window = create_guard_window (screen->display->xdisplay,
screen);
windows = list_windows (screen);
@@ -1468,18 +1613,29 @@ void
meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor)
{
Cursor xcursor;
if (cursor == screen->current_cursor)
return;
screen->current_cursor = cursor;
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
xcursor = meta_display_create_x_cursor (screen->display, cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
screen->current_cursor);
Cursor xcursor;
xcursor = meta_display_create_x_cursor (screen->display,
screen->current_cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
}
void
@@ -1742,15 +1898,12 @@ meta_screen_tile_preview_update_timeout (gpointer data)
{
Window xwindow;
gulong create_serial;
MetaStackWindow stack_window;
screen->tile_preview = meta_tile_preview_new (screen->number);
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
&create_serial);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
meta_stack_tracker_record_add (screen->stack_tracker,
&stack_window,
xwindow,
create_serial);
}
@@ -2844,15 +2997,19 @@ meta_screen_resize_func (MetaScreen *screen,
meta_window_recalc_features (window);
}
static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
void
meta_screen_resize (MetaScreen *screen,
int width,
int height)
{
GSList *tmp, *windows;
GSList *windows, *tmp;
MetaMonitorInfo *old_monitor_infos;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->rect.width = width;
screen->rect.height = height;
/* Save the old monitor infos, so they stay valid during the update */
old_monitor_infos = screen->monitor_infos;
reload_monitor_infos (screen);
set_desktop_geometry_hint (screen);
@@ -2864,8 +3021,8 @@ on_monitors_changed (MetaMonitorManager *manager,
changes.x = 0;
changes.y = 0;
changes.width = screen->rect.width;
changes.height = screen->rect.height;
changes.width = width;
changes.height = height;
XConfigureWindow(screen->display->xdisplay,
screen->guard_window,
@@ -2875,8 +3032,7 @@ on_monitors_changed (MetaMonitorManager *manager,
if (screen->display->compositor)
meta_compositor_sync_screen_size (screen->display->compositor,
screen,
screen->rect.width, screen->rect.height);
screen, width, height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
@@ -2892,6 +3048,7 @@ on_monitors_changed (MetaMonitorManager *manager,
meta_window_update_for_monitors_changed (window);
}
g_free (old_monitor_infos);
g_slist_free (windows);
meta_screen_queue_check_fullscreen (screen);
@@ -3687,13 +3844,3 @@ meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
/* We use -1 as a flag to mean "not known yet" for notification purposes */
return screen->monitor_infos[monitor].in_fullscreen == TRUE;
}
gboolean
meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent)
{
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
return TRUE;
return FALSE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -37,55 +37,36 @@
#define META_STACK_TRACKER_H
#include <meta/screen.h>
#include <meta/window.h>
typedef struct _MetaStackTracker MetaStackTracker;
typedef union _MetaStackWindow
{
struct {
MetaWindowClientType type;
} any;
struct {
MetaWindowClientType type;
Window xwindow;
} x11;
struct {
MetaWindowClientType type;
MetaWindow *meta_window;
} wayland;
} MetaStackWindow;
gboolean meta_stack_window_equal (const MetaStackWindow *a,
const MetaStackWindow *b);
MetaStackTracker *meta_stack_tracker_new (MetaScreen *screen);
void meta_stack_tracker_free (MetaStackTracker *tracker);
/* These functions are called when we make an X call that changes the
* stacking order; this allows MetaStackTracker to predict stacking
* order before it receives events back from the X server */
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
const MetaStackWindow *windows,
int n_windows,
gulong serial);
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
const MetaStackWindow *window,
const MetaStackWindow *sibling,
gulong serial);
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
const MetaStackWindow *window,
const MetaStackWindow *sibling,
gulong serial);
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
Window window,
gulong serial);
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
Window window,
gulong serial);
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
Window *windows,
int n_windows,
gulong serial);
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
Window window,
Window sibling,
gulong serial);
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
Window window,
Window sibling,
gulong serial);
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
Window window,
gulong serial);
/* These functions are used to update the stack when we get events
* reflecting changes to the stacking order */
@@ -98,9 +79,9 @@ void meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
void meta_stack_tracker_configure_event (MetaStackTracker *tracker,
XConfigureEvent *event);
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
MetaStackWindow **windows,
int *n_entries);
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
Window **windows,
int *n_windows);
void meta_stack_tracker_sync_stack (MetaStackTracker *tracker);
void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);

View File

@@ -52,7 +52,7 @@
#define WINDOW_IN_STACK(w) (w->stack_position >= 0)
static void stack_sync_to_xserver (MetaStack *stack);
static void stack_sync_to_server (MetaStack *stack);
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
int position);
static void stack_do_window_deletions (MetaStack *stack);
@@ -71,14 +71,14 @@ meta_stack_new (MetaScreen *screen)
stack = g_new (MetaStack, 1);
stack->screen = screen;
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
stack->windows = g_array_new (FALSE, FALSE, sizeof (Window));
stack->sorted = NULL;
stack->added = NULL;
stack->removed = NULL;
stack->freeze_count = 0;
stack->last_all_root_children_stacked = NULL;
stack->last_root_children_stacked = NULL;
stack->n_positions = 0;
@@ -89,34 +89,17 @@ meta_stack_new (MetaScreen *screen)
return stack;
}
static void
free_last_all_root_children_stacked_cache (MetaStack *stack)
{
unsigned int i;
for (i = 0; i < stack->last_all_root_children_stacked->len; i++)
{
MetaStackWindow *window = &g_array_index (stack->last_all_root_children_stacked, MetaStackWindow, i);
if (window->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND)
g_object_remove_weak_pointer (G_OBJECT (window->wayland.meta_window),
(gpointer *)&window->wayland.meta_window);
}
g_array_free (stack->last_all_root_children_stacked, TRUE);
stack->last_all_root_children_stacked = NULL;
}
void
meta_stack_free (MetaStack *stack)
{
g_array_free (stack->xwindows, TRUE);
g_array_free (stack->windows, TRUE);
g_list_free (stack->sorted);
g_list_free (stack->added);
g_list_free (stack->removed);
if (stack->last_all_root_children_stacked)
free_last_all_root_children_stacked_cache (stack);
if (stack->last_root_children_stacked)
g_array_free (stack->last_root_children_stacked, TRUE);
g_free (stack);
}
@@ -138,7 +121,7 @@ meta_stack_add (MetaStack *stack,
"Window %s has stack_position initialized to %d\n",
window->desc, window->stack_position);
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -174,7 +157,7 @@ meta_stack_remove (MetaStack *stack,
stack->removed = g_list_prepend (stack->removed,
GUINT_TO_POINTER (window->frame->xwindow));
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -184,7 +167,7 @@ meta_stack_update_layer (MetaStack *stack,
{
stack->need_relayer = TRUE;
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -194,7 +177,7 @@ meta_stack_update_transient (MetaStack *stack,
{
stack->need_constrain = TRUE;
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -223,7 +206,7 @@ meta_stack_raise (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, max_stack_position);
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -251,7 +234,7 @@ meta_stack_lower (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, min_stack_position);
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@@ -267,7 +250,7 @@ meta_stack_thaw (MetaStack *stack)
g_return_if_fail (stack->freeze_count > 0);
stack->freeze_count -= 1;
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@@ -295,7 +278,7 @@ static gboolean
is_focused_foreach (MetaWindow *window,
void *data)
{
if (window->has_focus)
if (window == window->display->expected_focus_window)
{
*((gboolean*) data) = TRUE;
return FALSE;
@@ -352,11 +335,11 @@ get_standalone_layer (MetaWindow *window)
layer = META_LAYER_BOTTOM;
else if (window->fullscreen &&
(focused_transient ||
window == window->display->focus_window ||
window->display->focus_window == NULL ||
(window->display->focus_window != NULL &&
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
windows_on_different_monitor (window,
window->display->focus_window))))
window->display->expected_focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
layer = META_LAYER_TOP;
@@ -846,7 +829,7 @@ stack_do_window_deletions (MetaStack *stack)
/* We go from the end figuring removals are more
* likely to be recent.
*/
i = stack->xwindows->len;
i = stack->windows->len;
while (i > 0)
{
--i;
@@ -857,9 +840,9 @@ stack_do_window_deletions (MetaStack *stack)
* both the window->xwindow and window->frame->xwindow
* in the removal list.
*/
if (xwindow == g_array_index (stack->xwindows, Window, i))
if (xwindow == g_array_index (stack->windows, Window, i))
{
g_array_remove_index (stack->xwindows, i);
g_array_remove_index (stack->windows, i);
goto next;
}
}
@@ -888,10 +871,10 @@ stack_do_window_additions (MetaStack *stack)
"Adding %d windows to sorted list\n",
n_added);
old_size = stack->xwindows->len;
g_array_set_size (stack->xwindows, old_size + n_added);
old_size = stack->windows->len;
g_array_set_size (stack->windows, old_size + n_added);
end = &g_array_index (stack->xwindows, Window, old_size);
end = &g_array_index (stack->windows, Window, old_size);
/* stack->added has the most recent additions at the
* front of the list, so we need to reverse it
@@ -1046,102 +1029,6 @@ stack_ensure_sorted (MetaStack *stack)
stack_do_resort (stack);
}
static MetaStackWindow *
find_top_most_managed_window (MetaScreen *screen,
const MetaStackWindow *ignore)
{
MetaStackTracker *stack_tracker = screen->stack_tracker;
MetaStackWindow *windows;
int n_windows;
int i;
meta_stack_tracker_get_stack (stack_tracker,
&windows, &n_windows);
/* Children are in order from bottom to top. We want to
* find the topmost managed child, then configure
* our window to be above it.
*/
for (i = n_windows -1; i >= 0; i--)
{
MetaStackWindow *other_window = &windows[i];
if (other_window->any.type == ignore->any.type &&
((other_window->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
other_window->x11.xwindow == ignore->x11.xwindow) ||
other_window->wayland.meta_window == ignore->wayland.meta_window))
{
/* Do nothing. This means we're already the topmost managed
* window, but it DOES NOT mean we are already just above
* the topmost managed window. This is important because if
* an override redirect window is up, and we map a new
* managed window, the new window is probably above the old
* popup by default, and we want to push it below that
* popup. So keep looking for a sibling managed window
* to be moved below.
*/
}
else
{
if (other_window->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
MetaWindow *other = meta_display_lookup_x_window (screen->display,
other_window->x11.xwindow);
if (other != NULL && !other->override_redirect)
return other_window;
}
else
{
/* All wayland windows are currently considered "managed"
* TODO: consider wayland pop-up windows like override
* redirect windows here. */
return other_window;
}
}
}
return NULL;
}
/* When moving an X window we sometimes need an X based sibling.
*
* If the given sibling is X based this function returns it back
* otherwise it searches downwards looking for the nearest X window.
*
* If no X based sibling could be found return NULL. */
static MetaStackWindow *
find_x11_sibling_downwards (MetaScreen *screen,
MetaStackWindow *sibling)
{
MetaStackTracker *stack_tracker = screen->stack_tracker;
MetaStackWindow *windows;
int n_windows;
int i;
if (sibling->any.type == META_WINDOW_CLIENT_TYPE_X11)
return sibling;
meta_stack_tracker_get_stack (stack_tracker,
&windows, &n_windows);
/* NB: Children are in order from bottom to top and we
* want to search downwards for the nearest X window.
*/
for (i = n_windows - 1; i >= 0; i--)
if (meta_stack_window_equal (&windows[i], sibling))
break;
for (; i >= 0; i--)
{
if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
return &windows[i];
}
return NULL;
}
/**
* raise_window_relative_to_managed_windows:
*
@@ -1166,74 +1053,84 @@ find_x11_sibling_downwards (MetaScreen *screen,
*/
static void
raise_window_relative_to_managed_windows (MetaScreen *screen,
const MetaStackWindow *window)
Window xwindow)
{
gulong serial = 0;
MetaStackWindow *sibling;
sibling = find_top_most_managed_window (screen, window);
if (!sibling)
Window *children;
int n_children;
int i;
meta_stack_tracker_get_stack (screen->stack_tracker,
&children, &n_children);
/* Children are in order from bottom to top. We want to
* find the topmost managed child, then configure
* our window to be above it.
*/
i = n_children - 1;
while (i >= 0)
{
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
if (children[i] == xwindow)
{
serial = XNextRequest (screen->display->xdisplay);
meta_error_trap_push (screen->display);
XLowerWindow (screen->display->xdisplay,
window->x11.xwindow);
meta_error_trap_pop (screen->display);
}
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
/* Do nothing. This means we're already the topmost managed
* window, but it DOES NOT mean we are already just above
* the topmost managed window. This is important because if
* an override redirect window is up, and we map a new
* managed window, the new window is probably above the old
* popup by default, and we want to push it below that
* popup. So keep looking for a sibling managed window
* to be moved below.
*/
meta_stack_tracker_record_lower (screen->stack_tracker,
window,
serial);
return;
}
else
{
MetaWindow *other = meta_display_lookup_x_window (screen->display,
children[i]);
if (other != NULL && !other->override_redirect)
{
XWindowChanges changes;
/* window is the topmost managed child */
/* children[i] is the topmost managed child */
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);
xwindow, children[i]);
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
XWindowChanges changes;
MetaStackWindow *x11_sibling = find_x11_sibling_downwards (screen, sibling);
serial = XNextRequest (screen->display->xdisplay);
if (x11_sibling)
{
changes.sibling = x11_sibling->x11.xwindow;
changes.sibling = children[i];
changes.stack_mode = Above;
meta_error_trap_push (screen->display);
meta_stack_tracker_record_raise_above (screen->stack_tracker,
xwindow,
children[i],
XNextRequest (screen->display->xdisplay));
XConfigureWindow (screen->display->xdisplay,
window->x11.xwindow,
xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (screen->display);
break;
}
}
else
--i;
}
if (i < 0)
{
/* 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);
meta_stack_tracker_record_lower (screen->stack_tracker,
xwindow,
XNextRequest (screen->display->xdisplay));
XLowerWindow (screen->display->xdisplay,
window->x11.xwindow);
xwindow);
meta_error_trap_pop (screen->display);
}
}
meta_stack_tracker_record_raise_above (screen->stack_tracker,
window,
sibling,
serial);
}
/**
* stack_sync_to_server:
*
@@ -1248,16 +1145,13 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
* job of computing the minimal set of stacking requests needed.
*/
static void
stack_sync_to_xserver (MetaStack *stack)
stack_sync_to_server (MetaStack *stack)
{
GArray *x11_stacked;
GArray *x11_root_children_stacked;
GArray *all_root_children_stacked; /* wayland OR x11 */
GArray *stacked;
GArray *root_children_stacked;
GList *tmp;
GArray *x11_hidden;
GArray *x11_hidden_stack_windows;
GArray *all_hidden;
int n_override_redirect = 0;
MetaStackWindow guard_stack_window;
/* Bail out if frozen */
if (stack->freeze_count > 0)
@@ -1272,17 +1166,13 @@ stack_sync_to_xserver (MetaStack *stack)
* _NET hints, and "root_children_stacked" is in top-to-bottom
* order for XRestackWindows()
*/
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
x11_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
x11_hidden_stack_windows = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
x11_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
stacked = g_array_new (FALSE, FALSE, sizeof (Window));
root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
/* The screen guard window sits above all hidden windows and acts as
* a barrier to input reaching these windows. */
g_array_append_val (x11_hidden, stack->screen->guard_window);
g_array_append_val (all_hidden, stack->screen->guard_window);
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
meta_push_no_msg_prefix ();
@@ -1291,9 +1181,6 @@ stack_sync_to_xserver (MetaStack *stack)
{
MetaWindow *w = tmp->data;
Window top_level_window;
MetaStackWindow stack_window;
stack_window.any.type = w->client_type;
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
w->layer, w->stack_position, w->desc);
@@ -1302,93 +1189,60 @@ stack_sync_to_xserver (MetaStack *stack)
if (w->override_redirect)
n_override_redirect++;
else
g_array_prepend_val (x11_stacked, w->xwindow);
g_array_prepend_val (stacked, w->xwindow);
if (w->frame)
top_level_window = w->frame->xwindow;
else
top_level_window = w->xwindow;
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
stack_window.x11.xwindow = top_level_window;
else
stack_window.wayland.meta_window = w;
/* We don't restack hidden windows along with the rest, though they are
* reflected in the _NET hints. Hidden windows all get pushed below
* the screens fullscreen guard_window. */
if (w->hidden)
{
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
MetaStackWindow stack_window;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = top_level_window;
g_array_append_val (x11_hidden_stack_windows, stack_window);
g_array_append_val (x11_hidden, top_level_window);
}
g_array_append_val (all_hidden, top_level_window);
continue;
}
g_array_append_val (all_root_children_stacked, stack_window);
/* build XRestackWindows() array from top to bottom */
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (x11_root_children_stacked, top_level_window);
else
{
MetaStackWindow *new;
/* So we can determine later if a cached stack window is
* stale because the corresponding window has been freed we
* associate a weak pointer with the new window. */
new = &g_array_index (all_root_children_stacked, MetaStackWindow, all_root_children_stacked->len - 1);
g_object_add_weak_pointer (G_OBJECT (new->wayland.meta_window),
(gpointer *)&new->wayland.meta_window);
}
g_array_append_val (root_children_stacked, top_level_window);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
/* All X windows should be in some stacking order */
if (x11_stacked->len != stack->xwindows->len - n_override_redirect)
/* All windows should be in some stacking order */
if (stacked->len != stack->windows->len - n_override_redirect)
meta_bug ("%u windows stacked, %u windows exist in stack\n",
x11_stacked->len, stack->xwindows->len);
stacked->len, stack->windows->len);
/* Sync to server */
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
all_root_children_stacked->len);
root_children_stacked->len);
meta_error_trap_push (stack->screen->display);
if (stack->last_all_root_children_stacked == NULL)
if (stack->last_root_children_stacked == NULL)
{
/* Just impose our stack, we don't know the previous state.
* This involves a ton of circulate requests and may flicker.
*/
meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n");
if (all_root_children_stacked->len > 1)
if (root_children_stacked->len > 0)
{
gulong serial = 0;
if (x11_root_children_stacked->len > 1)
{
serial = XNextRequest (stack->screen->display->xdisplay);
XRestackWindows (stack->screen->display->xdisplay,
(Window *) x11_root_children_stacked->data,
x11_root_children_stacked->len);
}
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(MetaStackWindow *) all_root_children_stacked->data,
all_root_children_stacked->len,
serial);
(Window *) root_children_stacked->data,
root_children_stacked->len,
XNextRequest (stack->screen->display->xdisplay));
XRestackWindows (stack->screen->display->xdisplay,
(Window *) root_children_stacked->data,
root_children_stacked->len);
}
}
else if (all_root_children_stacked->len > 0)
else if (root_children_stacked->len > 0)
{
/* Try to do minimal window moves to get the stack in order */
/* A point of note: these arrays include frames not client windows,
@@ -1396,34 +1250,28 @@ stack_sync_to_xserver (MetaStack *stack)
* was saved, then we may have inefficiency, but I don't think things
* break...
*/
const MetaStackWindow *old_stack = (MetaStackWindow *) stack->last_all_root_children_stacked->data;
const MetaStackWindow *new_stack = (MetaStackWindow *) all_root_children_stacked->data;
const int old_len = stack->last_all_root_children_stacked->len;
const int new_len = all_root_children_stacked->len;
const MetaStackWindow *oldp = old_stack;
const MetaStackWindow *newp = new_stack;
const MetaStackWindow *old_end = old_stack + old_len;
const MetaStackWindow *new_end = new_stack + new_len;
Window last_xwindow = None;
const MetaStackWindow *last_window = NULL;
const Window *old_stack = (Window *) stack->last_root_children_stacked->data;
const Window *new_stack = (Window *) root_children_stacked->data;
const int old_len = stack->last_root_children_stacked->len;
const int new_len = root_children_stacked->len;
const Window *oldp = old_stack;
const Window *newp = new_stack;
const Window *old_end = old_stack + old_len;
const Window *new_end = new_stack + new_len;
Window last_window = None;
while (oldp != old_end &&
newp != new_end)
{
if (meta_stack_window_equal (oldp, newp))
if (*oldp == *newp)
{
/* Stacks are the same here, move on */
++oldp;
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
last_xwindow = newp->x11.xwindow;
last_window = newp;
last_window = *newp;
++newp;
}
else if ((oldp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
meta_display_lookup_x_window (stack->screen->display,
oldp->x11.xwindow) == NULL) ||
(oldp->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
oldp->wayland.meta_window == NULL))
else if (meta_display_lookup_x_window (stack->screen->display,
*oldp) == NULL)
{
/* *oldp is no longer known to us (probably destroyed),
* so we can just skip it
@@ -1432,161 +1280,75 @@ stack_sync_to_xserver (MetaStack *stack)
}
else
{
/* Move *newp below the last_window */
if (!last_window)
/* Move *newp below last_window */
if (last_window == None)
{
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n",
newp->x11.xwindow);
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp);
raise_window_relative_to_managed_windows (stack->screen, newp);
}
else if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
last_xwindow == None)
{
/* In this case we have an X window that we need to
* put below a wayland window and this is the
* topmost X window. */
/* In X terms (because this is the topmost X window)
* we want to
* raise_window_relative_to_managed_windows() to
* ensure the X window is below override-redirect
* pop-up windows.
*
* In Wayland terms we just want to ensure
* newp is lowered below last_window (which
* notably doesn't require an X request because we
* know last_window isn't an X window).
*/
raise_window_relative_to_managed_windows (stack->screen, newp);
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
newp, last_window,
0); /* no x request serial */
raise_window_relative_to_managed_windows (stack->screen,
*newp);
}
else
{
gulong serial = 0;
/* This means that if last_xwindow is dead, but not
/* This means that if last_window is dead, but not
* *newp, then we fail to restack *newp; but on
* unmanaging last_xwindow, we'll fix it up.
* unmanaging last_window, we'll fix it up.
*/
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
newp->any.type == META_WINDOW_CLIENT_TYPE_X11 ? newp->x11.xwindow : 0,
last_xwindow);
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
XWindowChanges changes;
serial = XNextRequest (stack->screen->display->xdisplay);
changes.sibling = last_xwindow;
changes.sibling = last_window;
changes.stack_mode = Below;
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
*newp, last_window);
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
*newp, last_window,
XNextRequest (stack->screen->display->xdisplay));
XConfigureWindow (stack->screen->display->xdisplay,
newp->x11.xwindow,
*newp,
CWSibling | CWStackMode,
&changes);
}
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
newp, last_window,
serial);
}
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
last_xwindow = newp->x11.xwindow;
last_window = newp;
last_window = *newp;
++newp;
}
}
if (newp != new_end)
{
const MetaStackWindow *x_ref;
unsigned long serial = 0;
/* Restack remaining windows */
meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
(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 */
if (newp != new_stack)
for (x_ref = newp - 1;
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
x_ref--)
;
else
x_ref = new_stack;
/* If we didn't find an X window looking backwards then walk forwards
* through the remaining windows to find the first remaining X window
* instead. */
if (x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11)
{
for (x_ref = newp;
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
x_ref++)
;
}
/* If there are any X windows remaining unstacked then restack them */
if (x_ref->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
int i;
for (i = x11_root_children_stacked->len - 1; i; i--)
{
Window *reference = &g_array_index (x11_root_children_stacked, Window, i);
if (*reference == x_ref->x11.xwindow)
{
int n = x11_root_children_stacked->len - i;
/* There's no point restacking if there's only one X window */
if (n == 1)
break;
serial = XNextRequest (stack->screen->display->xdisplay);
XRestackWindows (stack->screen->display->xdisplay,
reference, n);
break;
}
}
}
/* We need to include an already-stacked window
* in the restack call, so we get in the proper position
* with respect to it.
*/
if (newp != new_stack)
newp = MIN (newp - 1, x_ref);
--newp;
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
newp, new_end - newp,
serial);
(Window *) newp, new_end - newp,
XNextRequest (stack->screen->display->xdisplay));
XRestackWindows (stack->screen->display->xdisplay,
(Window *) newp, new_end - newp);
}
}
/* Push hidden X windows to the bottom of the stack under the guard window */
guard_stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
guard_stack_window.x11.xwindow = stack->screen->guard_window;
/* Push hidden windows to the bottom of the stack under the guard window */
meta_stack_tracker_record_lower (stack->screen->stack_tracker,
&guard_stack_window,
stack->screen->guard_window,
XNextRequest (stack->screen->display->xdisplay));
XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(MetaStackWindow *)x11_hidden_stack_windows->data,
x11_hidden_stack_windows->len,
(Window *)all_hidden->data,
all_hidden->len,
XNextRequest (stack->screen->display->xdisplay));
XRestackWindows (stack->screen->display->xdisplay,
(Window *)x11_hidden->data,
x11_hidden->len);
g_array_free (x11_hidden, TRUE);
g_array_free (x11_hidden_stack_windows, TRUE);
(Window *)all_hidden->data,
all_hidden->len);
g_array_free (all_hidden, TRUE);
meta_error_trap_pop (stack->screen->display);
/* on error, a window was destroyed; it should eventually
@@ -1601,23 +1363,21 @@ stack_sync_to_xserver (MetaStack *stack)
stack->screen->display->atom__NET_CLIENT_LIST,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)stack->xwindows->data,
stack->xwindows->len);
(unsigned char *)stack->windows->data,
stack->windows->len);
XChangeProperty (stack->screen->display->xdisplay,
stack->screen->xroot,
stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)x11_stacked->data,
x11_stacked->len);
(unsigned char *)stacked->data,
stacked->len);
g_array_free (x11_stacked, TRUE);
g_array_free (stacked, TRUE);
if (stack->last_all_root_children_stacked)
free_last_all_root_children_stacked_cache (stack);
stack->last_all_root_children_stacked = all_root_children_stacked;
g_array_free (x11_root_children_stacked, TRUE);
if (stack->last_root_children_stacked)
g_array_free (stack->last_root_children_stacked, TRUE);
stack->last_root_children_stacked = root_children_stacked;
/* That was scary... */
}
@@ -1978,7 +1738,7 @@ meta_stack_set_positions (MetaStack *stack,
meta_topic (META_DEBUG_STACK,
"Reset the stack positions of (nearly) all windows\n");
stack_sync_to_xserver (stack);
stack_sync_to_server (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@@ -2041,7 +1801,7 @@ meta_window_set_stack_position (MetaWindow *window,
int position)
{
meta_window_set_stack_position_no_sync (window, position);
stack_sync_to_xserver (window->screen->stack);
stack_sync_to_server (window->screen->stack);
meta_stack_update_window_tile_matches (window->screen->stack,
window->screen->active_workspace);
}

View File

@@ -60,7 +60,7 @@ struct _MetaStack
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
*/
GArray *xwindows;
GArray *windows;
/** The MetaWindows of the windows we manage, sorted in order. */
GList *sorted;
@@ -99,7 +99,7 @@ struct _MetaStack
* The last-known stack of all windows, bottom to top. We cache it here
* so that subsequent times we'll be able to do incremental moves.
*/
GArray *last_all_root_children_stacked;
GArray *last_root_children_stacked;
/**
* Number of stack positions; same as the length of added, but

View File

@@ -55,7 +55,6 @@ static gint verbose_topics = 0;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
static int no_prefix = 0;
static gboolean is_wayland_compositor = FALSE;
#ifdef WITH_VERBOSE_MODE
static FILE* logfile = NULL;
@@ -195,18 +194,6 @@ meta_set_replace_current_wm (gboolean setting)
replace_current = setting;
}
gboolean
meta_is_wayland_compositor (void)
{
return is_wayland_compositor;
}
void
meta_set_is_wayland_compositor (gboolean value)
{
is_wayland_compositor = value;
}
char *
meta_g_utf8_strndup (const gchar *src,
gsize n)
@@ -345,8 +332,6 @@ topic_name (MetaDebugTopic topic)
return "COMPOSITOR";
case META_DEBUG_EDGE_RESISTANCE:
return "EDGE_RESISTANCE";
case META_DEBUG_DBUS:
return "DBUS";
case META_DEBUG_VERBOSE:
return "VERBOSE";
}
@@ -652,13 +637,8 @@ meta_show_dialog (const char *type,
append_argument (args, "zenity");
append_argument (args, type);
if (display)
{
append_argument (args, "--display");
append_argument (args, display);
}
append_argument (args, "--display");
append_argument (args, display);
append_argument (args, "--class");
append_argument (args, "mutter-dialog");
append_argument (args, "--title");

View File

@@ -44,15 +44,6 @@
#include <X11/Xutil.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "meta-wayland-private.h"
/* XXX: We should find a nicer approach to deal with the
* circular dependency we have with the current headers
* (meta-wayland-private.h which typedefs MetaWaylandSurface
* also includes window-private.h) */
#ifndef HAVE_META_WAYLAND_SURFACE_TYPE
typedef struct _MetaWaylandSurface MetaWaylandSurface;
#endif
typedef struct _MetaWindowQueue MetaWindowQueue;
@@ -78,7 +69,6 @@ typedef enum {
_NET_WM_BYPASS_COMPOSITOR_HINT_OFF = 2,
} MetaBypassCompositorHintValue;
struct _MetaWindow
{
GObject parent_instance;
@@ -87,10 +77,6 @@ struct _MetaWindow
MetaScreen *screen;
const MetaMonitorInfo *monitor;
MetaWorkspace *workspace;
MetaWindowClientType client_type;
#ifdef HAVE_WAYLAND
MetaWaylandSurface *surface;
#endif
Window xwindow;
/* may be NULL! not all windows get decorated */
MetaFrame *frame;
@@ -179,7 +165,7 @@ struct _MetaWindow
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
* origin is on. */
gint fullscreen_monitors[4];
long fullscreen_monitors[4];
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
@@ -291,7 +277,7 @@ struct _MetaWindow
/* EWHH demands attention flag */
guint wm_state_demands_attention : 1;
/* TRUE iff window == window->display->focus_window */
/* this flag tracks receipt of focus_in focus_out */
guint has_focus : 1;
/* Have we placed this window? */
@@ -339,6 +325,9 @@ struct _MetaWindow
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
/* has a shape mask */
guint has_shape : 1;
/* icon props have changed */
guint need_reread_icon : 1;
@@ -360,15 +349,9 @@ struct _MetaWindow
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
/* if non-NULL, the bounding shape region of the window */
cairo_region_t *shape_region;
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
cairo_region_t *opaque_region;
/* the input shape region for picking */
cairo_region_t *input_region;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
@@ -411,9 +394,6 @@ struct _MetaWindow
*/
MetaRectangle rect;
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
@@ -507,10 +487,6 @@ MetaWindow* meta_window_new_with_attrs (MetaDisplay *display,
gboolean must_be_viewable,
MetaCompEffect effect,
XWindowAttributes *attrs);
MetaWindow *meta_window_new_for_wayland (MetaDisplay *display,
int width,
int height,
MetaWaylandSurface *surface);
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);
@@ -614,8 +590,9 @@ gboolean meta_window_property_notify (MetaWindow *window,
XEvent *event);
gboolean meta_window_client_message (MetaWindow *window,
XEvent *event);
void meta_window_set_focused_internal (MetaWindow *window,
gboolean focused);
gboolean meta_window_notify_focus (MetaWindow *window,
XIEnterEvent *event);
void meta_window_lost_focus (MetaWindow *window);
void meta_window_set_current_workspace_hint (MetaWindow *window);
@@ -686,6 +663,7 @@ void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_role (MetaWindow *window);
void meta_window_update_net_wm_type (MetaWindow *window);
void meta_window_update_opaque_region (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
@@ -699,16 +677,4 @@ void meta_window_compute_tile_match (MetaWindow *window);
gboolean meta_window_updates_are_frozen (MetaWindow *window);
void meta_window_set_opaque_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_opaque_region_x11 (MetaWindow *window);
void meta_window_set_input_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_input_region_x11 (MetaWindow *window);
void meta_window_set_shape_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_shape_region_x11 (MetaWindow *window);
#endif

View File

@@ -289,35 +289,6 @@ reload_icon_geometry (MetaWindow *window,
}
}
static void
reload_gtk_frame_extents (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (value->type != META_PROP_VALUE_INVALID)
{
if (value->v.cardinal_list.n_cardinals != 4)
{
meta_verbose ("_GTK_FRAME_EXTENTS on %s has %d values instead of 4\n",
window->desc, value->v.cardinal_list.n_cardinals);
}
else
{
GtkBorder *extents = &window->custom_frame_extents;
window->has_custom_frame_extents = TRUE;
extents->left = (int)value->v.cardinal_list.cardinals[0];
extents->right = (int)value->v.cardinal_list.cardinals[1];
extents->top = (int)value->v.cardinal_list.cardinals[2];
extents->bottom = (int)value->v.cardinal_list.cardinals[3];
}
}
else
{
window->has_custom_frame_extents = FALSE;
}
}
static void
reload_struts (MetaWindow *window,
MetaPropValue *value,
@@ -565,7 +536,7 @@ reload_opaque_region (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
meta_window_update_opaque_region_x11 (window);
meta_window_update_opaque_region (window);
}
static void
@@ -1795,7 +1766,6 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, TRUE, FALSE },
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, TRUE, FALSE },
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, TRUE, FALSE },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, TRUE, FALSE },
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
{ display->atom_WM_STATE, META_PROP_VALUE_INVALID, NULL, FALSE, FALSE },
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, FALSE, FALSE },

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +0,0 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Mutter.IdleMonitor:
@short_description: idle monitor interface
This interface is used by gnome-desktop to implement
user activity monitoring.
-->
<interface name="org.gnome.Mutter.IdleMonitor">
<method name="GetIdletime">
<arg name="idletime" direction="out" type="t"/>
</method>
<method name="AddIdleWatch">
<arg name="interval" direction="in" type="t" />
<arg name="id" direction="out" type="u" />
</method>
<method name="AddUserActiveWatch">
<arg name="id" direction="out" type="u" />
</method>
<method name="RemoveWatch">
<arg name="id" direction="in" type="u" />
</method>
<signal name="WatchFired">
<arg name="id" direction="out" type="u" />
</signal>
</interface>
</node>

View File

@@ -1,18 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
girdir=@libdir@/mutter-wayland
typelibdir=@libdir@/mutter-wayland
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter-wayland
Description: Mutter window manager library (Wayland branch)
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11 wayland-server
Version: @VERSION@
Libs: -L${libdir} -lmutter-wayland
Cflags: -I${includedir}/mutter-wayland -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}

18
src/libmutter.pc.in Normal file
View File

@@ -0,0 +1,18 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
girdir=@libdir@/mutter
typelibdir=@libdir@/mutter
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter
Description: Mutter window manager library
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
Version: @VERSION@
Libs: -L${libdir} -lmutter
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}

View File

@@ -54,6 +54,9 @@ item(WM_WINDOW_ROLE)
item(UTF8_STRING)
item(WM_ICON_SIZE)
item(_KWM_WIN_ICON)
item(_MUTTER_RELOAD_THEME_MESSAGE)
item(_MUTTER_SET_KEYBINDINGS_MESSAGE)
item(_MUTTER_TOGGLE_VERBOSE)
item(_MUTTER_HINTS)
item(_GTK_THEME_VARIANT)
item(_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED)
@@ -63,16 +66,12 @@ item(_GTK_APPLICATION_OBJECT_PATH)
item(_GTK_WINDOW_OBJECT_PATH)
item(_GTK_APP_MENU_OBJECT_PATH)
item(_GTK_MENUBAR_OBJECT_PATH)
item(_GTK_FRAME_EXTENTS)
item(_GNOME_WM_KEYBINDINGS)
item(_GNOME_PANEL_ACTION)
item(_GNOME_PANEL_ACTION_MAIN_MENU)
item(_GNOME_PANEL_ACTION_RUN_DIALOG)
item(_MUTTER_TIMESTAMP_PING)
item(_MUTTER_FOCUS_SET)
item(_MUTTER_SENTINEL)
item(_MUTTER_VERSION)
item(_MUTTER_PRESENTATION_OUTPUT)
item(WM_CLIENT_MACHINE)
item(MANAGER)
item(TARGETS)
@@ -80,7 +79,6 @@ item(MULTIPLE)
item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
item(BACKLIGHT)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

View File

@@ -35,6 +35,7 @@
/* Public compositor API */
ClutterActor *meta_get_stage_for_screen (MetaScreen *screen);
ClutterActor *meta_get_overlay_group_for_screen (MetaScreen *screen);
Window meta_get_overlay_window (MetaScreen *screen);
GList *meta_get_window_actors (MetaScreen *screen);
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
@@ -46,8 +47,5 @@ void meta_enable_unredirect_for_screen (MetaScreen *screen);
void meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region);
void meta_empty_stage_input_region (MetaScreen *screen);
void meta_focus_stage_window (MetaScreen *screen,
guint32 timestamp);
gboolean meta_stage_is_focused (MetaScreen *screen);
#endif

View File

@@ -165,10 +165,6 @@ void meta_display_set_input_focus_window (MetaDisplay *display,
gboolean focus_frame,
guint32 timestamp);
void meta_display_request_take_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp);
/* meta_display_focus_the_no_focus_window is called when the
* designated no_focus_window should be focused, but is otherwise the
* same as meta_display_set_input_focus_window

View File

@@ -1,50 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_H
#define META_CURSOR_TRACKER_H
#include <glib-object.h>
#include <meta/types.h>
#include <meta/workspace.h>
#include <cogl/cogl.h>
#define META_TYPE_CURSOR_TRACKER (meta_cursor_tracker_get_type ())
#define META_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTracker))
#define META_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER, MetaCursorTrackerClass))
#define META_IS_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER))
#define META_IS_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER))
#define META_CURSOR_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTrackerClass))
typedef struct _MetaCursorTrackerClass MetaCursorTrackerClass;
GType meta_cursor_tracker_get_type (void);
MetaCursorTracker *meta_cursor_tracker_get_for_screen (MetaScreen *screen);
void meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y);
CoglTexture *meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker);
#endif

View File

@@ -1,62 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_IDLE_MONITOR_H
#define META_IDLE_MONITOR_H
#include <glib-object.h>
#include <meta/types.h>
#define META_TYPE_IDLE_MONITOR (meta_idle_monitor_get_type ())
#define META_IDLE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR, MetaIdleMonitor))
#define META_IDLE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR, MetaIdleMonitorClass))
#define META_IS_IDLE_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR))
#define META_IS_IDLE_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR))
#define META_IDLE_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR, MetaIdleMonitorClass))
typedef struct _MetaIdleMonitor MetaIdleMonitor;
typedef struct _MetaIdleMonitorClass MetaIdleMonitorClass;
GType meta_idle_monitor_get_type (void);
typedef void (*MetaIdleMonitorWatchFunc) (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data);
MetaIdleMonitor *meta_idle_monitor_get_core (void);
MetaIdleMonitor *meta_idle_monitor_get_for_device (int device_id);
guint meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);
guint meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);
void meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id);
gint64 meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor);
#endif

View File

@@ -205,21 +205,6 @@ struct _MetaPluginClass
gboolean (*keybinding_filter) (MetaPlugin *plugin,
MetaKeyBinding *binding);
/**
* MetaPluginClass::confirm_display_config:
* @plugin: a #MetaPlugin
*
* Virtual function called when the display configuration changes.
* The common way to implement this function is to show some form
* of modal dialog that should ask the user if everything was ok.
*
* When confirmed by the user, the plugin must call meta_plugin_complete_display_change()
* to make the configuration permanent. If that function is not
* called within the timeout, the previous configuration will be
* reapplied.
*/
void (*confirm_display_change) (MetaPlugin *plugin);
/**
* MetaPluginClass::plugin_info:
* @plugin: a #MetaPlugin
@@ -229,7 +214,6 @@ struct _MetaPluginClass
* Returns: a #MetaPluginInfo.
*/
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
};
/**
@@ -376,10 +360,6 @@ void
meta_plugin_destroy_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok);
/**
* MetaModalOptions:
* @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already
@@ -396,6 +376,8 @@ typedef enum {
gboolean
meta_plugin_begin_modal (MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);

View File

@@ -64,6 +64,8 @@ struct _MetaShapedTexture
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps);
@@ -73,20 +75,18 @@ void meta_shaped_texture_update_area (MetaShapedTexture *stex,
int width,
int height);
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap);
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
CoglTexture *mask_texture);
void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
cairo_region_t *shape_region);
/* Assumes ownership of clip_region */
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region);
void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
cairo_region_t *opaque_region);
cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex,
cairo_rectangle_int_t *clip);

View File

@@ -64,6 +64,7 @@ gint meta_window_actor_get_workspace (MetaWindowActor *self
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
gboolean meta_window_actor_is_override_redirect (MetaWindowActor *self);
const char * meta_window_actor_get_description (MetaWindowActor *self);
gboolean meta_window_actor_showing_on_its_workspace (MetaWindowActor *self);
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);

View File

@@ -49,6 +49,7 @@
* @META_PREF_TITLEBAR_FONT: title-bar font
* @META_PREF_NUM_WORKSPACES: number of workspaces
* @META_PREF_DYNAMIC_WORKSPACES: dynamic workspaces
* @META_PREF_APPLICATION_BASED: application-based
* @META_PREF_KEYBINDINGS: keybindings
* @META_PREF_DISABLE_WORKAROUNDS: disable workarounds
* @META_PREF_BUTTON_LAYOUT: button layout
@@ -87,6 +88,7 @@ typedef enum
META_PREF_TITLEBAR_FONT,
META_PREF_NUM_WORKSPACES,
META_PREF_DYNAMIC_WORKSPACES,
META_PREF_APPLICATION_BASED,
META_PREF_KEYBINDINGS,
META_PREF_DISABLE_WORKAROUNDS,
META_PREF_BUTTON_LAYOUT,
@@ -134,6 +136,7 @@ const char* meta_prefs_get_theme (void);
const PangoFontDescription* meta_prefs_get_titlebar_font (void);
int meta_prefs_get_num_workspaces (void);
gboolean meta_prefs_get_dynamic_workspaces (void);
gboolean meta_prefs_get_application_based (void);
gboolean meta_prefs_get_disable_workarounds (void);
gboolean meta_prefs_get_auto_raise (void);
int meta_prefs_get_auto_raise_delay (void);

87
src/meta/preview-widget.h Normal file
View File

@@ -0,0 +1,87 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity theme preview widget */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#include <meta/common.h>
#include <meta/theme.h>
#include <gtk/gtk.h>
#ifndef META_PREVIEW_WIDGET_H
#define META_PREVIEW_WIDGET_H
#define META_TYPE_PREVIEW (meta_preview_get_type ())
#define META_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PREVIEW, MetaPreview))
#define META_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass))
#define META_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PREVIEW))
#define META_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW))
#define META_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass))
typedef struct _MetaPreview MetaPreview;
typedef struct _MetaPreviewClass MetaPreviewClass;
struct _MetaPreview
{
GtkBin bin;
GtkStyleContext *style_context;
MetaTheme *theme;
char *title;
MetaFrameType type;
MetaFrameFlags flags;
PangoLayout *layout;
int text_height;
MetaFrameBorders borders;
guint borders_cached : 1;
MetaButtonLayout button_layout;
};
struct _MetaPreviewClass
{
/*< private >*/
GtkBinClass parent_class;
};
GType meta_preview_get_type (void) G_GNUC_CONST;
GtkWidget* meta_preview_new (void);
void meta_preview_set_theme (MetaPreview *preview,
MetaTheme *theme);
void meta_preview_set_title (MetaPreview *preview,
const char *title);
void meta_preview_set_frame_type (MetaPreview *preview,
MetaFrameType type);
void meta_preview_set_frame_flags (MetaPreview *preview,
MetaFrameFlags flags);
void meta_preview_set_button_layout (MetaPreview *preview,
const MetaButtonLayout *button_layout);
GdkPixbuf* meta_preview_get_icon (void);
GdkPixbuf* meta_preview_get_mini_icon (void);
#endif

View File

@@ -33,7 +33,8 @@
typedef struct _MetaTheme MetaTheme;
MetaTheme* meta_theme_get_current (void);
void meta_theme_set_current (const char *name);
void meta_theme_set_current (const char *name,
gboolean force_reload);
MetaTheme* meta_theme_new (void);
void meta_theme_free (MetaTheme *theme);

View File

@@ -38,6 +38,5 @@ typedef struct _MetaWorkspace MetaWorkspace;
*/
typedef struct _MetaGroup MetaGroup;
typedef struct _MetaKeyBinding MetaKeyBinding;
typedef struct _MetaCursorTracker MetaCursorTracker;
#endif

View File

@@ -37,8 +37,6 @@ void meta_set_debugging (gboolean setting);
gboolean meta_is_syncing (void);
void meta_set_syncing (gboolean setting);
void meta_set_replace_current_wm (gboolean setting);
gboolean meta_is_wayland_compositor (void);
void meta_set_is_wayland_compositor (gboolean setting);
void meta_debug_spew_real (const char *format,
...) G_GNUC_PRINTF (1, 2);
@@ -102,8 +100,7 @@ typedef enum
META_DEBUG_RESIZING = 1 << 18,
META_DEBUG_SHAPES = 1 << 19,
META_DEBUG_COMPOSITOR = 1 << 20,
META_DEBUG_EDGE_RESISTANCE = 1 << 21,
META_DEBUG_DBUS = 1 << 22
META_DEBUG_EDGE_RESISTANCE = 1 << 21
} MetaDebugTopic;
void meta_topic_real (MetaDebugTopic topic,

View File

@@ -81,16 +81,6 @@ typedef enum
META_MAXIMIZE_VERTICAL = 1 << 1
} MetaMaximizeFlags;
/**
* MetaWindowClientType:
* @META_WINDOW_CLIENT_TYPE_WAYLAND: A Wayland based window
* @META_WINDOW_CLIENT_TYPE_X11: An X11 based window
*/
typedef enum {
META_WINDOW_CLIENT_TYPE_WAYLAND,
META_WINDOW_CLIENT_TYPE_X11
} MetaWindowClientType;
#define META_TYPE_WINDOW (meta_window_get_type ())
#define META_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW, MetaWindow))
#define META_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW, MetaWindowClass))
@@ -247,6 +237,4 @@ void meta_window_begin_grab_op (MetaWindow *window,
gboolean frame_action,
guint32 timestamp);
gboolean meta_window_can_close (MetaWindow *window);
#endif

17
src/mutter-plugins.pc.in Normal file
View File

@@ -0,0 +1,17 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
plugindir=@MUTTER_PLUGIN_DIR@
libgnome_serverdir=@libexecdir@
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: mutter-plugins
Description: Dev parameters for mutter plugins
Requires: @CLUTTER_PACKAGE@
Version: @VERSION@
Libs: @CLUTTER_LIBS@
Cflags: @CLUTTER_CFLAGS@ -DWITH_CLUTTER -I${includedir}/mutter/mutter-private -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version} -DMUTTER_PLUGIN_DIR=\"${plugindir}\"

20
src/mutter-wm.desktop.in Normal file
View File

@@ -0,0 +1,20 @@
[Desktop Entry]
Type=Application
_Name=Mutter
Exec=mutter
# name of loadable control center module
X-GNOME-WMSettingsModule=metacity
# name we put on the WM spec check window
X-GNOME-WMName=Mutter
# back compat only
X-GnomeWMSettingsLibrary=metacity
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=mutter
X-GNOME-Bugzilla-Component=general
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=windowmanager
X-GNOME-Autostart-Notify=true
[Window Manager]
SessionManaged=true

View File

@@ -1,7 +1,7 @@
[Desktop Entry]
Type=Application
_Name=Mutter (wayland compositor)
Exec=mutter-launch -- mutter --nested
_Name=Mutter
Exec=mutter
NoDisplay=true
# name of loadable control center module
X-GNOME-WMSettingsModule=metacity
@@ -12,5 +12,6 @@ X-GnomeWMSettingsLibrary=metacity
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=mutter
X-GNOME-Bugzilla-Component=general
X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=windowmanager
X-GNOME-Autostart-Notify=true

BIN
src/stock_delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
src/stock_maximize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

BIN
src/stock_minimize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

8
src/tools/.cvsignore Normal file
View File

@@ -0,0 +1,8 @@
Makefile
Makefile.in
metacity-grayscale
metacity-message
metacity-mag
metacity-properties
metacity-properties.desktop
metacity-window-demo

34
src/tools/Makefile.am Normal file
View File

@@ -0,0 +1,34 @@
@INTLTOOL_DESKTOP_RULE@
icondir=$(pkgdatadir)/icons
icon_DATA=mutter-window-demo.png
INCLUDES=@MUTTER_WINDOW_DEMO_CFLAGS@ @MUTTER_MESSAGE_CFLAGS@ \
-I$(top_srcdir)/src \
-DMUTTER_ICON_DIR=\"$(pkgdatadir)/icons\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"
mutter_message_SOURCES= \
mutter-message.c
mutter_window_demo_SOURCES= \
mutter-window-demo.c
mutter_mag_SOURCES= \
mutter-mag.c
mutter_grayscale_SOURCES= \
mutter-grayscale.c
bin_PROGRAMS=mutter-message mutter-window-demo
## cheesy hacks I use, don't really have any business existing. ;-)
noinst_PROGRAMS=mutter-mag mutter-grayscale
mutter_message_LDADD= @MUTTER_MESSAGE_LIBS@
mutter_window_demo_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
mutter_mag_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
mutter_grayscale_LDADD = @MUTTER_WINDOW_DEMO_LIBS@
EXTRA_DIST=$(icon_DATA)

View File

@@ -0,0 +1,107 @@
/* Hack for grayscaling an image */
/*
* Copyright (C) 2002 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
static GdkPixbuf*
grayscale_pixbuf (GdkPixbuf *pixbuf)
{
GdkPixbuf *gray;
guchar *pixels;
int rowstride;
int pixstride;
int row;
int n_rows;
int width;
gray = gdk_pixbuf_copy (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (gray);
pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3;
pixels = gdk_pixbuf_get_pixels (gray);
n_rows = gdk_pixbuf_get_height (gray);
width = gdk_pixbuf_get_width (gray);
row = 0;
while (row < n_rows)
{
guchar *p = pixels + row * rowstride;
guchar *end = p + (pixstride * width);
while (p != end)
{
double v = INTENSITY (p[0], p[1], p[2]);
p[0] = (guchar) v;
p[1] = (guchar) v;
p[2] = (guchar) v;
p += pixstride;
}
++row;
}
return gray;
}
int
main (int argc, char **argv)
{
GdkPixbuf *pixbuf;
GdkPixbuf *gray;
GError *err;
if (argc != 2)
{
g_printerr ("specify a single image on the command line\n");
return 1;
}
err = NULL;
pixbuf = gdk_pixbuf_new_from_file (argv[1], &err);
if (err != NULL)
{
g_printerr ("failed to load image: %s\n", err->message);
g_error_free (err);
return 1;
}
gray = grayscale_pixbuf (pixbuf);
err = NULL;
gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL);
if (err != NULL)
{
g_printerr ("failed to save image: %s\n", err->message);
g_error_free (err);
return 1;
}
g_print ("wrote grayscale.png\n");
return 0;
}

299
src/tools/mutter-mag.c Normal file
View File

@@ -0,0 +1,299 @@
/* Hack for use instead of xmag */
/*
* Copyright (C) 2002 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600 /* C99 -- for rint() */
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
static GtkWidget *grab_widget = NULL;
static GtkWidget *display_window = NULL;
static int last_grab_x = 0;
static int last_grab_y = 0;
static int last_grab_width = 150;
static int last_grab_height = 150;
static GtkAllocation last_grab_allocation;
static double width_factor = 4.0;
static double height_factor = 4.0;
static GdkInterpType interp_mode = GDK_INTERP_NEAREST;
static guint regrab_idle_id = 0;
static GdkPixbuf*
get_pixbuf (void)
{
GdkPixbuf *screenshot;
GdkPixbuf *magnified;
#if 0
g_print ("Size %d x %d\n",
last_grab_width, last_grab_height);
#endif
screenshot = gdk_pixbuf_get_from_window (gdk_get_default_root_window (),
last_grab_x, last_grab_y,
last_grab_width, last_grab_height);
if (screenshot == NULL)
{
g_printerr ("Screenshot failed\n");
exit (1);
}
magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor,
last_grab_height * height_factor,
interp_mode);
g_object_unref (G_OBJECT (screenshot));
return magnified;
}
static gboolean
regrab_idle (GtkWidget *image)
{
GtkAllocation allocation;
GdkPixbuf *magnified;
gtk_widget_get_allocation (image, &allocation);
if (allocation.width != last_grab_allocation.width ||
allocation.height != last_grab_allocation.height)
{
last_grab_width = rint (allocation.width / width_factor);
last_grab_height = rint (allocation.height / height_factor);
last_grab_allocation = allocation;
magnified = get_pixbuf ();
gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified);
g_object_unref (G_OBJECT (magnified));
}
regrab_idle_id = 0;
return FALSE;
}
static void
image_resized (GtkWidget *image)
{
if (regrab_idle_id == 0)
regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle,
image, NULL);
}
static void
grab_area_at_mouse (GtkWidget *invisible,
int x_root,
int y_root)
{
GdkPixbuf *magnified;
int width, height;
GtkWidget *widget;
width = last_grab_width;
height = last_grab_height;
last_grab_x = x_root;
last_grab_y = y_root;
last_grab_width = width;
last_grab_height = height;
magnified = get_pixbuf ();
display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (display_window),
last_grab_width, last_grab_height);
widget = gtk_image_new_from_pixbuf (magnified);
gtk_widget_set_size_request (widget, 40, 40);
gtk_container_add (GTK_CONTAINER (display_window), widget);
g_object_unref (G_OBJECT (magnified));
g_object_add_weak_pointer (G_OBJECT (display_window),
(gpointer) &display_window);
g_signal_connect (G_OBJECT (display_window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL);
gtk_widget_show_all (display_window);
}
static void
shutdown_grab (void)
{
GdkDeviceManager *manager;
GdkDevice *device;
manager = gdk_display_get_device_manager (gdk_display_get_default ());
device = gdk_device_manager_get_client_pointer (manager);
gdk_device_ungrab (device, gtk_get_current_event_time ());
gdk_device_ungrab (gdk_device_get_associated_device (device),
gtk_get_current_event_time ());
gtk_grab_remove (grab_widget);
}
static void
mouse_motion (GtkWidget *invisible,
GdkEventMotion *event,
gpointer data)
{
}
static gboolean
mouse_release (GtkWidget *invisible,
GdkEventButton *event,
gpointer data)
{
if (event->button != 1)
return FALSE;
grab_area_at_mouse (invisible, event->x_root, event->y_root);
shutdown_grab ();
g_signal_handlers_disconnect_by_func (invisible, mouse_motion, NULL);
g_signal_handlers_disconnect_by_func (invisible, mouse_release, NULL);
return TRUE;
}
/* Helper Functions */
static gboolean mouse_press (GtkWidget *invisible,
GdkEventButton *event,
gpointer data);
static gboolean
key_press (GtkWidget *invisible,
GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_KEY_Escape)
{
shutdown_grab ();
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
gtk_main_quit ();
return TRUE;
}
return FALSE;
}
static gboolean
mouse_press (GtkWidget *invisible,
GdkEventButton *event,
gpointer data)
{
if (event->type == GDK_BUTTON_PRESS &&
event->button == 1)
{
g_signal_connect (invisible, "motion_notify_event",
G_CALLBACK (mouse_motion), NULL);
g_signal_connect (invisible, "button_release_event",
G_CALLBACK (mouse_release), NULL);
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
return TRUE;
}
return FALSE;
}
static void
begin_area_grab (void)
{
GdkWindow *window;
GdkDeviceManager *manager;
GdkDevice *device;
if (grab_widget == NULL)
{
grab_widget = gtk_invisible_new ();
gtk_widget_add_events (grab_widget,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
gtk_widget_show (grab_widget);
}
window = gtk_widget_get_window (grab_widget);
manager = gdk_display_get_device_manager (gdk_display_get_default ());
device = gdk_device_manager_get_client_pointer (manager);
if (gdk_device_grab (device,
window,
GDK_OWNERSHIP_NONE,
FALSE,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
NULL,
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
{
g_warning ("Failed to grab pointer to do eyedropper");
return;
}
if (gdk_device_grab (gdk_device_get_associated_device (device),
window,
GDK_OWNERSHIP_NONE,
FALSE,
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
NULL,
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
{
gdk_device_ungrab (device, gtk_get_current_event_time ());
g_warning ("Failed to grab keyboard to do eyedropper");
return;
}
gtk_grab_add (grab_widget);
g_signal_connect (grab_widget, "button_press_event",
G_CALLBACK (mouse_press), NULL);
g_signal_connect (grab_widget, "key_press_event",
G_CALLBACK (key_press), NULL);
}
int
main (int argc, char **argv)
{
gtk_init (&argc, &argv);
begin_area_grab ();
gtk_main ();
return 0;
}

160
src/tools/mutter-message.c Normal file
View File

@@ -0,0 +1,160 @@
/* Mutter send-magic-messages app */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
static Display *display;
static void
send_reload_theme (void)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_RELOAD_THEME_MESSAGE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
static void
send_set_keybindings (gboolean enabled)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_SET_KEYBINDINGS_MESSAGE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = enabled;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
#ifdef WITH_VERBOSE_MODE
static void
send_toggle_verbose (void)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_TOGGLE_VERBOSE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
#endif
static void
usage (void)
{
g_printerr (_("Usage: %s\n"),
"mutter-message (reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)");
exit (1);
}
int
main (int argc, char **argv)
{
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
gtk_init (&argc, &argv);
if (argc < 2)
usage ();
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
if (strcmp (argv[1], "reload-theme") == 0)
send_reload_theme ();
else if (strcmp (argv[1], "enable-keybindings") == 0)
send_set_keybindings (TRUE);
else if (strcmp (argv[1], "disable-keybindings") == 0)
send_set_keybindings (FALSE);
else if (strcmp (argv[1], "toggle-verbose") == 0)
{
#ifndef WITH_VERBOSE_MODE
g_printerr (_("Mutter was compiled without support for verbose mode\n"));
return 1;
#else
send_toggle_verbose ();
#endif
}
else
usage ();
return 0;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -739,6 +739,22 @@ 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_get_corner_radiuses (MetaFrames *frames,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, xwindow);
meta_ui_frame_get_corner_radiuses (frames, frame, top_left, top_right,
bottom_left, bottom_right);
}
void
meta_frames_reset_bg (MetaFrames *frames,
Window xwindow)
@@ -1835,102 +1851,6 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
cairo_region_destroy (frame_border);
}
#define TAU (2*M_PI)
/*
* Draw the opaque and semi-opaque pixels of this frame into a mask.
*
* (0,0) in Cairo coordinates is assumed to be the top left corner of the
* invisible border.
*
* The parts of @cr's surface in the clip region are assumed to be
* initialized to fully-transparent, and the clip region is assumed to
* contain the invisible border and the visible parts of the frame, but
* not the client area.
*
* This function uses @cr to draw pixels of arbitrary color (it will
* typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is
* discarded anyway) with appropriate alpha values to reproduce this
* frame's alpha channel, as a mask to be applied to an opaque pixmap.
*
* @frame: This frame
* @xwindow: The X window for the frame, which has the client window as a child
* @width: The width of the framed window including any invisible borders
* @height: The height of the framed window including any invisible borders
* @cr: Used to draw the resulting mask
*/
void
meta_frames_get_mask (MetaFrames *frames,
Window xwindow,
guint width,
guint height,
cairo_t *cr)
{
MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
float top_left, top_right, bottom_left, bottom_right;
int x, y;
MetaFrameBorders borders;
if (frame == NULL)
meta_bug ("No such frame 0x%lx\n", xwindow);
cairo_save (cr);
meta_ui_frame_get_borders (frames, frame, &borders);
meta_ui_frame_get_corner_radiuses (frames, frame,
&top_left, &top_right,
&bottom_left, &bottom_right);
/* top left */
x = borders.invisible.left;
y = borders.invisible.top;
cairo_arc (cr,
x + top_left,
y + top_left,
top_left,
2 * TAU / 4,
3 * TAU / 4);
/* top right */
x = width - borders.invisible.right - top_right;
y = borders.invisible.top;
cairo_arc (cr,
x,
y + top_right,
top_right,
3 * TAU / 4,
4 * TAU / 4);
/* bottom right */
x = width - borders.invisible.right - bottom_right;
y = height - borders.invisible.bottom - bottom_right;
cairo_arc (cr,
x,
y,
bottom_right,
0 * TAU / 4,
1 * TAU / 4);
/* bottom left */
x = borders.invisible.left;
y = height - borders.invisible.bottom - bottom_left;
cairo_arc (cr,
x + bottom_left,
y,
bottom_left,
1 * TAU / 4,
2 * TAU / 4);
cairo_set_source_rgba (cr, 1, 1, 1, 1);
cairo_fill (cr);
cairo_restore (cr);
}
static gboolean
meta_frames_draw (GtkWidget *widget,
cairo_t *cr)

View File

@@ -140,11 +140,12 @@ cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
int window_width,
int window_height);
void meta_frames_get_mask (MetaFrames *frames,
Window xwindow,
guint width,
guint height,
cairo_t *cr);
void meta_frames_get_corner_radiuses (MetaFrames *frames,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
void meta_frames_move_resize_frame (MetaFrames *frames,
Window xwindow,

View File

@@ -40,6 +40,7 @@ typedef enum
{
MENU_ITEM_SEPARATOR = 0,
MENU_ITEM_NORMAL,
MENU_ITEM_IMAGE,
MENU_ITEM_CHECKBOX,
MENU_ITEM_RADIOBUTTON,
MENU_ITEM_WORKSPACE_LIST,
@@ -49,6 +50,7 @@ struct _MenuItem
{
MetaMenuOp op;
MetaMenuItemType type;
const char *stock_id;
const gboolean checked;
const char *label;
};
@@ -64,42 +66,42 @@ static void activate_cb (GtkWidget *menuitem, gpointer data);
static MenuItem menuitems[] = {
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
{ META_MENU_OP_MINIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Unma_ximize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Roll _Up") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Unroll") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Move") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Resize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move Titlebar On_screen") },
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, NULL, FALSE, N_("Always on _Top") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, NULL, TRUE, N_("Always on _Top") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Always on Visible Workspace") },
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Always on Visible Workspace") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Only on This Workspace") },
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Only on This Workspace") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Left") },
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Left") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace R_ight") },
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace R_ight") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Up") },
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Up") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Down") },
{ 0, MENU_ITEM_WORKSPACE_LIST, FALSE, NULL },
{ 0, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Down") },
{ 0, MENU_ITEM_WORKSPACE_LIST, NULL, FALSE, NULL },
{ 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
{ META_MENU_OP_DELETE, MENU_ITEM_IMAGE, METACITY_STOCK_DELETE, FALSE, N_("_Close") }
};
static void
@@ -272,6 +274,16 @@ menu_item_new (MenuItem *menuitem, int workspace_id)
{
mi = gtk_menu_item_new ();
}
else if (menuitem->type == MENU_ITEM_IMAGE)
{
GtkWidget *image;
image = gtk_image_new_from_stock (menuitem->stock_id, GTK_ICON_SIZE_MENU);
mi = gtk_image_menu_item_new ();
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
}
else if (menuitem->type == MENU_ITEM_CHECKBOX)
{
mi = gtk_check_menu_item_new ();
@@ -380,7 +392,8 @@ meta_window_menu_new (MetaFrames *frames,
int j;
MenuItem to_another_workspace = {
0, MENU_ITEM_NORMAL, FALSE,
0, MENU_ITEM_NORMAL,
NULL, FALSE,
N_("Move to Another _Workspace")
};

View File

@@ -27,6 +27,11 @@
#include <gtk/gtk.h>
#include "frames.h"
/* Stock icons */
#define METACITY_STOCK_DELETE "metacity-delete"
#define METACITY_STOCK_MINIMIZE "metacity-minimize"
#define METACITY_STOCK_MAXIMIZE "metacity-maximize"
struct _MetaWindowMenu
{
MetaFrames *frames;

496
src/ui/preview-widget.c Normal file
View File

@@ -0,0 +1,496 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2002 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/*
* SECTION:preview-widget
* @title: MetaPreview
* @short_description: Mutter theme preview widget
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600 /* for the maths routines over floats */
#include <math.h>
#include <gtk/gtk.h>
#include <meta/preview-widget.h>
#include "theme-private.h"
static void meta_preview_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural);
static void meta_preview_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural);
static void meta_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gboolean meta_preview_draw (GtkWidget *widget,
cairo_t *cr);
static void meta_preview_realize (GtkWidget *widget);
static void meta_preview_dispose (GObject *object);
static void meta_preview_finalize (GObject *object);
G_DEFINE_TYPE (MetaPreview, meta_preview, GTK_TYPE_BIN);
static void
meta_preview_class_init (MetaPreviewClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class;
widget_class = (GtkWidgetClass*) class;
gobject_class->dispose = meta_preview_dispose;
gobject_class->finalize = meta_preview_finalize;
widget_class->realize = meta_preview_realize;
widget_class->draw = meta_preview_draw;
widget_class->get_preferred_width = meta_preview_get_preferred_width;
widget_class->get_preferred_height = meta_preview_get_preferred_height;
widget_class->size_allocate = meta_preview_size_allocate;
gtk_container_class_handle_border_width (GTK_CONTAINER_CLASS (class));
}
static void
meta_preview_init (MetaPreview *preview)
{
int i;
gtk_widget_set_has_window (GTK_WIDGET (preview), FALSE);
i = 0;
while (i < MAX_BUTTONS_PER_CORNER)
{
preview->button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
preview->button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
++i;
}
preview->button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
preview->button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
preview->button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
preview->button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
preview->type = META_FRAME_TYPE_NORMAL;
preview->flags =
META_FRAME_ALLOWS_DELETE |
META_FRAME_ALLOWS_MENU |
META_FRAME_ALLOWS_MINIMIZE |
META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_VERTICAL_RESIZE |
META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
META_FRAME_HAS_FOCUS |
META_FRAME_ALLOWS_SHADE |
META_FRAME_ALLOWS_MOVE;
preview->borders_cached = FALSE;
}
GtkWidget*
meta_preview_new (void)
{
MetaPreview *preview;
preview = g_object_new (META_TYPE_PREVIEW, NULL);
return GTK_WIDGET (preview);
}
static void
meta_preview_dispose (GObject *object)
{
MetaPreview *preview = META_PREVIEW (object);
g_clear_object (&preview->style_context);
G_OBJECT_CLASS (meta_preview_parent_class)->dispose (object);
}
static void
meta_preview_finalize (GObject *object)
{
MetaPreview *preview;
preview = META_PREVIEW (object);
g_free (preview->title);
preview->title = NULL;
G_OBJECT_CLASS (meta_preview_parent_class)->finalize (object);
}
static void
ensure_info (MetaPreview *preview)
{
GtkWidget *widget;
widget = GTK_WIDGET (preview);
if (preview->layout == NULL)
{
PangoFontDescription *font_desc;
double scale;
PangoAttrList *attrs;
PangoAttribute *attr;
if (preview->theme)
scale = meta_theme_get_title_scale (preview->theme,
preview->type,
preview->flags);
else
scale = 1.0;
preview->layout = gtk_widget_create_pango_layout (widget,
preview->title);
font_desc = meta_gtk_widget_get_font_desc (widget, scale, NULL);
preview->text_height =
meta_pango_font_desc_get_text_height (font_desc,
gtk_widget_get_pango_context (widget));
attrs = pango_attr_list_new ();
attr = pango_attr_size_new (pango_font_description_get_size (font_desc));
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_insert (attrs, attr);
pango_layout_set_attributes (preview->layout, attrs);
pango_attr_list_unref (attrs);
pango_font_description_free (font_desc);
}
if (!preview->borders_cached)
{
if (preview->theme)
meta_theme_get_frame_borders (preview->theme,
preview->type,
preview->text_height,
preview->flags,
&preview->borders);
else
meta_frame_borders_clear (&preview->borders);
preview->borders_cached = TRUE;
}
}
static gboolean
meta_preview_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaPreview *preview = META_PREVIEW (widget);
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
if (preview->theme)
{
int client_width;
int client_height;
MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
{
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL
};
ensure_info (preview);
cairo_save (cr);
client_width = allocation.width - preview->borders.total.left - preview->borders.total.right;
client_height = allocation.height - preview->borders.total.top - preview->borders.total.bottom;
if (client_width < 0)
client_width = 1;
if (client_height < 0)
client_height = 1;
meta_theme_draw_frame (preview->theme,
preview->style_context,
cr,
preview->type,
preview->flags,
client_width, client_height,
preview->layout,
preview->text_height,
&preview->button_layout,
button_states,
meta_preview_get_mini_icon (),
meta_preview_get_icon ());
cairo_restore (cr);
}
/* draw child */
return GTK_WIDGET_CLASS (meta_preview_parent_class)->draw (widget, cr);
}
static void
meta_preview_realize (GtkWidget *widget)
{
MetaPreview *preview = META_PREVIEW (widget);
GTK_WIDGET_CLASS (meta_preview_parent_class)->realize (widget);
preview->style_context = meta_theme_create_style_context (gtk_widget_get_screen (widget),
NULL);
}
#define NO_CHILD_WIDTH 80
#define NO_CHILD_HEIGHT 20
static void
meta_preview_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
MetaPreview *preview;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
*minimum = *natural = preview->borders.total.left + preview->borders.total.right;
child = gtk_bin_get_child (GTK_BIN (preview));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
*minimum += child_min;
*natural += child_nat;
}
else
{
*minimum += NO_CHILD_WIDTH;
*natural += NO_CHILD_WIDTH;
}
}
static void
meta_preview_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
MetaPreview *preview;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
*minimum = *natural = preview->borders.total.top + preview->borders.total.bottom;
child = gtk_bin_get_child (GTK_BIN (preview));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
*minimum += child_min;
*natural += child_nat;
}
else
{
*minimum += NO_CHILD_HEIGHT;
*natural += NO_CHILD_HEIGHT;
}
}
static void
meta_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
MetaPreview *preview;
GtkAllocation widget_allocation, child_allocation;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
gtk_widget_set_allocation (widget, allocation);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child && gtk_widget_get_visible (child))
{
gtk_widget_get_allocation (widget, &widget_allocation);
child_allocation.x = widget_allocation.x + preview->borders.total.left;
child_allocation.y = widget_allocation.y + preview->borders.total.top;
child_allocation.width = MAX (1, widget_allocation.width - preview->borders.total.left - preview->borders.total.right);
child_allocation.height = MAX (1, widget_allocation.height - preview->borders.total.top - preview->borders.total.bottom);
gtk_widget_size_allocate (child, &child_allocation);
}
}
static void
clear_cache (MetaPreview *preview)
{
if (preview->layout)
{
g_object_unref (G_OBJECT (preview->layout));
preview->layout = NULL;
}
preview->borders_cached = FALSE;
}
void
meta_preview_set_theme (MetaPreview *preview,
MetaTheme *theme)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->theme = theme;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_title (MetaPreview *preview,
const char *title)
{
g_return_if_fail (META_IS_PREVIEW (preview));
g_free (preview->title);
preview->title = g_strdup (title);
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_frame_type (MetaPreview *preview,
MetaFrameType type)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->type = type;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_frame_flags (MetaPreview *preview,
MetaFrameFlags flags)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->flags = flags;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_button_layout (MetaPreview *preview,
const MetaButtonLayout *button_layout)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->button_layout = *button_layout;
gtk_widget_queue_draw (GTK_WIDGET (preview));
}
GdkPixbuf*
meta_preview_get_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"gtk-missing-image",
META_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
return default_icon;
}
GdkPixbuf*
meta_preview_get_mini_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_MINI_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"gtk-missing-image",
META_MINI_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
return default_icon;
}

View File

@@ -857,7 +857,10 @@ meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
WnckWindowDisplayInfo wnck_window;
wnck_window.icon = window->icon;
wnck_window.mini_icon = window->mini_icon;
wnck_window.is_active = window->has_focus;
wnck_window.is_active = FALSE;
if (window == window->display->expected_focus_window)
wnck_window.is_active = TRUE;
if (window->frame)
{

1365
src/ui/theme-viewer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1880,7 +1880,7 @@ debug_print_tokens (PosToken *tokens,
/**
* pos_tokenize:
* @expr: The expression
* @tokens_p: (out): The resulting tokens
* @tokens_p: (out) The resulting tokens
* @n_tokens_p: (out): The number of resulting tokens
* @err: (out): set to the problem if there was a problem
@@ -5063,14 +5063,16 @@ meta_theme_get_current (void)
}
void
meta_theme_set_current (const char *name)
meta_theme_set_current (const char *name,
gboolean force_reload)
{
MetaTheme *new_theme;
GError *err;
meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
if (meta_current_theme &&
if (!force_reload &&
meta_current_theme &&
strcmp (name, meta_current_theme->name) == 0)
return;

View File

@@ -4,6 +4,7 @@
/*
* Copyright (C) 2002 Havoc Pennington
* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -30,10 +31,13 @@
#include "core.h"
#include "theme-private.h"
#include "inlinepixbufs.h"
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
static void meta_stock_icons_init (void);
static void meta_ui_accelerator_parse (const char *accel,
guint *keysym,
guint *keycode,
@@ -56,10 +60,10 @@ struct _MetaUI
void
meta_ui_init (void)
{
gdk_set_allowed_backends ("x11");
if (!gtk_init_check (NULL, NULL))
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
meta_stock_icons_init ();
}
Display*
@@ -320,16 +324,6 @@ meta_ui_free (MetaUI *ui)
g_free (ui);
}
void
meta_ui_get_frame_mask (MetaUI *ui,
Window frame_xwindow,
guint width,
guint height,
cairo_t *cr)
{
meta_frames_get_mask (ui->frames, frame_xwindow, width, height, cr);
}
void
meta_ui_get_frame_borders (MetaUI *ui,
Window frame_xwindow,
@@ -339,6 +333,19 @@ meta_ui_get_frame_borders (MetaUI *ui,
borders);
}
void
meta_ui_get_corner_radiuses (MetaUI *ui,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
meta_frames_get_corner_radiuses (ui->frames, xwindow,
top_left, top_right,
bottom_left, bottom_right);
}
Window
meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
@@ -771,9 +778,10 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
}
void
meta_ui_set_current_theme (const char *name)
meta_ui_set_current_theme (const char *name,
gboolean force_reload)
{
meta_theme_set_current (name);
meta_theme_set_current (name, force_reload);
meta_invalidate_default_icons ();
}
@@ -993,6 +1001,48 @@ meta_ui_window_is_widget (MetaUI *ui,
return FALSE;
}
/* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> */
typedef struct
{
char *stock_id;
const guint8 *icon_data;
} MetaStockIcon;
static void
meta_stock_icons_init (void)
{
GtkIconFactory *factory;
int i;
MetaStockIcon items[] =
{
{ METACITY_STOCK_DELETE, stock_delete_data },
{ METACITY_STOCK_MINIMIZE, stock_minimize_data },
{ METACITY_STOCK_MAXIMIZE, stock_maximize_data }
};
factory = gtk_icon_factory_new ();
gtk_icon_factory_add_default (factory);
for (i = 0; i < (gint) G_N_ELEMENTS (items); i++)
{
GtkIconSet *icon_set;
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new_from_inline (-1, items[i].icon_data,
FALSE,
NULL);
icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
g_object_unref (G_OBJECT (pixbuf));
}
g_object_unref (G_OBJECT (factory));
}
int
meta_ui_get_drag_threshold (MetaUI *ui)
{

View File

@@ -66,13 +66,6 @@ void meta_ui_theme_get_frame_borders (MetaUI *ui,
void meta_ui_get_frame_borders (MetaUI *ui,
Window frame_xwindow,
MetaFrameBorders *borders);
void meta_ui_get_frame_mask (MetaUI *ui,
Window frame_xwindow,
guint width,
guint height,
cairo_t *cr);
Window meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
@@ -109,6 +102,13 @@ cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
int window_width,
int window_height);
void meta_ui_get_corner_radiuses (MetaUI *ui,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
void meta_ui_queue_frame_draw (MetaUI *ui,
Window xwindow);
@@ -154,7 +154,8 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
void meta_ui_set_current_theme (const char *name);
void meta_ui_set_current_theme (const char *name,
gboolean force_reload);
gboolean meta_ui_have_a_theme (void);
/* Not a real key symbol but means "key above the tab key"; this is

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