Compare commits
73 Commits
3.9.2
...
wip/displa
Author | SHA1 | Date | |
---|---|---|---|
78b41e542b | |||
13557b39d0 | |||
39aecd2dde | |||
c564515ef6 | |||
d7b2ea37b1 | |||
0a1e0fe132 | |||
1a0513ea61 | |||
028fa6cd4e | |||
194b11186c | |||
40f064abc3 | |||
27b8716795 | |||
50b44d0445 | |||
c74d40ac41 | |||
c21f7d43bd | |||
80e0b4aac9 | |||
12cd4c216b | |||
91d193e5e8 | |||
f82f3ef67b | |||
6125b3fa7e | |||
169780346b | |||
9b255f9292 | |||
60e11fbae3 | |||
355f0258b1 | |||
09984bb56d | |||
f48ddb3683 | |||
9ac92336c9 | |||
2bc5e89a5e | |||
a413bc106f | |||
b04ac57f02 | |||
c3a08ee589 | |||
1fdb161f54 | |||
f3d1653f13 | |||
3093b5c95d | |||
c3e8646af3 | |||
8c17b670fb | |||
12d2e1f600 | |||
c20b007985 | |||
ef480e9120 | |||
8c1c77482d | |||
e633606ca9 | |||
6fdc23d0b7 | |||
4862872c78 | |||
ae2e4c5114 | |||
06b5be2d13 | |||
56fb8a81b3 | |||
90a3d613ca | |||
c2af13cf31 | |||
b0cf0b2442 | |||
1c569c2d0e | |||
e3855c77af | |||
21fe5be026 | |||
57bc974a57 | |||
3b51405255 | |||
73dbb4b9a5 | |||
51acc3ee31 | |||
a6f206f07c | |||
9504fdd2cb | |||
b76c3312e9 | |||
fd7db8e6b3 | |||
b7840bec7d | |||
f743539886 | |||
15e01152da | |||
2103ff6a5c | |||
8ab136b7ea | |||
5205821fb9 | |||
7187206ef5 | |||
96221e6c04 | |||
7fdfbad6d4 | |||
2a5b068863 | |||
0c505faded | |||
b2dd4f33f7 | |||
47b21b3547 | |||
c119f98bac |
1
.gitignore
vendored
1
.gitignore
vendored
@ -46,7 +46,6 @@ POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
|
32
NEWS
32
NEWS
@ -1,3 +1,35 @@
|
||||
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
|
||||
=====
|
||||
* 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
|
||||
|
||||
3.9.2
|
||||
=====
|
||||
* Add meta_window_can_close() function [Jasper; #699269]
|
||||
|
14
configure.ac
14
configure.ac
@ -2,7 +2,7 @@ AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [9])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
m4_define([mutter_micro_version], [5])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -73,8 +73,10 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.13.5
|
||||
$CLUTTER_PACKAGE >= 1.14.3
|
||||
cogl-1.0 >= 1.13.3
|
||||
upower-glib > 0.9.11
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
|
||||
GLIB_GSETTINGS
|
||||
@ -118,9 +120,6 @@ 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"
|
||||
@ -307,9 +306,6 @@ 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
|
||||
@ -439,10 +435,8 @@ doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/wm-tester/Makefile
|
||||
src/libmutter.pc
|
||||
src/mutter-plugins.pc
|
||||
src/tools/Makefile
|
||||
src/compositor/plugins/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
@ -409,7 +409,6 @@ 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
|
||||
|
@ -23,12 +23,9 @@ 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
|
||||
|
||||
|
32
po/ja.po
32
po/ja.po
@ -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-03-22 10:02+0000\n"
|
||||
"PO-Revision-Date: 2013-03-25 17:02+0000\n"
|
||||
"POT-Creation-Date: 2013-07-30 12:29+0000\n"
|
||||
"PO-Revision-Date: 2013-07-30 23:01+0900\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:568
|
||||
#: ../src/compositor/compositor.c:589
|
||||
#, 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:1191
|
||||
#: ../src/compositor/meta-background.c:1076
|
||||
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:401
|
||||
#: ../src/core/display.c:421
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "ウィンドウの合成に必要な %s という拡張モジュールが存在しません"
|
||||
|
||||
#: ../src/core/display.c:493
|
||||
#: ../src/core/display.c:513
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "X Window System のディスプレイ '%s' のオープンに失敗しました\n"
|
||||
|
||||
#: ../src/core/keybindings.c:935
|
||||
#: ../src/core/keybindings.c:1138
|
||||
#, 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:1135
|
||||
#: ../src/core/keybindings.c:1335
|
||||
#, 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:1095
|
||||
#: ../src/core/prefs.c:1202
|
||||
msgid "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
|
||||
msgstr "仕様に準拠していないアプリケーションに対する次善策は無効になっています。一部のアプリケーションは正常に動作しない可能性があります\n"
|
||||
|
||||
#: ../src/core/prefs.c:1170
|
||||
#: ../src/core/prefs.c:1277
|
||||
#, 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:1236
|
||||
#: ../src/core/prefs.c:1343
|
||||
#, 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:1788
|
||||
#: ../src/core/prefs.c:1909
|
||||
#, 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:1887
|
||||
#: ../src/core/prefs.c:1999
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "ワークスペース %d"
|
||||
@ -465,7 +465,7 @@ msgid "Window manager error: "
|
||||
msgstr "ウィンドウマネージャーのエラー: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7596
|
||||
#: ../src/core/window.c:7513
|
||||
#, 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:8320
|
||||
#: ../src/core/window.c:8237
|
||||
#, 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"
|
||||
|
18
po/nb.po
18
po/nb.po
@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter 3.9.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-05-28 09:47+0200\n"
|
||||
"POT-Creation-Date: 2013-08-08 22:14+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 09:48+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\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:571
|
||||
#: ../src/compositor/compositor.c:589
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
@ -333,7 +333,7 @@ msgstr "Skriv versjonsnummer"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Mutter-tillegg som skal brukes"
|
||||
|
||||
#: ../src/core/prefs.c:1210
|
||||
#: ../src/core/prefs.c:1202
|
||||
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:1285
|
||||
#: ../src/core/prefs.c:1277
|
||||
#, 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:1351
|
||||
#: ../src/core/prefs.c:1343
|
||||
#, 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:1928
|
||||
#: ../src/core/prefs.c:1909
|
||||
#, 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:2018
|
||||
#: ../src/core/prefs.c:1999
|
||||
#, 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:7505
|
||||
#: ../src/core/window.c:7513
|
||||
#, 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:8229
|
||||
#: ../src/core/window.c:8237
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=wm-tester tools compositor/plugins
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
@ -19,7 +19,7 @@ INCLUDES= \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DG_LOG_DOMAIN=\"Mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
|
||||
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
|
||||
@ -30,6 +30,7 @@ INCLUDES= \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
|
||||
@ -94,6 +95,8 @@ libmutter_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 \
|
||||
@ -110,6 +113,11 @@ libmutter_la_SOURCES = \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
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 \
|
||||
@ -139,7 +147,6 @@ libmutter_la_SOURCES = \
|
||||
meta/common.h \
|
||||
core/core.h \
|
||||
ui/ui.h \
|
||||
inlinepixbufs.h \
|
||||
ui/frames.c \
|
||||
ui/frames.h \
|
||||
ui/menu.c \
|
||||
@ -157,8 +164,6 @@ libmutter_la_SOURCES = \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
meta/preview-widget.h \
|
||||
ui/preview-widget.c \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
@ -196,7 +201,6 @@ 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/meta
|
||||
@ -205,10 +209,7 @@ libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
mutter_theme_viewer_SOURCES= \
|
||||
ui/theme-viewer.c
|
||||
|
||||
bin_PROGRAMS=mutter mutter-theme-viewer
|
||||
bin_PROGRAMS=mutter
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
@ -246,8 +247,6 @@ Meta-$(api_version).gir: libmutter.la
|
||||
|
||||
endif
|
||||
|
||||
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = core/testasyncgetprop.c
|
||||
@ -284,14 +283,7 @@ 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 = \
|
||||
inlinepixbufs.h \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
@ -300,9 +292,6 @@ CLEANFILES = \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
|
||||
inlinepixbufs.h: $(IMAGES)
|
||||
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
|
||||
@ -320,7 +309,7 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
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)
|
||||
|
||||
@ -342,3 +331,12 @@ 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 \
|
||||
xrandr.xml
|
||||
|
@ -391,6 +391,24 @@ meta_focus_stage_window (MetaScreen *screen,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_stage_is_focused (MetaScreen *screen)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
Window window;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return FALSE;
|
||||
|
||||
return (screen->display->focus_xwindow == window);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
@ -517,20 +535,20 @@ meta_check_end_modal (MetaScreen *screen)
|
||||
{
|
||||
meta_end_modal_for_plugin (screen,
|
||||
compositor->modal_plugin,
|
||||
CurrentTime);
|
||||
|
||||
CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
after_stage_paint (gpointer data)
|
||||
static void
|
||||
after_stage_paint (ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
MetaCompScreen *info = (MetaCompScreen*) data;
|
||||
GList *l;
|
||||
|
||||
for (l = info->windows; l; l = l->next)
|
||||
meta_window_actor_post_paint (l->data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -611,9 +629,10 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
info->stage = clutter_stage_new ();
|
||||
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
after_stage_paint,
|
||||
info, NULL);
|
||||
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
|
||||
after_stage_paint,
|
||||
info,
|
||||
NULL);
|
||||
|
||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
|
||||
|
||||
@ -641,6 +660,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
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;
|
||||
@ -1565,8 +1587,10 @@ void
|
||||
meta_enable_unredirect_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
if (info != NULL)
|
||||
info->disable_unredirect_count = MAX(0, info->disable_unredirect_count - 1);
|
||||
if (info != NULL && info->disable_unredirect_count == 0)
|
||||
g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
|
||||
if (info != NULL && info->disable_unredirect_count > 0)
|
||||
info->disable_unredirect_count = info->disable_unredirect_count - 1;
|
||||
}
|
||||
|
||||
#define FLASH_TIME_MS 50
|
||||
|
@ -73,13 +73,12 @@ void
|
||||
meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GList *children, *l;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *actor;
|
||||
|
||||
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
|
||||
for (l = children; l; l = l->next)
|
||||
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self));
|
||||
while (clutter_actor_iter_next (&iter, &actor))
|
||||
{
|
||||
ClutterActor *actor = l->data;
|
||||
|
||||
if (META_IS_BACKGROUND_ACTOR (actor))
|
||||
{
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
|
||||
@ -96,7 +95,6 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||
cairo_region_translate (region, x, y);
|
||||
}
|
||||
}
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
|
@ -1060,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
|
||||
|
||||
texture = cogl_texture_new_from_data (width,
|
||||
height,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_TEXTURE_NO_ATLAS,
|
||||
has_alpha ?
|
||||
COGL_PIXEL_FORMAT_RGBA_8888 :
|
||||
COGL_PIXEL_FORMAT_RGB_888,
|
||||
|
@ -85,12 +85,20 @@ 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;
|
||||
@ -101,6 +109,10 @@ 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;
|
||||
}
|
||||
|
||||
@ -320,3 +332,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
@ -73,4 +73,6 @@ 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
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
@ -338,3 +339,13 @@ 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);
|
||||
}
|
||||
|
@ -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, 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 } },
|
||||
{ "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 } },
|
||||
|
||||
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
|
||||
|
@ -69,9 +69,6 @@ struct _MetaWindowActorPrivate
|
||||
Damage damage;
|
||||
|
||||
guint8 opacity;
|
||||
guint8 shadow_opacity;
|
||||
|
||||
gchar * desc;
|
||||
|
||||
/* A region that matches the shape of the window, including frame bounds */
|
||||
cairo_region_t *shape_region;
|
||||
@ -130,8 +127,6 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
guint no_shadow : 1;
|
||||
|
||||
guint no_more_x_calls : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
|
||||
/* This is used to detect fullscreen windows that need to be unredirected */
|
||||
@ -323,9 +318,6 @@ window_decorated_notify (MetaWindow *mw,
|
||||
priv->damage = None;
|
||||
}
|
||||
|
||||
g_free (priv->desc);
|
||||
priv->desc = NULL;
|
||||
|
||||
priv->xwindow = new_xwindow;
|
||||
|
||||
/*
|
||||
@ -377,10 +369,10 @@ meta_window_actor_constructed (GObject *object)
|
||||
*/
|
||||
g_object_ref (priv->actor);
|
||||
|
||||
g_signal_connect (window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self);
|
||||
g_signal_connect (window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self);
|
||||
g_signal_connect_object (window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
g_signal_connect_object (window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -457,7 +449,6 @@ meta_window_actor_finalize (GObject *object)
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
g_list_free_full (priv->frames, (GDestroyNotify) frame_data_free);
|
||||
g_free (priv->desc);
|
||||
|
||||
G_OBJECT_CLASS (meta_window_actor_parent_class)->finalize (object);
|
||||
}
|
||||
@ -852,25 +843,6 @@ meta_window_actor_is_override_redirect (MetaWindowActor *self)
|
||||
return meta_window_is_override_redirect (self->priv->window);
|
||||
}
|
||||
|
||||
const char *meta_window_actor_get_description (MetaWindowActor *self)
|
||||
{
|
||||
/*
|
||||
* For windows managed by the WM, we just defer to the WM for the window
|
||||
* description. For override-redirect windows, we create the description
|
||||
* ourselves, but only on demand.
|
||||
*/
|
||||
if (self->priv->window)
|
||||
return meta_window_get_description (self->priv->window);
|
||||
|
||||
if (G_UNLIKELY (self->priv->desc == NULL))
|
||||
{
|
||||
self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
|
||||
(guint) self->priv->xwindow);
|
||||
}
|
||||
|
||||
return self->priv->desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_workspace:
|
||||
* @self: #MetaWindowActor
|
||||
@ -1340,14 +1312,6 @@ meta_window_actor_destroy (MetaWindowActor *self)
|
||||
|
||||
priv->needs_destroy = TRUE;
|
||||
|
||||
/*
|
||||
* Once the window destruction is initiated we can no longer perform any
|
||||
* furter X-based operations. For example, if we have a Map effect running,
|
||||
* we cannot query the window geometry once the effect completes. So, flag
|
||||
* this.
|
||||
*/
|
||||
priv->no_more_x_calls = TRUE;
|
||||
|
||||
if (!meta_window_actor_effect_in_progress (self))
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (self));
|
||||
}
|
||||
@ -1748,8 +1712,8 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
|
||||
* meta_window_actor_reset_visible_regions:
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
* Unsets the regions set by meta_window_actor_reset_visible_region() and
|
||||
* meta_window_actor_reset_visible_region_beneath()
|
||||
* Unsets the regions set by meta_window_actor_set_visible_region() and
|
||||
* meta_window_actor_set_visible_region_beneath()
|
||||
*/
|
||||
void
|
||||
meta_window_actor_reset_visible_regions (MetaWindowActor *self)
|
||||
|
@ -91,8 +91,9 @@ 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;
|
||||
@ -123,13 +124,6 @@ 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
|
||||
@ -151,12 +145,18 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
|
||||
}
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
/* 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))
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
continue;
|
||||
|
||||
if (l->data == info->unredirected_window)
|
||||
if (info->unredirected_window != NULL &&
|
||||
child == CLUTTER_ACTOR (info->unredirected_window))
|
||||
continue;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
@ -175,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 (l->data))
|
||||
if (clutter_actor_has_effects (child))
|
||||
continue;
|
||||
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
{
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
@ -204,13 +204,12 @@ 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 (l->data) ||
|
||||
META_IS_BACKGROUND_GROUP (l->data))
|
||||
else if (META_IS_BACKGROUND_ACTOR (child) ||
|
||||
META_IS_BACKGROUND_GROUP (child))
|
||||
{
|
||||
ClutterActor *background_actor = l->data;
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
|
||||
if (!meta_actor_is_untransformed (child, &x, &y))
|
||||
continue;
|
||||
|
||||
x += paint_x_offset;
|
||||
@ -218,10 +217,10 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
|
||||
cairo_region_translate (visible_region, - x, - y);
|
||||
|
||||
if (META_IS_BACKGROUND_GROUP (background_actor))
|
||||
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
|
||||
if (META_IS_BACKGROUND_GROUP (child))
|
||||
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
|
||||
else
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
}
|
||||
@ -233,21 +232,20 @@ 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)
|
||||
*/
|
||||
for (l = children; l; l = l->next)
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
{
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
meta_window_actor_reset_visible_regions (window_actor);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (l->data))
|
||||
else if (META_IS_BACKGROUND_ACTOR (child))
|
||||
{
|
||||
MetaBackgroundActor *background_actor = l->data;
|
||||
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
|
||||
meta_background_actor_set_visible_region (background_actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -24,6 +24,8 @@
|
||||
#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)
|
||||
@ -98,6 +100,8 @@ 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);
|
||||
@ -113,6 +117,8 @@ struct _MetaDefaultPluginPrivate
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
ClutterActor *background_group;
|
||||
|
||||
MetaPluginInfo info;
|
||||
};
|
||||
|
||||
@ -203,6 +209,7 @@ 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));
|
||||
}
|
||||
@ -299,9 +306,58 @@ 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,
|
||||
@ -782,3 +838,33 @@ 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);
|
||||
}
|
||||
|
@ -113,6 +113,9 @@ struct _MetaDisplay
|
||||
* or event that caused this.
|
||||
*/
|
||||
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;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
@ -457,7 +460,8 @@ 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 deviceid,
|
||||
guint timestamp);
|
||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
/* In above-tab-keycode.c */
|
||||
|
@ -254,7 +254,7 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
|
||||
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
||||
|
||||
/**
|
||||
* MetaDisplay::modifiers-accelerator-activated:
|
||||
@ -1467,6 +1467,17 @@ 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)
|
||||
@ -1478,17 +1489,13 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
||||
{
|
||||
XEvent property_event;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
timestamp = property_event.xproperty.time;
|
||||
}
|
||||
|
||||
@ -1876,11 +1883,12 @@ get_input_event (MetaDisplay *display,
|
||||
static void
|
||||
update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial)
|
||||
{
|
||||
display->focus_serial = serial;
|
||||
|
||||
if (window == display->focus_window)
|
||||
if (display->focus_xwindow == xwindow)
|
||||
return;
|
||||
|
||||
if (display->focus_window)
|
||||
@ -1897,11 +1905,13 @@ update_focus_window (MetaDisplay *display,
|
||||
*/
|
||||
previous = display->focus_window;
|
||||
display->focus_window = NULL;
|
||||
display->focus_xwindow = None;
|
||||
|
||||
meta_window_set_focused_internal (previous, FALSE);
|
||||
}
|
||||
|
||||
display->focus_window = window;
|
||||
display->focus_xwindow = xwindow;
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
@ -1952,6 +1962,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *meta_window;
|
||||
gulong serial;
|
||||
|
||||
if (timestamp_too_old (display, ×tamp))
|
||||
return;
|
||||
@ -1959,14 +1970,35 @@ request_xserver_input_focus_change (MetaDisplay *display,
|
||||
meta_window = meta_display_lookup_x_window (display, xwindow);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
update_focus_window (display,
|
||||
meta_window,
|
||||
XNextRequest (display->xdisplay));
|
||||
|
||||
/* 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,
|
||||
meta_window,
|
||||
xwindow,
|
||||
serial);
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
display->last_focus_time = timestamp;
|
||||
@ -2079,9 +2111,11 @@ handle_window_focus_event (MetaDisplay *display,
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
if (display->server_focus_serial >= display->focus_serial)
|
||||
if (display->server_focus_serial > display->focus_serial)
|
||||
{
|
||||
update_focus_window (display, focus_window,
|
||||
update_focus_window (display,
|
||||
focus_window,
|
||||
focus_window ? focus_window->xwindow : None,
|
||||
display->server_focus_serial);
|
||||
}
|
||||
}
|
||||
@ -2112,6 +2146,7 @@ event_callback (XEvent *event,
|
||||
gboolean bypass_compositor;
|
||||
gboolean filter_out_event;
|
||||
XIEvent *input_event;
|
||||
MetaMonitorManager *monitor;
|
||||
|
||||
display = data;
|
||||
|
||||
@ -2123,6 +2158,14 @@ event_callback (XEvent *event,
|
||||
#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;
|
||||
@ -2137,6 +2180,7 @@ event_callback (XEvent *event,
|
||||
display->focus_window->desc);
|
||||
update_focus_window (display,
|
||||
meta_display_lookup_x_window (display, display->server_focus_window),
|
||||
display->server_focus_window,
|
||||
display->server_focus_serial);
|
||||
}
|
||||
|
||||
@ -2459,30 +2503,12 @@ event_callback (XEvent *event,
|
||||
/* 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 mode %s time %u\n",
|
||||
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)device_event->time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, device_event->deviceid,
|
||||
mode, device_event->time);
|
||||
XIReplayDevice, device_event->time);
|
||||
}
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
@ -2805,32 +2831,10 @@ event_callback (XEvent *event,
|
||||
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 */
|
||||
@ -3025,27 +3029,6 @@ event_callback (XEvent *event,
|
||||
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)
|
||||
{
|
||||
@ -3755,6 +3738,12 @@ meta_spew_event (MetaDisplay *display,
|
||||
if (event->type == (display->damage_event_base + XDamageNotify))
|
||||
return;
|
||||
|
||||
if (event->type == (display->xsync_event_base + XSyncAlarmNotify))
|
||||
return;
|
||||
|
||||
if (event->type == PropertyNotify && event->xproperty.atom == display->atom__NET_WM_USER_TIME)
|
||||
return;
|
||||
|
||||
input_event = get_input_event (display, event);
|
||||
|
||||
if (input_event)
|
||||
@ -5869,10 +5858,11 @@ meta_display_overlay_key_activate (MetaDisplay *display)
|
||||
void
|
||||
meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
guint deviceid)
|
||||
guint deviceid,
|
||||
guint timestamp)
|
||||
{
|
||||
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
|
||||
0, action, deviceid);
|
||||
0, action, deviceid, timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
540
src/core/edid-parse.c
Normal file
540
src/core/edid-parse.c
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
195
src/core/edid.h
Normal file
195
src/core/edid.h
Normal file
@ -0,0 +1,195 @@
|
||||
/* 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
|
@ -69,7 +69,6 @@ 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);
|
||||
|
||||
|
@ -56,8 +56,6 @@
|
||||
#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,
|
||||
@ -1312,7 +1310,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);
|
||||
meta_display_accelerator_activate (display, action, event->deviceid, event->time);
|
||||
}
|
||||
|
||||
|
||||
@ -1480,7 +1478,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
timestamp,
|
||||
None,
|
||||
grab_mode, grab_mode,
|
||||
True, /* owner_events */
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
|
||||
if (grab_status != Success)
|
||||
@ -1967,6 +1965,23 @@ 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;
|
||||
}
|
||||
@ -2046,21 +2061,6 @@ 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,14 +4098,6 @@ 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
|
||||
|
112
src/core/main.c
112
src/core/main.c
@ -56,6 +56,7 @@
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <glib-object.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
@ -93,26 +94,6 @@ static GMainLoop *meta_main_loop = NULL;
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* log_handler:
|
||||
* @log_domain: the domain the error occurred in (we ignore this)
|
||||
* @log_level: the log level so that we can filter out less
|
||||
* important messages
|
||||
* @message: the message to log
|
||||
* @user_data: arbitrary data (we ignore this)
|
||||
*
|
||||
* Prints log messages. If Mutter was compiled with backtrace support,
|
||||
* also prints a backtrace (see meta_print_backtrace()).
|
||||
*/
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_warning ("Log level %d: %s\n", log_level, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_print_compilation_info:
|
||||
*
|
||||
@ -348,23 +329,8 @@ meta_finalize (void)
|
||||
CurrentTime); /* I doubt correct timestamps matter here */
|
||||
}
|
||||
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
||||
static void
|
||||
sigterm_handler (int signum)
|
||||
{
|
||||
if (sigterm_pipe_fds[1] >= 0)
|
||||
{
|
||||
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_sigterm (void)
|
||||
on_sigterm (gpointer user_data)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
@ -381,8 +347,7 @@ meta_init (void)
|
||||
{
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
GIOChannel *channel;
|
||||
|
||||
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_mask = empty_mask;
|
||||
@ -396,20 +361,9 @@ meta_init (void)
|
||||
g_strerror (errno));
|
||||
#endif
|
||||
|
||||
if (pipe (sigterm_pipe_fds) != 0)
|
||||
g_printerr ("Failed to create SIGTERM pipe: %s\n",
|
||||
g_strerror (errno));
|
||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
||||
|
||||
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
|
||||
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
|
||||
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
|
||||
g_io_channel_set_close_on_unref (channel, TRUE);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
act.sa_handler = &sigterm_handler;
|
||||
if (sigaction (SIGTERM, &act, NULL) < 0)
|
||||
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
||||
g_strerror (errno));
|
||||
meta_debug_init ();
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
meta_set_verbose (TRUE);
|
||||
@ -496,63 +450,25 @@ meta_register_with_session (void)
|
||||
int
|
||||
meta_run (void)
|
||||
{
|
||||
const gchar *log_domains[] = {
|
||||
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
|
||||
/* Load prefs */
|
||||
meta_prefs_init ();
|
||||
meta_prefs_add_listener (prefs_changed_callback, NULL);
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
|
||||
g_log_set_handler (log_domains[i],
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler, NULL);
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
|
||||
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 (), 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 the theme preference does not exists, fallback to
|
||||
* Adwaita (the default theme), or abort if that doesn't
|
||||
* exists.
|
||||
*/
|
||||
if (!meta_ui_have_a_theme ())
|
||||
meta_ui_set_current_theme ("Simple", FALSE);
|
||||
|
||||
meta_ui_set_current_theme ("Adwaita");
|
||||
|
||||
if (!meta_ui_have_a_theme ())
|
||||
{
|
||||
const char *dir_entry = NULL;
|
||||
GError *err = NULL;
|
||||
GDir *themes_dir = NULL;
|
||||
|
||||
if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err)))
|
||||
{
|
||||
meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
|
||||
(!meta_ui_have_a_theme ()))
|
||||
{
|
||||
meta_ui_set_current_theme (dir_entry, FALSE);
|
||||
}
|
||||
|
||||
g_dir_close (themes_dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!meta_ui_have_a_theme ())
|
||||
meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
|
||||
MUTTER_DATADIR"/themes");
|
||||
meta_fatal ("Adwaita theme missing, please install the gnome-themes-standard package");
|
||||
|
||||
if (!meta_display_open ())
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
|
||||
|
||||
g_main_loop_run (meta_main_loop);
|
||||
|
||||
meta_finalize ();
|
||||
@ -598,7 +514,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 (), FALSE);
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
meta_display_retheme_all ();
|
||||
break;
|
||||
|
||||
|
40
src/core/meta-xrandr-shared.h
Normal file
40
src/core/meta-xrandr-shared.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- 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
|
1771
src/core/monitor-config.c
Normal file
1771
src/core/monitor-config.c
Normal file
File diff suppressed because it is too large
Load Diff
390
src/core/monitor-private.h
Normal file
390
src/core/monitor-private.h
Normal file
@ -0,0 +1,390 @@
|
||||
/* -*- 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 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 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
|
938
src/core/monitor-xrandr.c
Normal file
938
src/core/monitor-xrandr.c
Normal file
@ -0,0 +1,938 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
||||
* Some ICCCM manager selection code derived from fvwm2,
|
||||
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/dpms.h>
|
||||
|
||||
#include <meta/main.h>
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
|
||||
#include "edid.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
/* Look for DPI_FALLBACK in:
|
||||
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
||||
* for the reasoning */
|
||||
#define DPI_FALLBACK 96.0
|
||||
|
||||
struct _MetaMonitorManagerXrandr
|
||||
{
|
||||
MetaMonitorManager parent_instance;
|
||||
|
||||
Display *xdisplay;
|
||||
XRRScreenResources *resources;
|
||||
int time;
|
||||
int rr_event_base;
|
||||
int rr_error_base;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerXrandrClass
|
||||
{
|
||||
MetaMonitorManagerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
|
||||
|
||||
static enum wl_output_transform
|
||||
wl_transform_from_xrandr (Rotation rotation)
|
||||
{
|
||||
static const enum wl_output_transform y_reflected_map[4] = {
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
enum wl_output_transform ret;
|
||||
|
||||
switch (rotation & 0x7F)
|
||||
{
|
||||
default:
|
||||
case RR_Rotate_0:
|
||||
ret = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
ret = WL_OUTPUT_TRANSFORM_90;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
ret = WL_OUTPUT_TRANSFORM_180;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
ret = WL_OUTPUT_TRANSFORM_270;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rotation & RR_Reflect_X)
|
||||
return ret + 4;
|
||||
else if (rotation & RR_Reflect_Y)
|
||||
return y_reflected_map[ret];
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
|
||||
|
||||
static unsigned int
|
||||
wl_transform_from_xrandr_all (Rotation rotation)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
/* Handle the common cases first (none or all) */
|
||||
if (rotation == 0 || rotation == RR_Rotate_0)
|
||||
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
/* All rotations and one reflection -> all of them by composition */
|
||||
if ((rotation & ALL_ROTATIONS) &&
|
||||
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
|
||||
return ALL_WL_TRANSFORMS;
|
||||
|
||||
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
if (rotation & RR_Rotate_90)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
|
||||
if (rotation & RR_Rotate_180)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
|
||||
if (rotation & RR_Rotate_270)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
|
||||
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
|
||||
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
|
||||
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
|
||||
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
gboolean value;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return FALSE;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
XFree (buffer);
|
||||
return value;
|
||||
}
|
||||
|
||||
static int
|
||||
normalize_backlight (MetaOutput *output,
|
||||
int hw_value)
|
||||
{
|
||||
return round((double)(hw_value - output->backlight_min) /
|
||||
(output->backlight_max - output->backlight_min) * 100.0);
|
||||
}
|
||||
|
||||
static int
|
||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
gboolean value;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_BACKLIGHT,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return -1;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
XFree (buffer);
|
||||
return normalize_backlight (output, value);
|
||||
}
|
||||
|
||||
static void
|
||||
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XRRPropertyInfo *info;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_BACKLIGHT);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
meta_verbose ("could not get output property for %s\n", output->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info->range || info->num_values != 2)
|
||||
{
|
||||
meta_verbose ("backlight %s was not range\n", output->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
output->backlight_min = info->values[0];
|
||||
output->backlight_max = info->values[1];
|
||||
|
||||
out:
|
||||
XFree (info);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_outputs (const void *one,
|
||||
const void *two)
|
||||
{
|
||||
const MetaOutput *o_one = one, *o_two = two;
|
||||
|
||||
return strcmp (o_one->name, o_two->name);
|
||||
}
|
||||
|
||||
static guint8 *
|
||||
get_edid_property (Display *dpy,
|
||||
RROutput output,
|
||||
Atom atom,
|
||||
gsize *len)
|
||||
{
|
||||
unsigned char *prop;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
Atom actual_type;
|
||||
guint8 *result;
|
||||
|
||||
XRRGetOutputProperty (dpy, output, atom,
|
||||
0, 100, False, False,
|
||||
AnyPropertyType,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &prop);
|
||||
|
||||
if (actual_type == XA_INTEGER && actual_format == 8)
|
||||
{
|
||||
result = g_memdup (prop, nitems);
|
||||
if (len)
|
||||
*len = nitems;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
XFree (prop);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
{
|
||||
Atom edid_atom;
|
||||
guint8 *result;
|
||||
gsize len;
|
||||
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (len > 0 && len % 128 == 0)
|
||||
return g_bytes_new_take (result, len);
|
||||
else
|
||||
g_free (result);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
XRRScreenResources *resources;
|
||||
RROutput primary_output;
|
||||
unsigned int i, j, k;
|
||||
unsigned int n_actual_outputs;
|
||||
int min_width, min_height;
|
||||
Screen *screen;
|
||||
BOOL dpms_capable, dpms_enabled;
|
||||
CARD16 dpms_state;
|
||||
|
||||
if (manager_xrandr->resources)
|
||||
XRRFreeScreenResources (manager_xrandr->resources);
|
||||
manager_xrandr->resources = NULL;
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
if (dpms_capable &&
|
||||
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
|
||||
dpms_enabled)
|
||||
{
|
||||
switch (dpms_state)
|
||||
{
|
||||
case DPMSModeOn:
|
||||
manager->power_save_mode = META_POWER_SAVE_ON;
|
||||
case DPMSModeStandby:
|
||||
manager->power_save_mode = META_POWER_SAVE_STANDBY;
|
||||
case DPMSModeSuspend:
|
||||
manager->power_save_mode = META_POWER_SAVE_SUSPEND;
|
||||
case DPMSModeOff:
|
||||
manager->power_save_mode = META_POWER_SAVE_OFF;
|
||||
default:
|
||||
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
|
||||
}
|
||||
|
||||
XRRGetScreenSizeRange (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
&min_width,
|
||||
&min_height,
|
||||
&manager->max_screen_width,
|
||||
&manager->max_screen_height);
|
||||
|
||||
screen = ScreenOfDisplay (manager_xrandr->xdisplay,
|
||||
DefaultScreen (manager_xrandr->xdisplay));
|
||||
/* This is updated because we called RRUpdateConfiguration below */
|
||||
manager->screen_width = WidthOfScreen (screen);
|
||||
manager->screen_height = HeightOfScreen (screen);
|
||||
|
||||
resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay));
|
||||
if (!resources)
|
||||
return;
|
||||
|
||||
manager_xrandr->resources = resources;
|
||||
manager_xrandr->time = resources->configTimestamp;
|
||||
manager->n_outputs = resources->noutput;
|
||||
manager->n_crtcs = resources->ncrtc;
|
||||
manager->n_modes = resources->nmode;
|
||||
manager->outputs = g_new0 (MetaOutput, manager->n_outputs);
|
||||
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
|
||||
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
|
||||
|
||||
for (i = 0; i < (unsigned)resources->nmode; i++)
|
||||
{
|
||||
XRRModeInfo *xmode = &resources->modes[i];
|
||||
MetaMonitorMode *mode;
|
||||
|
||||
mode = &manager->modes[i];
|
||||
|
||||
mode->mode_id = xmode->id;
|
||||
mode->width = xmode->width;
|
||||
mode->height = xmode->height;
|
||||
mode->refresh_rate = (xmode->dotClock /
|
||||
((float)xmode->hTotal * xmode->vTotal));
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)resources->ncrtc; i++)
|
||||
{
|
||||
XRRCrtcInfo *crtc;
|
||||
MetaCRTC *meta_crtc;
|
||||
|
||||
crtc = XRRGetCrtcInfo (manager_xrandr->xdisplay, resources, resources->crtcs[i]);
|
||||
|
||||
meta_crtc = &manager->crtcs[i];
|
||||
|
||||
meta_crtc->crtc_id = resources->crtcs[i];
|
||||
meta_crtc->rect.x = crtc->x;
|
||||
meta_crtc->rect.y = crtc->y;
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->dirty = FALSE;
|
||||
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
||||
|
||||
for (j = 0; j < (unsigned)resources->nmode; j++)
|
||||
{
|
||||
if (resources->modes[j].id == crtc->mode)
|
||||
{
|
||||
meta_crtc->current_mode = &manager->modes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
|
||||
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay));
|
||||
|
||||
n_actual_outputs = 0;
|
||||
for (i = 0; i < (unsigned)resources->noutput; i++)
|
||||
{
|
||||
XRROutputInfo *output;
|
||||
MetaOutput *meta_output;
|
||||
|
||||
output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
|
||||
|
||||
meta_output = &manager->outputs[n_actual_outputs];
|
||||
|
||||
if (output->connection != RR_Disconnected)
|
||||
{
|
||||
GBytes *edid;
|
||||
MonitorInfo *parsed_edid;
|
||||
|
||||
meta_output->output_id = resources->outputs[i];
|
||||
meta_output->name = g_strdup (output->name);
|
||||
|
||||
edid = read_output_edid (manager_xrandr, meta_output->output_id);
|
||||
if (edid)
|
||||
{
|
||||
gsize len;
|
||||
|
||||
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
|
||||
if (parsed_edid)
|
||||
{
|
||||
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
|
||||
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
|
||||
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
|
||||
|
||||
g_free (parsed_edid);
|
||||
}
|
||||
|
||||
g_bytes_unref (edid);
|
||||
}
|
||||
|
||||
if (!meta_output->vendor)
|
||||
{
|
||||
meta_output->vendor = g_strdup ("unknown");
|
||||
meta_output->product = g_strdup ("unknown");
|
||||
meta_output->serial = g_strdup ("unknown");
|
||||
}
|
||||
meta_output->width_mm = output->mm_width;
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
for (j = 0; j < meta_output->n_modes; j++)
|
||||
{
|
||||
for (k = 0; k < manager->n_modes; k++)
|
||||
{
|
||||
if (output->modes[j] == (XID)manager->modes[k].mode_id)
|
||||
{
|
||||
meta_output->modes[j] = &manager->modes[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
meta_output->preferred_mode = meta_output->modes[0];
|
||||
|
||||
meta_output->n_possible_crtcs = output->ncrtc;
|
||||
meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
|
||||
for (j = 0; j < (unsigned)output->ncrtc; j++)
|
||||
{
|
||||
for (k = 0; k < manager->n_crtcs; k++)
|
||||
{
|
||||
if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
|
||||
{
|
||||
meta_output->possible_crtcs[j] = &manager->crtcs[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_output->crtc = NULL;
|
||||
for (j = 0; j < manager->n_crtcs; j++)
|
||||
{
|
||||
if ((XID)manager->crtcs[j].crtc_id == output->crtc)
|
||||
{
|
||||
meta_output->crtc = &manager->crtcs[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_output->n_possible_clones = output->nclone;
|
||||
meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
|
||||
/* We can build the list of clones now, because we don't have the list of outputs
|
||||
yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
|
||||
in a second pass
|
||||
*/
|
||||
for (j = 0; j < (unsigned)output->nclone; j++)
|
||||
{
|
||||
meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
|
||||
}
|
||||
|
||||
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
||||
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
|
||||
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
|
||||
|
||||
if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
|
||||
meta_output->backlight = output_get_backlight_xrandr (manager_xrandr, meta_output);
|
||||
else
|
||||
meta_output->backlight = -1;
|
||||
|
||||
n_actual_outputs++;
|
||||
}
|
||||
|
||||
XRRFreeOutputInfo (output);
|
||||
}
|
||||
|
||||
manager->n_outputs = n_actual_outputs;
|
||||
|
||||
/* Sort the outputs for easier handling in MetaMonitorConfig */
|
||||
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
|
||||
|
||||
/* Now fix the clones */
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *meta_output;
|
||||
|
||||
meta_output = &manager->outputs[i];
|
||||
|
||||
for (j = 0; j < meta_output->n_possible_clones; j++)
|
||||
{
|
||||
RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
|
||||
|
||||
for (k = 0; k < manager->n_outputs; k++)
|
||||
{
|
||||
if (clone == (XID)manager->outputs[k].output_id)
|
||||
{
|
||||
meta_output->possible_clones[j] = &manager->outputs[k];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
return read_output_edid (manager_xrandr, output->output_id);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaPowerSave mode)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
CARD16 state;
|
||||
|
||||
switch (mode) {
|
||||
case META_POWER_SAVE_ON:
|
||||
state = DPMSModeOn;
|
||||
break;
|
||||
case META_POWER_SAVE_STANDBY:
|
||||
state = DPMSModeStandby;
|
||||
break;
|
||||
case META_POWER_SAVE_SUSPEND:
|
||||
state = DPMSModeSuspend;
|
||||
break;
|
||||
case META_POWER_SAVE_OFF:
|
||||
state = DPMSModeOff;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
DPMSForceLevel (manager_xrandr->xdisplay, state);
|
||||
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
}
|
||||
|
||||
static Rotation
|
||||
wl_transform_to_xrandr (enum wl_output_transform transform)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
return RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
return RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
return RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
return RR_Rotate_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
return RR_Reflect_X | RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
return RR_Reflect_X | RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
return RR_Reflect_X | RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
return RR_Reflect_X | RR_Rotate_270;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output,
|
||||
gboolean presentation)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
int value = presentation;
|
||||
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
unsigned i;
|
||||
int width, height, width_mm, height_mm;
|
||||
|
||||
meta_display_grab (meta_get_display ());
|
||||
|
||||
/* First compute the new size of the screen (framebuffer) */
|
||||
width = 0; height = 0;
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
crtc->dirty = TRUE;
|
||||
|
||||
if (crtc_info->mode == NULL)
|
||||
continue;
|
||||
|
||||
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||
{
|
||||
width = MAX (width, crtc_info->x + crtc_info->mode->height);
|
||||
height = MAX (height, crtc_info->y + crtc_info->mode->width);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = MAX (width, crtc_info->x + crtc_info->mode->width);
|
||||
height = MAX (height, crtc_info->y + crtc_info->mode->height);
|
||||
}
|
||||
}
|
||||
|
||||
/* Second disable all newly disabled CRTCs, or CRTCs that in the previous
|
||||
configuration would be outside the new framebuffer (otherwise X complains
|
||||
loudly when resizing)
|
||||
CRTC will be enabled again after resizing the FB
|
||||
*/
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
|
||||
if (crtc_info->mode == NULL ||
|
||||
crtc->rect.x + crtc->rect.width > width ||
|
||||
crtc->rect.y + crtc->rect.height > height)
|
||||
{
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable CRTCs not mentioned in the list */
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
{
|
||||
MetaCRTC *crtc = &manager->crtcs[i];
|
||||
|
||||
if (crtc->dirty)
|
||||
{
|
||||
crtc->dirty = FALSE;
|
||||
continue;
|
||||
}
|
||||
if (crtc->current_mode == NULL)
|
||||
continue;
|
||||
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
g_assert (width > 0 && height > 0);
|
||||
/* The 'physical size' of an X screen is meaningless if that screen
|
||||
* can consist of many monitors. So just pick a size that make the
|
||||
* dpi 96.
|
||||
*
|
||||
* Firefox and Evince apparently believe what X tells them.
|
||||
*/
|
||||
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
width, height, width_mm, height_mm);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
|
||||
if (crtc_info->mode != NULL)
|
||||
{
|
||||
MetaMonitorMode *mode;
|
||||
XID *outputs;
|
||||
int j, n_outputs;
|
||||
Status ok;
|
||||
|
||||
mode = crtc_info->mode;
|
||||
|
||||
n_outputs = crtc_info->outputs->len;
|
||||
outputs = g_new (XID, n_outputs);
|
||||
|
||||
for (j = 0; j < n_outputs; j++)
|
||||
outputs[j] = ((MetaOutput**)crtc_info->outputs->pdata)[j]->output_id;
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
if (ok != Success)
|
||||
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
|
||||
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
|
||||
mode->width, mode->height, (float)mode->refresh_rate,
|
||||
crtc_info->x, crtc_info->y, crtc_info->transform);
|
||||
|
||||
g_free (outputs);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
MetaOutputInfo *output_info = outputs[i];
|
||||
|
||||
if (output_info->is_primary)
|
||||
{
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
output_info->output,
|
||||
output_info->is_presentation);
|
||||
}
|
||||
|
||||
meta_display_ungrab (meta_get_display ());
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
MetaOutput *output,
|
||||
gint value)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
int hw_value;
|
||||
|
||||
hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
display->atom_BACKLIGHT,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* We're not selecting for property notifies, so update the value immediately */
|
||||
output->backlight = normalize_backlight (output, hw_value);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_get_crtc_gamma (MetaMonitorManager *manager,
|
||||
MetaCRTC *crtc,
|
||||
gsize *size,
|
||||
unsigned short **red,
|
||||
unsigned short **green,
|
||||
unsigned short **blue)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
XRRCrtcGamma *gamma;
|
||||
|
||||
gamma = XRRGetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id);
|
||||
|
||||
*size = gamma->size;
|
||||
*red = g_memdup (gamma->red, sizeof (unsigned short) * gamma->size);
|
||||
*green = g_memdup (gamma->green, sizeof (unsigned short) * gamma->size);
|
||||
*blue = g_memdup (gamma->blue, sizeof (unsigned short) * gamma->size);
|
||||
|
||||
XRRFreeGamma (gamma);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
MetaCRTC *crtc,
|
||||
gsize size,
|
||||
unsigned short *red,
|
||||
unsigned short *green,
|
||||
unsigned short *blue)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
XRRCrtcGamma gamma;
|
||||
|
||||
gamma.size = size;
|
||||
gamma.red = red;
|
||||
gamma.green = green;
|
||||
gamma.blue = blue;
|
||||
|
||||
XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, &gamma);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
return FALSE;
|
||||
|
||||
XRRUpdateConfiguration (event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
manager_xrandr->xdisplay = display->xdisplay;
|
||||
|
||||
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
||||
&manager_xrandr->rr_event_base,
|
||||
&manager_xrandr->rr_error_base))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We only use ScreenChangeNotify, but GDK uses the others,
|
||||
and we don't want to step on its toes */
|
||||
XRRSelectInput (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
RRScreenChangeNotifyMask
|
||||
| RRCrtcChangeNotifyMask
|
||||
| RROutputPropertyNotifyMask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_finalize (GObject *object)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
||||
|
||||
if (manager_xrandr->resources)
|
||||
XRRFreeScreenResources (manager_xrandr->resources);
|
||||
manager_xrandr->resources = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
||||
|
||||
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
|
||||
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
||||
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
|
||||
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
||||
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
||||
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
||||
manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
|
||||
}
|
||||
|
1553
src/core/monitor.c
Normal file
1553
src/core/monitor.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -89,7 +89,6 @@ 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;
|
||||
@ -298,13 +297,6 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&dynamic_workspaces,
|
||||
},
|
||||
{
|
||||
{ "application-based",
|
||||
SCHEMA_GENERAL,
|
||||
META_PREF_APPLICATION_BASED,
|
||||
},
|
||||
NULL, /* feature is known but disabled */
|
||||
},
|
||||
{
|
||||
{ "disable-workarounds",
|
||||
SCHEMA_GENERAL,
|
||||
@ -1723,14 +1715,6 @@ 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)
|
||||
{
|
||||
@ -1768,9 +1752,6 @@ 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";
|
||||
|
||||
|
@ -38,17 +38,7 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.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 */
|
||||
};
|
||||
#include "monitor-private.h"
|
||||
|
||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||
gpointer user_data);
|
||||
@ -100,10 +90,11 @@ struct _MetaScreen
|
||||
Window wm_sn_selection_window;
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int primary_monitor_index;
|
||||
int n_monitor_infos;
|
||||
int primary_monitor_index;
|
||||
gboolean has_xinerama_indices;
|
||||
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
@ -187,6 +178,9 @@ MetaWindow* meta_screen_get_mouse_window (MetaScreen *scre
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor_info (MetaScreen *screen);
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
|
||||
int x,
|
||||
int y);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
@ -228,10 +222,6 @@ 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);
|
||||
|
||||
@ -254,4 +244,9 @@ void meta_screen_workspace_switched (MetaScreen *screen,
|
||||
|
||||
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
|
||||
|
||||
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
|
||||
|
@ -48,10 +48,6 @@
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
@ -76,6 +72,9 @@ 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,
|
||||
@ -350,250 +349,93 @@ 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
|
||||
filter_mirrored_monitors (MetaScreen *screen)
|
||||
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
|
||||
{
|
||||
int i, j;
|
||||
XineramaScreenInfo *infos;
|
||||
int n_infos, i, j;
|
||||
|
||||
/* Currently always true and simplifies things */
|
||||
g_assert (screen->primary_monitor_index == 0);
|
||||
if (screen->has_xinerama_indices)
|
||||
return;
|
||||
|
||||
for (i = 1; i < screen->n_monitor_infos; i++)
|
||||
screen->has_xinerama_indices = TRUE;
|
||||
|
||||
if (!XineramaIsActive (screen->display->xdisplay))
|
||||
return;
|
||||
|
||||
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
|
||||
if (n_infos <= 0 || infos == NULL)
|
||||
{
|
||||
/* In case we've filtered previous monitors */
|
||||
screen->monitor_infos[i].number = i;
|
||||
meta_XFree (infos);
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
for (i = 0; i < screen->n_monitor_infos; ++i)
|
||||
{
|
||||
for (j = 0; j < n_infos; ++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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
meta_XFree (infos);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
static MetaMonitorInfo *
|
||||
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
|
||||
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)
|
||||
{
|
||||
MetaMonitorInfo *info;
|
||||
int i;
|
||||
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
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;
|
||||
if (screen->monitor_infos[i].xinerama_index == index)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
GList *tmp;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
{
|
||||
GList *tmp;
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
|
||||
|
||||
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;
|
||||
|
||||
/* 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->has_xinerama_indices = FALSE;
|
||||
screen->display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Pretending a single monitor has two Xinerama screens\n");
|
||||
manager = meta_monitor_manager_get ();
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/* The guard window allows us to leave minimized windows mapped so
|
||||
@ -668,6 +510,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
char buf[128];
|
||||
guint32 manager_timestamp;
|
||||
gulong current_workspace;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
replace_current_wm = meta_get_replace_current_wm ();
|
||||
|
||||
@ -826,8 +669,17 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->xroot = xroot;
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
screen->rect.width = WidthOfScreen (screen->xscreen);
|
||||
screen->rect.height = HeightOfScreen (screen->xscreen);
|
||||
|
||||
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->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
@ -852,10 +704,6 @@ 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_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
@ -941,7 +789,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;
|
||||
}
|
||||
|
||||
@ -2216,6 +2064,65 @@ meta_screen_get_current_monitor_info (MetaScreen *screen)
|
||||
return &screen->monitor_infos[monitor_index];
|
||||
}
|
||||
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
int monitor_index;
|
||||
monitor_index = meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
return &screen->monitor_infos[monitor_index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* meta_screen_get_current_monitor_for_pos:
|
||||
* @screen: a #MetaScreen
|
||||
* @x: The x coordinate
|
||||
* @y: The y coordinate
|
||||
*
|
||||
* Gets the index of the monitor that contains the passed coordinates.
|
||||
*
|
||||
* Return value: a monitor index
|
||||
*/
|
||||
int
|
||||
meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
if (screen->n_monitor_infos == 1)
|
||||
return 0;
|
||||
else if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
int i;
|
||||
MetaRectangle pointer_position;
|
||||
pointer_position.x = x;
|
||||
pointer_position.y = y;
|
||||
pointer_position.width = pointer_position.height = 1;
|
||||
|
||||
screen->display->monitor_cache_invalidated = FALSE;
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
|
||||
&pointer_position))
|
||||
{
|
||||
screen->last_monitor_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Rechecked current monitor, now %d\n",
|
||||
screen->last_monitor_index);
|
||||
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* meta_screen_get_current_monitor:
|
||||
* @screen: a #MetaScreen
|
||||
@ -2241,11 +2148,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int i;
|
||||
MetaRectangle pointer_position;
|
||||
|
||||
screen->display->monitor_cache_invalidated = FALSE;
|
||||
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
@ -2260,24 +2163,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
pointer_position.x = root_x_return;
|
||||
pointer_position.y = root_y_return;
|
||||
pointer_position.width = pointer_position.height = 1;
|
||||
|
||||
screen->last_monitor_index = 0;
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
|
||||
&pointer_position))
|
||||
{
|
||||
screen->last_monitor_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Rechecked current monitor, now %d\n",
|
||||
screen->last_monitor_index);
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
@ -2959,19 +2845,15 @@ meta_screen_resize_func (MetaScreen *screen,
|
||||
meta_window_recalc_features (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_resize (MetaScreen *screen,
|
||||
int width,
|
||||
int height)
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *manager,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
GSList *windows, *tmp;
|
||||
MetaMonitorInfo *old_monitor_infos;
|
||||
GSList *tmp, *windows;
|
||||
|
||||
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;
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
set_desktop_geometry_hint (screen);
|
||||
@ -2983,8 +2865,8 @@ meta_screen_resize (MetaScreen *screen,
|
||||
|
||||
changes.x = 0;
|
||||
changes.y = 0;
|
||||
changes.width = width;
|
||||
changes.height = height;
|
||||
changes.width = screen->rect.width;
|
||||
changes.height = screen->rect.height;
|
||||
|
||||
XConfigureWindow(screen->display->xdisplay,
|
||||
screen->guard_window,
|
||||
@ -2994,14 +2876,15 @@ meta_screen_resize (MetaScreen *screen,
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen, width, height);
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
|
||||
/* Queue a resize on all the windows */
|
||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||
|
||||
/* Fix up monitor for all windows on this screen */
|
||||
windows = meta_display_list_windows (screen->display,
|
||||
META_LIST_DEFAULT);
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
@ -3010,7 +2893,6 @@ meta_screen_resize (MetaScreen *screen,
|
||||
meta_window_update_for_monitors_changed (window);
|
||||
}
|
||||
|
||||
g_free (old_monitor_infos);
|
||||
g_slist_free (windows);
|
||||
|
||||
meta_screen_queue_check_fullscreen (screen);
|
||||
|
133
src/core/util.c
133
src/core/util.c
@ -332,6 +332,8 @@ 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";
|
||||
}
|
||||
@ -389,91 +391,100 @@ meta_topic_real (MetaDebugTopic topic,
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void
|
||||
logfile_log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
switch (log_level & G_LOG_LEVEL_MASK) {
|
||||
case G_LOG_LEVEL_ERROR:
|
||||
utf8_fputs ("ERROR: ", logfile);
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_CRITICAL:
|
||||
utf8_fputs ("CRITICAL: ", logfile);
|
||||
break;
|
||||
|
||||
case G_LOG_LEVEL_WARNING:
|
||||
utf8_fputs ("WARNING: ", logfile);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* the other levels don't go through
|
||||
g_log, they go directly to the log file */
|
||||
;
|
||||
}
|
||||
|
||||
utf8_fputs (message, logfile);
|
||||
}
|
||||
|
||||
void
|
||||
meta_debug_init (void)
|
||||
{
|
||||
ensure_logfile ();
|
||||
|
||||
if (logfile)
|
||||
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK,
|
||||
logfile_log_handler, NULL);
|
||||
}
|
||||
#else
|
||||
void
|
||||
meta_debug_init (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_bug (const char *format, ...)
|
||||
{
|
||||
char *stripped;
|
||||
va_list args;
|
||||
gchar *str;
|
||||
FILE *out;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
|
||||
stripped = g_strstrip (g_strdup (format));
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, stripped, args);
|
||||
va_end (args);
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
out = logfile ? logfile : stderr;
|
||||
#else
|
||||
out = stderr;
|
||||
#endif
|
||||
|
||||
if (no_prefix == 0)
|
||||
utf8_fputs (_("Bug in window manager: "), out);
|
||||
utf8_fputs (str, out);
|
||||
|
||||
fflush (out);
|
||||
|
||||
g_free (str);
|
||||
|
||||
/* stop us in a debugger */
|
||||
abort ();
|
||||
g_free (stripped);
|
||||
}
|
||||
|
||||
void
|
||||
meta_warning (const char *format, ...)
|
||||
{
|
||||
char *stripped;
|
||||
va_list args;
|
||||
gchar *str;
|
||||
FILE *out;
|
||||
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
|
||||
stripped = g_strstrip (g_strdup (format));
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, stripped, args);
|
||||
va_end (args);
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
out = logfile ? logfile : stderr;
|
||||
#else
|
||||
out = stderr;
|
||||
#endif
|
||||
|
||||
if (no_prefix == 0)
|
||||
utf8_fputs (_("Window manager warning: "), out);
|
||||
utf8_fputs (str, out);
|
||||
|
||||
fflush (out);
|
||||
|
||||
g_free (str);
|
||||
g_free (stripped);
|
||||
}
|
||||
|
||||
void
|
||||
meta_fatal (const char *format, ...)
|
||||
{
|
||||
char *stripped;
|
||||
va_list args;
|
||||
gchar *str;
|
||||
FILE *out;
|
||||
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
|
||||
stripped = g_strstrip (g_strdup (format));
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, stripped, args);
|
||||
va_end (args);
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
out = logfile ? logfile : stderr;
|
||||
#else
|
||||
out = stderr;
|
||||
#endif
|
||||
|
||||
if (no_prefix == 0)
|
||||
utf8_fputs (_("Window manager error: "), out);
|
||||
utf8_fputs (str, out);
|
||||
|
||||
fflush (out);
|
||||
|
||||
g_free (str);
|
||||
g_free (stripped);
|
||||
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
}
|
||||
@ -495,7 +506,6 @@ meta_pop_no_msg_prefix (void)
|
||||
void
|
||||
meta_exit (MetaExitCode code)
|
||||
{
|
||||
|
||||
exit (code);
|
||||
}
|
||||
|
||||
@ -637,8 +647,13 @@ meta_show_dialog (const char *type,
|
||||
|
||||
append_argument (args, "zenity");
|
||||
append_argument (args, type);
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
|
||||
if (display)
|
||||
{
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
}
|
||||
|
||||
append_argument (args, "--class");
|
||||
append_argument (args, "mutter-dialog");
|
||||
append_argument (args, "--title");
|
||||
|
@ -165,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. */
|
||||
long fullscreen_monitors[4];
|
||||
gint fullscreen_monitors[4];
|
||||
|
||||
/* Whether we're trying to constrain the window to be fully onscreen */
|
||||
guint require_fully_onscreen : 1;
|
||||
@ -394,6 +394,9 @@ 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
|
||||
|
@ -289,6 +289,35 @@ 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,
|
||||
@ -1766,6 +1795,7 @@ 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 },
|
||||
|
@ -145,6 +145,8 @@ static void meta_window_move_between_rects (MetaWindow *window,
|
||||
static void unmaximize_window_before_freeing (MetaWindow *window);
|
||||
static void unminimize_window_and_all_transient_parents (MetaWindow *window);
|
||||
|
||||
static void meta_window_update_monitor (MetaWindow *window);
|
||||
|
||||
/* Idle handlers for the three queues (run with meta_later_add()). The
|
||||
* "data" parameter in each case will be a GINT_TO_POINTER of the
|
||||
* index into the queue arrays to use.
|
||||
@ -2106,10 +2108,14 @@ set_net_wm_state (MetaWindow *window)
|
||||
|
||||
if (window->fullscreen)
|
||||
{
|
||||
data[0] = window->fullscreen_monitors[0];
|
||||
data[1] = window->fullscreen_monitors[1];
|
||||
data[2] = window->fullscreen_monitors[2];
|
||||
data[3] = window->fullscreen_monitors[3];
|
||||
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[0]);
|
||||
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[1]);
|
||||
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[2]);
|
||||
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[3]);
|
||||
|
||||
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
|
||||
meta_error_trap_push (window->display);
|
||||
@ -4767,6 +4773,12 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
if (window->type == META_WINDOW_DESKTOP)
|
||||
return;
|
||||
|
||||
if (window->override_redirect)
|
||||
{
|
||||
meta_window_update_monitor (window);
|
||||
return;
|
||||
}
|
||||
|
||||
old = window->monitor;
|
||||
|
||||
/* Start on primary */
|
||||
@ -4777,7 +4789,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
{
|
||||
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
|
||||
|
||||
if (info->output == old->output)
|
||||
if (info->output_id != 0 &&
|
||||
info->output_id == old->output_id)
|
||||
{
|
||||
new = info;
|
||||
break;
|
||||
@ -5813,7 +5826,18 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
||||
rect->height -= borders.invisible.top + borders.invisible.bottom;
|
||||
}
|
||||
else
|
||||
*rect = window->rect;
|
||||
{
|
||||
*rect = window->rect;
|
||||
|
||||
if (window->has_custom_frame_extents)
|
||||
{
|
||||
GtkBorder *extents = &window->custom_frame_extents;
|
||||
rect->x += extents->left;
|
||||
rect->y += extents->top;
|
||||
rect->width -= extents->left + extents->right;
|
||||
rect->height -= extents->top + extents->bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
@ -7111,10 +7135,14 @@ meta_window_client_message (MetaWindow *window,
|
||||
meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
|
||||
window->desc);
|
||||
|
||||
top = event->xclient.data.l[0];
|
||||
bottom = event->xclient.data.l[1];
|
||||
left = event->xclient.data.l[2];
|
||||
right = event->xclient.data.l[3];
|
||||
top = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[0]);
|
||||
bottom = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[1]);
|
||||
left = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[2]);
|
||||
right = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[3]);
|
||||
/* source_indication = event->xclient.data.l[4]; */
|
||||
|
||||
meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
|
||||
@ -8243,9 +8271,6 @@ recalc_window_features (MetaWindow *window)
|
||||
if (window->type == META_WINDOW_TOOLBAR)
|
||||
window->decorated = FALSE;
|
||||
|
||||
if (meta_window_is_attached_dialog (window))
|
||||
window->border_only = TRUE;
|
||||
|
||||
if (window->type == META_WINDOW_DESKTOP ||
|
||||
window->type == META_WINDOW_DOCK ||
|
||||
window->override_redirect)
|
||||
@ -8916,7 +8941,7 @@ update_move (MetaWindow *window,
|
||||
* refers to the monitor which contains the largest part of the window,
|
||||
* the latter to the one where the pointer is located.
|
||||
*/
|
||||
monitor = meta_screen_get_current_monitor_info (window->screen);
|
||||
monitor = meta_screen_get_current_monitor_info_for_pos (window->screen, x, y);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor->number,
|
||||
&work_area);
|
||||
@ -10978,7 +11003,7 @@ meta_window_get_frame_type (MetaWindow *window)
|
||||
/* can't add border if undecorated */
|
||||
return META_FRAME_TYPE_LAST;
|
||||
}
|
||||
else if ((window->border_only && base_type != META_FRAME_TYPE_ATTACHED) ||
|
||||
else if (window->border_only ||
|
||||
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)) ||
|
||||
(window->hide_titlebar_when_maximized && META_WINDOW_TILED_SIDE_BY_SIDE (window)))
|
||||
{
|
||||
|
@ -54,9 +54,6 @@ 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)
|
||||
@ -66,12 +63,16 @@ 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)
|
||||
@ -79,6 +80,7 @@ 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
|
||||
|
@ -48,5 +48,6 @@ void meta_set_stage_input_region (MetaScreen *screen,
|
||||
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
|
||||
|
@ -205,6 +205,21 @@ 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
|
||||
@ -214,6 +229,7 @@ struct _MetaPluginClass
|
||||
* Returns: a #MetaPluginInfo.
|
||||
*/
|
||||
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -360,6 +376,10 @@ 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
|
||||
|
@ -64,7 +64,6 @@ 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);
|
||||
|
||||
|
@ -49,7 +49,6 @@
|
||||
* @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
|
||||
@ -88,7 +87,6 @@ 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,
|
||||
@ -136,7 +134,6 @@ 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);
|
||||
|
@ -1,87 +0,0 @@
|
||||
/* -*- 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
|
@ -78,6 +78,9 @@ MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
|
||||
int meta_screen_get_n_monitors (MetaScreen *screen);
|
||||
int meta_screen_get_primary_monitor (MetaScreen *screen);
|
||||
int meta_screen_get_current_monitor (MetaScreen *screen);
|
||||
int meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
|
||||
int x,
|
||||
int y);
|
||||
void meta_screen_get_monitor_geometry (MetaScreen *screen,
|
||||
int monitor,
|
||||
MetaRectangle *geometry);
|
||||
|
@ -33,8 +33,7 @@
|
||||
typedef struct _MetaTheme MetaTheme;
|
||||
|
||||
MetaTheme* meta_theme_get_current (void);
|
||||
void meta_theme_set_current (const char *name,
|
||||
gboolean force_reload);
|
||||
void meta_theme_set_current (const char *name);
|
||||
|
||||
MetaTheme* meta_theme_new (void);
|
||||
void meta_theme_free (MetaTheme *theme);
|
||||
|
@ -100,7 +100,8 @@ 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_EDGE_RESISTANCE = 1 << 21,
|
||||
META_DEBUG_DBUS = 1 << 22
|
||||
} MetaDebugTopic;
|
||||
|
||||
void meta_topic_real (MetaDebugTopic topic,
|
||||
@ -109,6 +110,8 @@ void meta_topic_real (MetaDebugTopic topic,
|
||||
void meta_add_verbose_topic (MetaDebugTopic topic);
|
||||
void meta_remove_verbose_topic (MetaDebugTopic topic);
|
||||
|
||||
void meta_debug_init (void);
|
||||
|
||||
void meta_push_no_msg_prefix (void);
|
||||
void meta_pop_no_msg_prefix (void);
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 220 B |
Binary file not shown.
Before Width: | Height: | Size: 166 B |
Binary file not shown.
Before Width: | Height: | Size: 145 B |
@ -1,8 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
metacity-grayscale
|
||||
metacity-message
|
||||
metacity-mag
|
||||
metacity-properties
|
||||
metacity-properties.desktop
|
||||
metacity-window-demo
|
@ -1,34 +0,0 @@
|
||||
@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)
|
||||
|
@ -1,107 +0,0 @@
|
||||
/* 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;
|
||||
}
|
@ -1,299 +0,0 @@
|
||||
/* 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;
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
/* 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.
Before Width: | Height: | Size: 3.4 KiB |
@ -40,7 +40,6 @@ typedef enum
|
||||
{
|
||||
MENU_ITEM_SEPARATOR = 0,
|
||||
MENU_ITEM_NORMAL,
|
||||
MENU_ITEM_IMAGE,
|
||||
MENU_ITEM_CHECKBOX,
|
||||
MENU_ITEM_RADIOBUTTON,
|
||||
MENU_ITEM_WORKSPACE_LIST,
|
||||
@ -50,7 +49,6 @@ struct _MenuItem
|
||||
{
|
||||
MetaMenuOp op;
|
||||
MetaMenuItemType type;
|
||||
const char *stock_id;
|
||||
const gboolean checked;
|
||||
const char *label;
|
||||
};
|
||||
@ -66,42 +64,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_IMAGE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") },
|
||||
{ META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") },
|
||||
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Unma_ximize") },
|
||||
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Roll _Up") },
|
||||
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Unroll") },
|
||||
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Move") },
|
||||
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Resize") },
|
||||
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ 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 */
|
||||
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
|
||||
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, NULL, FALSE, N_("Always on _Top") },
|
||||
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, NULL, TRUE, N_("Always on _Top") },
|
||||
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Always on Visible Workspace") },
|
||||
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, 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, NULL, FALSE, N_("_Only on This Workspace") },
|
||||
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, 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, NULL, FALSE, N_("Move to Workspace _Left") },
|
||||
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, 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, NULL, FALSE, N_("Move to Workspace R_ight") },
|
||||
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, 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, NULL, FALSE, N_("Move to Workspace _Up") },
|
||||
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, 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, NULL, FALSE, N_("Move to Workspace _Down") },
|
||||
{ 0, MENU_ITEM_WORKSPACE_LIST, NULL, FALSE, NULL },
|
||||
{ 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
|
||||
{ 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 */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_DELETE, MENU_ITEM_IMAGE, METACITY_STOCK_DELETE, FALSE, N_("_Close") }
|
||||
{ META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
|
||||
};
|
||||
|
||||
static void
|
||||
@ -274,16 +272,6 @@ 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 ();
|
||||
@ -392,8 +380,7 @@ meta_window_menu_new (MetaFrames *frames,
|
||||
int j;
|
||||
|
||||
MenuItem to_another_workspace = {
|
||||
0, MENU_ITEM_NORMAL,
|
||||
NULL, FALSE,
|
||||
0, MENU_ITEM_NORMAL, FALSE,
|
||||
N_("Move to Another _Workspace")
|
||||
};
|
||||
|
||||
|
@ -27,11 +27,6 @@
|
||||
#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;
|
||||
|
@ -1,496 +0,0 @@
|
||||
/* -*- 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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -5063,16 +5063,14 @@ meta_theme_get_current (void)
|
||||
}
|
||||
|
||||
void
|
||||
meta_theme_set_current (const char *name,
|
||||
gboolean force_reload)
|
||||
meta_theme_set_current (const char *name)
|
||||
{
|
||||
MetaTheme *new_theme;
|
||||
GError *err;
|
||||
|
||||
meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
|
||||
|
||||
if (!force_reload &&
|
||||
meta_current_theme &&
|
||||
if (meta_current_theme &&
|
||||
strcmp (name, meta_current_theme->name) == 0)
|
||||
return;
|
||||
|
||||
|
53
src/ui/ui.c
53
src/ui/ui.c
@ -4,7 +4,6 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -31,13 +30,10 @@
|
||||
#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,
|
||||
@ -62,8 +58,6 @@ meta_ui_init (void)
|
||||
{
|
||||
if (!gtk_init_check (NULL, NULL))
|
||||
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
||||
|
||||
meta_stock_icons_init ();
|
||||
}
|
||||
|
||||
Display*
|
||||
@ -775,10 +769,9 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_set_current_theme (const char *name,
|
||||
gboolean force_reload)
|
||||
meta_ui_set_current_theme (const char *name)
|
||||
{
|
||||
meta_theme_set_current (name, force_reload);
|
||||
meta_theme_set_current (name);
|
||||
meta_invalidate_default_icons ();
|
||||
}
|
||||
|
||||
@ -998,48 +991,6 @@ 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)
|
||||
{
|
||||
|
@ -154,8 +154,7 @@ 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,
|
||||
gboolean force_reload);
|
||||
void meta_ui_set_current_theme (const char *name);
|
||||
gboolean meta_ui_have_a_theme (void);
|
||||
|
||||
/* Not a real key symbol but means "key above the tab key"; this is
|
||||
|
@ -1,7 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
wm-tester
|
||||
test-size-hints
|
@ -1,33 +0,0 @@
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@
|
||||
|
||||
wm_tester_SOURCES= \
|
||||
main.c
|
||||
|
||||
test_gravity_SOURCES= \
|
||||
test-gravity.c
|
||||
|
||||
focus_window_SOURCES= \
|
||||
focus-window.c
|
||||
|
||||
test_resizing_SOURCES= \
|
||||
test-resizing.c
|
||||
|
||||
test_size_hints_SOURCES= \
|
||||
test-size-hints.c
|
||||
|
||||
test_attached_SOURCES= \
|
||||
test-attached.c
|
||||
|
||||
test_focus_SOURCES= \
|
||||
test-focus.c
|
||||
|
||||
noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window test-size-hints test-attached test-focus
|
||||
|
||||
wm_tester_LDADD= @MUTTER_LIBS@
|
||||
test_gravity_LDADD= @MUTTER_LIBS@
|
||||
test_resizing_LDADD= @MUTTER_LIBS@
|
||||
test_size_hints_LDADD= @MUTTER_LIBS@
|
||||
focus_window_LDADD= @MUTTER_LIBS@
|
||||
test_attached_LDADD= @MUTTER_LIBS@
|
||||
test_focus_LDADD= @MUTTER_LIBS@
|
@ -1,37 +0,0 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
Display *d;
|
||||
Window w;
|
||||
const char *w_str;
|
||||
char *end;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf (stderr, "Usage: focus-window WINDOWID\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
d = XOpenDisplay (NULL);
|
||||
|
||||
w_str = argv[1];
|
||||
end = NULL;
|
||||
|
||||
w = strtoul (w_str, &end, 16);
|
||||
if (end == w_str)
|
||||
{
|
||||
fprintf (stderr, "Usage: focus-window WINDOWID\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
printf ("Setting input focus to 0x%lx\n", w);
|
||||
XSetInputFocus (d, w, RevertToPointerRoot, CurrentTime);
|
||||
XFlush (d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,245 +0,0 @@
|
||||
/* WM tester main() */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 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 <gtk/gtk.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void set_up_the_evil (void);
|
||||
static void set_up_icon_windows (void);
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
g_print ("wm-tester [--evil] [--icon-windows]\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
gboolean do_evil;
|
||||
gboolean do_icon_windows;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
do_evil = FALSE;
|
||||
do_icon_windows = FALSE;
|
||||
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
{
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (strcmp (arg, "--help") == 0 ||
|
||||
strcmp (arg, "-h") == 0 ||
|
||||
strcmp (arg, "-?") == 0)
|
||||
usage ();
|
||||
else if (strcmp (arg, "--evil") == 0)
|
||||
do_evil = TRUE;
|
||||
else if (strcmp (arg, "--icon-windows") == 0)
|
||||
do_icon_windows = TRUE;
|
||||
else
|
||||
usage ();
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Be sure some option was provided */
|
||||
if (! (do_evil || do_icon_windows))
|
||||
return 1;
|
||||
|
||||
if (do_evil)
|
||||
set_up_the_evil ();
|
||||
|
||||
if (do_icon_windows)
|
||||
set_up_icon_windows ();
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GSList *evil_windows = NULL;
|
||||
|
||||
static gint
|
||||
evil_timeout (gpointer data)
|
||||
{
|
||||
int i;
|
||||
int n_windows;
|
||||
int len;
|
||||
int create_count;
|
||||
int destroy_count;
|
||||
|
||||
len = g_slist_length (evil_windows);
|
||||
|
||||
if (len > 35)
|
||||
{
|
||||
create_count = 2;
|
||||
destroy_count = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
create_count = 5;
|
||||
destroy_count = 5;
|
||||
}
|
||||
|
||||
/* Create some windows */
|
||||
n_windows = g_random_int_range (0, create_count);
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
GtkWidget *w;
|
||||
GtkWidget *c;
|
||||
int t;
|
||||
GtkWidget *parent;
|
||||
|
||||
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
gtk_window_move (GTK_WINDOW (w),
|
||||
g_random_int_range (0,
|
||||
gdk_screen_width ()),
|
||||
g_random_int_range (0,
|
||||
gdk_screen_height ()));
|
||||
|
||||
parent = NULL;
|
||||
|
||||
/* set transient for random window (may create all kinds of weird cycles) */
|
||||
if (len > 0)
|
||||
{
|
||||
t = g_random_int_range (- (len / 3), len);
|
||||
if (t >= 0)
|
||||
{
|
||||
parent = g_slist_nth_data (evil_windows, t);
|
||||
|
||||
if (parent != NULL)
|
||||
gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (parent));
|
||||
}
|
||||
}
|
||||
|
||||
if (parent != NULL)
|
||||
c = gtk_button_new_with_label ("Evil Transient!");
|
||||
else
|
||||
c = gtk_button_new_with_label ("Evil Window!");
|
||||
gtk_container_add (GTK_CONTAINER (w), c);
|
||||
|
||||
gtk_widget_show_all (w);
|
||||
|
||||
evil_windows = g_slist_prepend (evil_windows, w);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
/* Destroy some windows */
|
||||
if (len > destroy_count)
|
||||
{
|
||||
n_windows = g_random_int_range (0, destroy_count);
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
w = g_slist_nth_data (evil_windows,
|
||||
g_random_int_range (0, len));
|
||||
if (w)
|
||||
{
|
||||
--len;
|
||||
evil_windows = g_slist_remove (evil_windows, w);
|
||||
gtk_widget_destroy (w);
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_the_evil (void)
|
||||
{
|
||||
g_timeout_add (400, evil_timeout, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_icon_windows (void)
|
||||
{
|
||||
int i;
|
||||
int n_windows;
|
||||
|
||||
/* Create some windows */
|
||||
n_windows = 9;
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
GtkWidget *w;
|
||||
GtkWidget *c;
|
||||
GList *icons;
|
||||
GdkPixbuf *pix;
|
||||
|
||||
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
c = gtk_button_new_with_label ("Icon window");
|
||||
gtk_container_add (GTK_CONTAINER (w), c);
|
||||
|
||||
icons = NULL;
|
||||
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_LARGE_TOOLBAR,
|
||||
NULL);
|
||||
|
||||
icons = g_list_append (icons, pix);
|
||||
|
||||
if (i % 2)
|
||||
{
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_DIALOG,
|
||||
NULL);
|
||||
icons = g_list_append (icons, pix);
|
||||
}
|
||||
|
||||
if (i % 3)
|
||||
{
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_MENU,
|
||||
NULL);
|
||||
icons = g_list_append (icons, pix);
|
||||
}
|
||||
|
||||
gtk_window_set_icon_list (GTK_WINDOW (w), icons);
|
||||
|
||||
g_list_foreach (icons, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (icons);
|
||||
|
||||
gtk_widget_show_all (w);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
enum {
|
||||
DESTROY_PARENT,
|
||||
DETACH,
|
||||
ATTACH_1,
|
||||
ATTACH_2
|
||||
};
|
||||
|
||||
GtkWidget *window1, *window2;
|
||||
|
||||
static void
|
||||
dialog_response (GtkDialog *dialog, int response, gpointer user_data)
|
||||
{
|
||||
if (response == DESTROY_PARENT)
|
||||
{
|
||||
GtkWidget *window = GTK_WIDGET (gtk_window_get_transient_for (GTK_WINDOW (dialog)));
|
||||
|
||||
if (window == window1)
|
||||
{
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
|
||||
window1 = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
|
||||
window2 = NULL;
|
||||
}
|
||||
|
||||
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
|
||||
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
else if (response == DETACH)
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL);
|
||||
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
|
||||
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
|
||||
}
|
||||
else if (response == ATTACH_1)
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window1));
|
||||
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
|
||||
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
|
||||
}
|
||||
else if (response == ATTACH_2)
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window2));
|
||||
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
|
||||
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
|
||||
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
|
||||
}
|
||||
else if (response == GTK_RESPONSE_CLOSE)
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window1), "Parent 1");
|
||||
gtk_widget_show (window1);
|
||||
|
||||
window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window2), "Parent 2");
|
||||
gtk_widget_show (window2);
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons ("Child",
|
||||
NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
"Destroy Parent",
|
||||
DESTROY_PARENT,
|
||||
"Detach",
|
||||
DETACH,
|
||||
"Attach to 1",
|
||||
ATTACH_1,
|
||||
"Attach to 2",
|
||||
ATTACH_2,
|
||||
GTK_STOCK_QUIT,
|
||||
GTK_RESPONSE_CLOSE,
|
||||
NULL);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DESTROY_PARENT, FALSE);
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DETACH, FALSE);
|
||||
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), NULL);
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
GtkWidget *main_window;
|
||||
GtkWidget *noinput_window, *passive_window, *local_window;
|
||||
GtkWidget *global_window, *lame_window, *grabby_window, *dying_window;
|
||||
|
||||
static void
|
||||
clear_on_destroy (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
GtkWidget **widget_pointer = user_data;
|
||||
|
||||
*widget_pointer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
disable_take_focus (GtkWidget *window)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkWindow *gdkwindow;
|
||||
Atom *protocols, wm_take_focus;
|
||||
int n_protocols, i;
|
||||
|
||||
gtk_widget_realize (window);
|
||||
gdkwindow = gtk_widget_get_window (window);
|
||||
display = gdk_window_get_display (gdkwindow);
|
||||
|
||||
wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
|
||||
XGetWMProtocols (GDK_DISPLAY_XDISPLAY (display),
|
||||
GDK_WINDOW_XID (gdkwindow),
|
||||
&protocols, &n_protocols);
|
||||
for (i = 0; i < n_protocols; i++)
|
||||
{
|
||||
if (protocols[i] == wm_take_focus)
|
||||
{
|
||||
protocols[i] = protocols[n_protocols - 1];
|
||||
n_protocols--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display),
|
||||
GDK_WINDOW_XID (gdkwindow),
|
||||
protocols, n_protocols);
|
||||
XFree (protocols);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_input_hint (GtkWidget *window)
|
||||
{
|
||||
/* This needs to be called after gtk_widget_show, otherwise
|
||||
* GTK+ will overwrite it. */
|
||||
GdkWindow *gdkwindow = gtk_widget_get_window (window);
|
||||
XWMHints *wm_hints;
|
||||
|
||||
wm_hints = XGetWMHints (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
|
||||
GDK_WINDOW_XID (gdkwindow));
|
||||
|
||||
wm_hints->flags |= InputHint;
|
||||
wm_hints->input = False;
|
||||
|
||||
XSetWMHints (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
|
||||
GDK_WINDOW_XID (gdkwindow),
|
||||
wm_hints);
|
||||
|
||||
XFree (wm_hints);
|
||||
}
|
||||
|
||||
static void
|
||||
active_notify (GObject *obj,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkLabel *label = user_data;
|
||||
|
||||
if (gtk_window_is_active (GTK_WINDOW (obj)))
|
||||
gtk_label_set_text (label, "Focused");
|
||||
else
|
||||
gtk_label_set_text (label, "Not focused");
|
||||
}
|
||||
|
||||
static void
|
||||
make_focused_label (GtkWidget *toplevel,
|
||||
GtkWidget *parent)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_show (label);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (parent), label);
|
||||
|
||||
g_signal_connect (toplevel, "notify::is-active",
|
||||
G_CALLBACK (active_notify), label);
|
||||
active_notify (G_OBJECT (toplevel), NULL, label);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_test_dialog (GtkWidget *toplevel)
|
||||
{
|
||||
make_focused_label (toplevel, toplevel);
|
||||
gtk_widget_set_size_request (toplevel, 200, 200);
|
||||
}
|
||||
|
||||
static void
|
||||
noinput_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (noinput_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (noinput_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
noinput_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "No Input",
|
||||
"accept-focus", FALSE,
|
||||
NULL);
|
||||
setup_test_dialog (noinput_window);
|
||||
g_signal_connect (noinput_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &noinput_window);
|
||||
disable_take_focus (noinput_window);
|
||||
gtk_widget_show (noinput_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
passive_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (passive_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (passive_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
passive_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Passive Input",
|
||||
"accept-focus", TRUE,
|
||||
NULL);
|
||||
setup_test_dialog (passive_window);
|
||||
g_signal_connect (passive_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &passive_window);
|
||||
disable_take_focus (passive_window);
|
||||
gtk_widget_show (passive_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
local_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (local_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (local_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
local_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Locally Active Input",
|
||||
"accept-focus", TRUE,
|
||||
NULL);
|
||||
setup_test_dialog (local_window);
|
||||
g_signal_connect (local_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &local_window);
|
||||
gtk_widget_show (local_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
global_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (global_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (global_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
/* gtk will only process WM_TAKE_FOCUS messages if accept-focus
|
||||
* is TRUE. So we set that property and then manually clear the
|
||||
* Input WMHint.
|
||||
*/
|
||||
global_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Globally Active Input",
|
||||
"accept-focus", TRUE,
|
||||
NULL);
|
||||
setup_test_dialog (global_window);
|
||||
g_signal_connect (global_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &global_window);
|
||||
gtk_widget_show (global_window);
|
||||
clear_input_hint (global_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lame_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (lame_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (lame_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
lame_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Lame Globally Active Input",
|
||||
"accept-focus", FALSE,
|
||||
NULL);
|
||||
setup_test_dialog (lame_window);
|
||||
g_signal_connect (lame_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &lame_window);
|
||||
gtk_widget_show (lame_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
grabby_active_changed (GObject *object, GParamSpec *param, gpointer user_data)
|
||||
{
|
||||
if (gtk_window_is_active (GTK_WINDOW (grabby_window)))
|
||||
{
|
||||
GdkWindow *gdkwindow = gtk_widget_get_window (grabby_window);
|
||||
guint32 now = gdk_x11_get_server_time (gdkwindow);
|
||||
|
||||
gtk_window_present_with_time (GTK_WINDOW (main_window), now - 1);
|
||||
XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
|
||||
GDK_WINDOW_XID (gdkwindow),
|
||||
RevertToParent,
|
||||
now);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
grabby_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (grabby_window)
|
||||
gtk_window_present_with_time (GTK_WINDOW (grabby_window), gtk_get_current_event_time ());
|
||||
else
|
||||
{
|
||||
grabby_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Focus-grabbing Window",
|
||||
"accept-focus", TRUE,
|
||||
/* Because mutter maps windows
|
||||
* asynchronously, our trick won't
|
||||
* work if we try to do it when the
|
||||
* window is first mapped.
|
||||
*/
|
||||
"focus-on-map", FALSE,
|
||||
NULL);
|
||||
setup_test_dialog (grabby_window);
|
||||
g_signal_connect (grabby_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &grabby_window);
|
||||
g_signal_connect (grabby_window, "notify::is-active",
|
||||
G_CALLBACK (grabby_active_changed), NULL);
|
||||
gtk_widget_show (grabby_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dying_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
if (dying_window)
|
||||
{
|
||||
gtk_window_present_with_time (GTK_WINDOW (dying_window), gtk_get_current_event_time ());
|
||||
gtk_widget_destroy (dying_window);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
dying_window = g_object_new (GTK_TYPE_WINDOW,
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Dying Window",
|
||||
"accept-focus", TRUE,
|
||||
/* As with grabby window */
|
||||
"focus-on-map", FALSE,
|
||||
NULL);
|
||||
setup_test_dialog (dying_window);
|
||||
g_signal_connect (dying_window, "destroy",
|
||||
G_CALLBACK (clear_on_destroy), &dying_window);
|
||||
|
||||
label = gtk_label_new ("Click button again to test");
|
||||
gtk_container_add (GTK_CONTAINER (dying_window), label);
|
||||
gtk_widget_set_size_request (dying_window, 200, 200);
|
||||
|
||||
gtk_widget_show_all (dying_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
main_window_destroyed (GtkWidget *widget, gpointer user_data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GtkWidget *vbox, *button;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (main_window), "Focus Tester");
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
|
||||
gtk_box_set_homogeneous (GTK_BOX (vbox), 8);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
|
||||
gtk_container_add (GTK_CONTAINER (main_window), vbox);
|
||||
|
||||
make_focused_label (main_window, vbox);
|
||||
|
||||
/* ICCCM "No Input" mode; Input hint False, WM_TAKE_FOCUS absent */
|
||||
button = gtk_button_new_with_label ("No Input Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (noinput_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* ICCCM "Passive" mode; Input hint True, WM_TAKE_FOCUS absent */
|
||||
button = gtk_button_new_with_label ("Passive Input Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (passive_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* ICCCM "Locally Active" mode; Input hint True, WM_TAKE_FOCUS present.
|
||||
* This is the behavior of GtkWindows with accept_focus==TRUE.
|
||||
*/
|
||||
button = gtk_button_new_with_label ("Locally Active Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (local_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* ICCCM "Globally Active" mode; Input hint False, WM_TAKE_FOCUS present,
|
||||
* and the window responds to WM_TAKE_FOCUS by calling XSetInputFocus.
|
||||
*/
|
||||
button = gtk_button_new_with_label ("Globally Active Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (global_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* "Lame" Globally Active mode; like "Globally Active", except that
|
||||
* the window does not respond to WM_TAKE_FOCUS. This is the
|
||||
* behavior of GtkWindows with accept_focus==FALSE.
|
||||
*/
|
||||
button = gtk_button_new_with_label ("Globally Lame Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (lame_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* "Grabby" window; when you activate the window, it asks the wm to
|
||||
* focus the main window, but then forcibly grabs focus back with
|
||||
* a newer timestamp, causing the wm to be temporarily confused
|
||||
* about what window is focused and triggering the "Earlier attempt
|
||||
* to focus ... failed" codepath.
|
||||
*/
|
||||
button = gtk_button_new_with_label ("Grabby Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (grabby_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
/* "Dying" window; we create the window on the first click, then
|
||||
* activate it and destroy it on the second click, causing mutter to
|
||||
* do an XSetInputFocus but not receive the corresponding FocusIn.
|
||||
*/
|
||||
button = gtk_button_new_with_label ("Dying Window");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (dying_clicked), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
|
||||
gtk_widget_show_all (main_window);
|
||||
|
||||
g_signal_connect (main_window, "destroy",
|
||||
G_CALLBACK (main_window_destroyed), NULL);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,308 +0,0 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int gravities[10] = {
|
||||
NorthWestGravity,
|
||||
NorthGravity,
|
||||
NorthEastGravity,
|
||||
WestGravity,
|
||||
CenterGravity,
|
||||
EastGravity,
|
||||
SouthWestGravity,
|
||||
SouthGravity,
|
||||
SouthEastGravity,
|
||||
StaticGravity
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x, y, width, height;
|
||||
} Rectangle;
|
||||
|
||||
static Window windows[10];
|
||||
static int doubled[10] = { 0, };
|
||||
static Rectangle window_rects[10];
|
||||
|
||||
#define WINDOW_WIDTH 100
|
||||
#define WINDOW_HEIGHT 100
|
||||
|
||||
static int x_offset[3] = { 0, - WINDOW_WIDTH/2, -WINDOW_WIDTH };
|
||||
static int y_offset[3] = { 0, - WINDOW_HEIGHT/2, -WINDOW_HEIGHT };
|
||||
static double screen_x_fraction[3] = { 0, 0.5, 1.0 };
|
||||
static double screen_y_fraction[3] = { 0, 0.5, 1.0 };
|
||||
static int screen_width;
|
||||
static int screen_height;
|
||||
|
||||
static const char*
|
||||
window_gravity_to_string (int gravity)
|
||||
{
|
||||
switch (gravity)
|
||||
{
|
||||
case NorthWestGravity:
|
||||
return "NorthWestGravity";
|
||||
case NorthGravity:
|
||||
return "NorthGravity";
|
||||
case NorthEastGravity:
|
||||
return "NorthEastGravity";
|
||||
case WestGravity:
|
||||
return "WestGravity";
|
||||
case CenterGravity:
|
||||
return "CenterGravity";
|
||||
case EastGravity:
|
||||
return "EastGravity";
|
||||
case SouthWestGravity:
|
||||
return "SouthWestGravity";
|
||||
case SouthGravity:
|
||||
return "SouthGravity";
|
||||
case SouthEastGravity:
|
||||
return "SouthEastGravity";
|
||||
case StaticGravity:
|
||||
return "StaticGravity";
|
||||
default:
|
||||
return "NorthWestGravity";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_position (int i, int doubled, int *x, int *y)
|
||||
{
|
||||
if (i == 9)
|
||||
{
|
||||
*x = 150;
|
||||
*y = 150;
|
||||
}
|
||||
else
|
||||
{
|
||||
int xoff = x_offset[i % 3];
|
||||
int yoff = y_offset[i / 3];
|
||||
if (doubled)
|
||||
{
|
||||
xoff *= 2;
|
||||
yoff *= 2;
|
||||
}
|
||||
|
||||
*x = screen_x_fraction[i % 3] * screen_width + xoff;
|
||||
*y = screen_y_fraction[i / 3] * screen_height + yoff;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
find_window (Window window)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
if (windows[i] == window)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned long flags;
|
||||
unsigned long functions;
|
||||
unsigned long decorations;
|
||||
long input_mode;
|
||||
unsigned long status;
|
||||
} MotifWmHints, MwmHints;
|
||||
|
||||
#define MWM_HINTS_FUNCTIONS (1L << 0)
|
||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||
#define MWM_HINTS_INPUT_MODE (1L << 2)
|
||||
#define MWM_HINTS_STATUS (1L << 3)
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
Display *d;
|
||||
Window w;
|
||||
XSizeHints hints;
|
||||
int i;
|
||||
int screen;
|
||||
XEvent ev;
|
||||
int noframes;
|
||||
|
||||
if (argc > 1 && strcmp (argv[1], "--noframes") == 0)
|
||||
noframes = 1;
|
||||
else
|
||||
noframes = 0;
|
||||
|
||||
d = XOpenDisplay (NULL);
|
||||
|
||||
screen = DefaultScreen (d);
|
||||
screen_width = DisplayWidth (d, screen);
|
||||
screen_height = DisplayHeight (d, screen);
|
||||
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
calculate_position (i, doubled[i], &x, &y);
|
||||
|
||||
w = XCreateSimpleWindow (d, RootWindow (d, screen),
|
||||
x, y, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
|
||||
WhitePixel (d, screen), WhitePixel (d, screen));
|
||||
|
||||
windows[i] = w;
|
||||
window_rects[i].x = x;
|
||||
window_rects[i].y = y;
|
||||
window_rects[i].width = WINDOW_WIDTH;
|
||||
window_rects[i].height = WINDOW_HEIGHT;
|
||||
|
||||
XSelectInput (d, w, ButtonPressMask | ExposureMask | StructureNotifyMask);
|
||||
|
||||
hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity;
|
||||
|
||||
hints.min_width = WINDOW_WIDTH / 2;
|
||||
hints.min_height = WINDOW_HEIGHT / 2;
|
||||
|
||||
#if 1
|
||||
/* we constrain max size below the "doubled" size so that
|
||||
* the WM will have to deal with constraints
|
||||
* at the same time it's dealing with configure request
|
||||
*/
|
||||
hints.max_width = WINDOW_WIDTH * 2 - WINDOW_WIDTH / 2;
|
||||
hints.max_height = WINDOW_HEIGHT * 2 - WINDOW_HEIGHT / 2;
|
||||
#else
|
||||
hints.max_width = WINDOW_WIDTH * 2 + WINDOW_WIDTH / 2;
|
||||
hints.max_height = WINDOW_HEIGHT * 2 + WINDOW_HEIGHT / 2;
|
||||
#endif
|
||||
hints.win_gravity = gravities[i];
|
||||
|
||||
XSetWMNormalHints (d, w, &hints);
|
||||
|
||||
XStoreName (d, w, window_gravity_to_string (hints.win_gravity));
|
||||
|
||||
if (noframes)
|
||||
{
|
||||
MotifWmHints mwm;
|
||||
Atom mwm_atom;
|
||||
|
||||
mwm.decorations = 0;
|
||||
mwm.flags = MWM_HINTS_DECORATIONS;
|
||||
|
||||
mwm_atom = XInternAtom (d, "_MOTIF_WM_HINTS", False);
|
||||
|
||||
XChangeProperty (d, w, mwm_atom, mwm_atom,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *)&mwm,
|
||||
sizeof (MotifWmHints)/sizeof (long));
|
||||
}
|
||||
|
||||
XMapWindow (d, w);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
XNextEvent (d, &ev);
|
||||
|
||||
if (ev.xany.type == ConfigureNotify)
|
||||
{
|
||||
i = find_window (ev.xconfigure.window);
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
Window ignored;
|
||||
|
||||
window_rects[i].width = ev.xconfigure.width;
|
||||
window_rects[i].height = ev.xconfigure.height;
|
||||
|
||||
XClearArea (d, windows[i], 0, 0,
|
||||
ev.xconfigure.width,
|
||||
ev.xconfigure.height,
|
||||
True);
|
||||
|
||||
if (!ev.xconfigure.send_event)
|
||||
XTranslateCoordinates (d, windows[i], DefaultRootWindow (d),
|
||||
0, 0,
|
||||
&window_rects[i].x, &window_rects[i].y,
|
||||
&ignored);
|
||||
else
|
||||
{
|
||||
window_rects[i].x = ev.xconfigure.x;
|
||||
window_rects[i].y = ev.xconfigure.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev.xany.type == Expose)
|
||||
{
|
||||
i = find_window (ev.xexpose.window);
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
GC gc;
|
||||
XGCValues values;
|
||||
char buf[256];
|
||||
|
||||
values.foreground = BlackPixel (d, screen);
|
||||
|
||||
gc = XCreateGC (d, windows[i],
|
||||
GCForeground, &values);
|
||||
|
||||
sprintf (buf,
|
||||
"%d,%d",
|
||||
window_rects[i].x,
|
||||
window_rects[i].y);
|
||||
|
||||
XDrawString (d, windows[i], gc, 10, 15,
|
||||
buf, strlen (buf));
|
||||
|
||||
sprintf (buf,
|
||||
"%dx%d",
|
||||
window_rects[i].width,
|
||||
window_rects[i].height);
|
||||
|
||||
XDrawString (d, windows[i], gc, 10, 35,
|
||||
buf, strlen (buf));
|
||||
|
||||
XFreeGC (d, gc);
|
||||
}
|
||||
}
|
||||
else if (ev.xany.type == ButtonPress)
|
||||
{
|
||||
i = find_window (ev.xbutton.window);
|
||||
|
||||
if (i >= 0)
|
||||
{
|
||||
/* Button 1 = move, 2 = resize, 3 = both at once */
|
||||
|
||||
if (ev.xbutton.button == Button1)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
calculate_position (i, doubled[i], &x, &y);
|
||||
XMoveWindow (d, windows[i], x, y);
|
||||
}
|
||||
else if (ev.xbutton.button == Button2)
|
||||
{
|
||||
if (doubled[i])
|
||||
XResizeWindow (d, windows[i], WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
else
|
||||
XResizeWindow (d, windows[i], WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
|
||||
|
||||
doubled[i] = !doubled[i];
|
||||
}
|
||||
else if (ev.xbutton.button == Button3)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
calculate_position (i, !doubled[i], &x, &y);
|
||||
|
||||
if (doubled[i])
|
||||
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
else
|
||||
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
|
||||
|
||||
doubled[i] = !doubled[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This program has an infinite loop above so a return statement would
|
||||
* just cause compiler warnings.
|
||||
*/
|
||||
}
|
||||
|
@ -1,257 +0,0 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
static void
|
||||
calc_rects (XRectangle *rects, int width, int height)
|
||||
{
|
||||
int w = (width - 21) / 3;
|
||||
int h = (height - 21) / 3;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (i < 9)
|
||||
{
|
||||
rects[i].width = w;
|
||||
rects[i].height = h;
|
||||
++i;
|
||||
}
|
||||
|
||||
/* NW */
|
||||
rects[0].x = 0;
|
||||
rects[0].y = 0;
|
||||
|
||||
/* N */
|
||||
rects[1].x = width / 2 - w / 2;
|
||||
rects[1].y = 0;
|
||||
|
||||
/* NE */
|
||||
rects[2].x = width - w;
|
||||
rects[2].y = 0;
|
||||
|
||||
/* E */
|
||||
rects[3].x = width - w;
|
||||
rects[3].y = height / 2 - h / 2;
|
||||
|
||||
/* SE */
|
||||
rects[4].x = width - w;
|
||||
rects[4].y = height - h;
|
||||
|
||||
/* S */
|
||||
rects[5].x = width / 2 - w / 2;
|
||||
rects[5].y = height - h;
|
||||
|
||||
/* SW */
|
||||
rects[6].x = 0;
|
||||
rects[6].y = height - h;
|
||||
|
||||
/* W */
|
||||
rects[7].x = 0;
|
||||
rects[7].y = height / 2 - h / 2;
|
||||
|
||||
/* Center */
|
||||
rects[8].x = width / 2 - w / 2;
|
||||
rects[8].y = height / 2 - h / 2;
|
||||
}
|
||||
|
||||
static Bool
|
||||
all_events (Display *display,
|
||||
XEvent *event,
|
||||
XPointer arg)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
static void
|
||||
get_size (Display *d, Drawable draw,
|
||||
int *xp, int *yp, int *widthp, int *heightp)
|
||||
{
|
||||
int x, y;
|
||||
unsigned int width=0, height=0, border=0, depth=0;
|
||||
Window root;
|
||||
|
||||
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
|
||||
|
||||
if (xp)
|
||||
*xp = x;
|
||||
if (yp)
|
||||
*yp = y;
|
||||
if (widthp)
|
||||
*widthp = width;
|
||||
if (heightp)
|
||||
*heightp = height;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
Display *d;
|
||||
Window w, cw;
|
||||
XSizeHints hints;
|
||||
int screen;
|
||||
XEvent ev;
|
||||
int x, y, width, height;
|
||||
Pixmap pix;
|
||||
GC gc;
|
||||
XGCValues gc_vals;
|
||||
XSetWindowAttributes set_attrs;
|
||||
XWindowChanges changes;
|
||||
XRectangle rects[9];
|
||||
gboolean redraw_pending;
|
||||
unsigned int mask;
|
||||
|
||||
d = XOpenDisplay (NULL);
|
||||
|
||||
screen = DefaultScreen (d);
|
||||
|
||||
/* Print some debug spew to show how StaticGravity works */
|
||||
w = XCreateSimpleWindow (d, RootWindow (d, screen),
|
||||
0, 0, 100, 100, 0,
|
||||
WhitePixel (d, screen),
|
||||
WhitePixel (d, screen));
|
||||
cw = XCreateSimpleWindow (d, w,
|
||||
0, 0, 100, 100, 0,
|
||||
WhitePixel (d, screen),
|
||||
WhitePixel (d, screen));
|
||||
set_attrs.win_gravity = StaticGravity;
|
||||
|
||||
XChangeWindowAttributes (d, cw,
|
||||
CWWinGravity,
|
||||
&set_attrs);
|
||||
|
||||
get_size (d, w, &x, &y, &width, &height);
|
||||
|
||||
g_print ("Parent is %d,%d %d x %d before configuring parent\n",
|
||||
x, y, width, height);
|
||||
|
||||
get_size (d, cw, &x, &y, &width, &height);
|
||||
|
||||
g_print ("Child is %d,%d %d x %d before configuring parent\n",
|
||||
x, y, width, height);
|
||||
|
||||
changes.x = 10;
|
||||
changes.y = 10;
|
||||
changes.width = 110;
|
||||
changes.height = 110;
|
||||
/* last mask wins */
|
||||
mask = CWX | CWY;
|
||||
mask = CWWidth | CWHeight;
|
||||
mask = CWX | CWY | CWWidth | CWHeight;
|
||||
|
||||
XConfigureWindow (d, w, mask, &changes);
|
||||
XSync (d, False);
|
||||
|
||||
get_size (d, w, &x, &y, &width, &height);
|
||||
|
||||
g_print ("Parent is %d,%d %d x %d after configuring parent\n",
|
||||
x, y, width, height);
|
||||
|
||||
get_size (d, cw, &x, &y, &width, &height);
|
||||
|
||||
g_print ("Child is %d,%d %d x %d after configuring parent\n",
|
||||
x, y, width, height);
|
||||
|
||||
XDestroyWindow (d, w);
|
||||
|
||||
/* The window that gets displayed */
|
||||
|
||||
x = 20;
|
||||
y = 20;
|
||||
width = 100;
|
||||
height = 100;
|
||||
|
||||
calc_rects (rects, width, height);
|
||||
|
||||
w = XCreateSimpleWindow (d, RootWindow (d, screen),
|
||||
x, y, width, height, 0,
|
||||
WhitePixel (d, screen),
|
||||
WhitePixel (d, screen));
|
||||
|
||||
set_attrs.bit_gravity = StaticGravity;
|
||||
|
||||
XChangeWindowAttributes (d, w,
|
||||
CWBitGravity,
|
||||
&set_attrs);
|
||||
|
||||
XSelectInput (d, w,
|
||||
ButtonPressMask | ExposureMask | StructureNotifyMask);
|
||||
|
||||
hints.flags = PMinSize;
|
||||
|
||||
hints.min_width = 100;
|
||||
hints.min_height = 100;
|
||||
|
||||
XSetWMNormalHints (d, w, &hints);
|
||||
XMapWindow (d, w);
|
||||
|
||||
redraw_pending = FALSE;
|
||||
while (1)
|
||||
{
|
||||
XNextEvent (d, &ev);
|
||||
|
||||
switch (ev.xany.type)
|
||||
{
|
||||
case ButtonPress:
|
||||
if (ev.xbutton.button == 3)
|
||||
{
|
||||
g_print ("Exiting on button 3 press\n");
|
||||
exit (0);
|
||||
}
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
x = ev.xconfigure.x;
|
||||
y = ev.xconfigure.y;
|
||||
width = ev.xconfigure.width;
|
||||
height = ev.xconfigure.height;
|
||||
|
||||
redraw_pending = TRUE;
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
redraw_pending = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Primitive event compression */
|
||||
if (XCheckIfEvent (d, &ev, all_events, NULL))
|
||||
{
|
||||
XPutBackEvent (d, &ev);
|
||||
}
|
||||
else if (redraw_pending)
|
||||
{
|
||||
calc_rects (rects, width, height);
|
||||
|
||||
pix = XCreatePixmap (d, w, width, height,
|
||||
DefaultDepth (d, screen));
|
||||
|
||||
gc_vals.foreground = WhitePixel (d, screen);
|
||||
|
||||
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
|
||||
|
||||
XFillRectangle (d, pix, gc, 0, 0, width, height);
|
||||
|
||||
/* Draw rectangles at each gravity point */
|
||||
gc_vals.foreground = BlackPixel (d, screen);
|
||||
XChangeGC (d, gc, GCForeground, &gc_vals);
|
||||
|
||||
XFillRectangles (d, pix, gc, rects, G_N_ELEMENTS (rects));
|
||||
|
||||
XCopyArea (d, pix, w, gc, 0, 0, width, height, 0, 0);
|
||||
|
||||
XFreePixmap (d, pix);
|
||||
XFreeGC (d, gc);
|
||||
|
||||
redraw_pending = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* This program has an infinite loop above so a return statement would
|
||||
* just cause compiler warnings.
|
||||
*/
|
||||
}
|
||||
|
@ -1,136 +0,0 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
static Bool
|
||||
all_events (Display *display,
|
||||
XEvent *event,
|
||||
XPointer arg)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
get_size (Display *d, Drawable draw,
|
||||
int *xp, int *yp, int *widthp, int *heightp)
|
||||
{
|
||||
int x, y;
|
||||
unsigned int width, height, border, depth;
|
||||
Window root;
|
||||
|
||||
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
|
||||
|
||||
if (xp)
|
||||
*xp = x;
|
||||
if (yp)
|
||||
*yp = y;
|
||||
if (widthp)
|
||||
*widthp = width;
|
||||
if (*heightp)
|
||||
*heightp = height;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
Display *d;
|
||||
Window zero_min_size;
|
||||
XSizeHints hints;
|
||||
int screen;
|
||||
XEvent ev;
|
||||
int x, y, width, height;
|
||||
Pixmap pix;
|
||||
GC gc;
|
||||
XGCValues gc_vals;
|
||||
gboolean redraw_pending;
|
||||
|
||||
d = XOpenDisplay (NULL);
|
||||
|
||||
screen = DefaultScreen (d);
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 100;
|
||||
height = 100;
|
||||
|
||||
zero_min_size = XCreateSimpleWindow (d, RootWindow (d, screen),
|
||||
x, y, width, height, 0,
|
||||
WhitePixel (d, screen),
|
||||
WhitePixel (d, screen));
|
||||
|
||||
XSelectInput (d, zero_min_size,
|
||||
ButtonPressMask | ExposureMask | StructureNotifyMask);
|
||||
|
||||
hints.flags = PMinSize;
|
||||
|
||||
hints.min_width = 0;
|
||||
hints.min_height = 0;
|
||||
|
||||
XSetWMNormalHints (d, zero_min_size, &hints);
|
||||
XMapWindow (d, zero_min_size);
|
||||
|
||||
redraw_pending = FALSE;
|
||||
while (1)
|
||||
{
|
||||
XNextEvent (d, &ev);
|
||||
|
||||
switch (ev.xany.type)
|
||||
{
|
||||
case ButtonPress:
|
||||
if (ev.xbutton.button == 1)
|
||||
{
|
||||
g_print ("Exiting on button 1 press\n");
|
||||
exit (0);
|
||||
}
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
x = ev.xconfigure.x;
|
||||
y = ev.xconfigure.y;
|
||||
width = ev.xconfigure.width;
|
||||
height = ev.xconfigure.height;
|
||||
|
||||
redraw_pending = TRUE;
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
redraw_pending = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Primitive event compression */
|
||||
if (XCheckIfEvent (d, &ev, all_events, NULL))
|
||||
{
|
||||
XPutBackEvent (d, &ev);
|
||||
}
|
||||
else if (redraw_pending)
|
||||
{
|
||||
pix = XCreatePixmap (d, zero_min_size, width, height,
|
||||
DefaultDepth (d, screen));
|
||||
|
||||
gc_vals.foreground = WhitePixel (d, screen);
|
||||
|
||||
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
|
||||
|
||||
XFillRectangle (d, pix, gc, 0, 0, width, height);
|
||||
|
||||
XCopyArea (d, pix, zero_min_size, gc, 0, 0, width, height, 0, 0);
|
||||
|
||||
XFreePixmap (d, pix);
|
||||
XFreeGC (d, gc);
|
||||
|
||||
redraw_pending = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* This program has an infinite loop above so a return statement would
|
||||
* just cause compiler warnings.
|
||||
*/
|
||||
}
|
||||
|
281
src/xrandr.xml
Normal file
281
src/xrandr.xml
Normal file
@ -0,0 +1,281 @@
|
||||
<!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.DisplayConfig:
|
||||
@short_description: display configuration interface
|
||||
|
||||
This interface is used by mutter and gnome-settings-daemon
|
||||
to apply multiple monitor configuration.
|
||||
-->
|
||||
|
||||
<interface name="org.gnome.Mutter.DisplayConfig">
|
||||
|
||||
<!--
|
||||
GetResources:
|
||||
@serial: configuration serial
|
||||
@crtcs: available CRTCs
|
||||
@outputs: available outputs
|
||||
@modes: available modes
|
||||
@max_screen_width:
|
||||
@max_screen_height:
|
||||
|
||||
Retrieves the current layout of the hardware.
|
||||
|
||||
@serial is an unique identifier representing the current state
|
||||
of the screen. It must be passed back to ApplyConfiguration()
|
||||
and will be increased for every configuration change (so that
|
||||
mutter can detect that the new configuration is based on old
|
||||
state).
|
||||
|
||||
A CRTC (CRT controller) is a logical monitor, ie a portion
|
||||
of the compositor coordinate space. It might correspond
|
||||
to multiple monitors, when in clone mode, but not that
|
||||
it is possible to implement clone mode also by setting different
|
||||
CRTCs to the same coordinates.
|
||||
|
||||
The number of CRTCs represent the maximum number of monitors
|
||||
that can be set to expand and it is a HW constraint; if more
|
||||
monitors are connected, then necessarily some will clone. This
|
||||
is complementary to the concept of the encoder (not exposed in
|
||||
the API), which groups outputs that necessarily will show the
|
||||
same image (again a HW constraint).
|
||||
|
||||
A CRTC is represented by a DBus structure with the following
|
||||
layout:
|
||||
* u ID: the ID in the API of this CRTC
|
||||
* x winsys_id: the low-level ID of this CRTC (which might
|
||||
be a XID, a KMS handle or something entirely
|
||||
different)
|
||||
* i x, y, width, height: the geometry of this CRTC
|
||||
(might be invalid if the CRTC is not in
|
||||
use)
|
||||
* i current_mode: the current mode of the CRTC, or -1 if this
|
||||
CRTC is not used
|
||||
Note: the size of the mode will always correspond
|
||||
to the width and height of the CRTC
|
||||
* u current_transform: the current transform (espressed according
|
||||
to the wayland protocol)
|
||||
* au transforms: all possible transforms
|
||||
* a{sv} properties: other high-level properties that affect this
|
||||
CRTC; they are not necessarily reflected in
|
||||
the hardware.
|
||||
No property is specified in this version of the API.
|
||||
|
||||
Note: all geometry information refers to the untransformed
|
||||
display.
|
||||
|
||||
An output represents a physical screen, connected somewhere to
|
||||
the computer. Floating connectors are not exposed in the API.
|
||||
An output is a DBus struct with the following fields:
|
||||
* u ID: the ID in the API
|
||||
* x winsys_id: the low-level ID of this output (XID or KMS handle)
|
||||
* i current_crtc: the CRTC that is currently driving this output,
|
||||
or -1 if the output is disabled
|
||||
* au possible_crtcs: all CRTCs that can control this output
|
||||
* s name: the name of the connector to which the output is attached
|
||||
(like VGA1 or HDMI)
|
||||
* au modes: valid modes for this output
|
||||
* au clones: valid clones for this output, ie other outputs that
|
||||
can be assigned the same CRTC as this one; if you
|
||||
want to mirror two outputs that don't have each other
|
||||
in the clone list, you must configure two different
|
||||
CRTCs for the same geometry
|
||||
* a{sv} properties: other high-level properties that affect this
|
||||
output; they are not necessarily reflected in
|
||||
the hardware.
|
||||
Known properties:
|
||||
- "vendor" (s): (readonly) the human readable name
|
||||
of the manufacturer
|
||||
- "product" (s): (readonly) the human readable name
|
||||
of the display model
|
||||
- "serial" (s): (readonly) the serial number of this
|
||||
particular hardware part
|
||||
- "display-name" (s): (readonly) a human readable name
|
||||
of this output, to be shown in the UI
|
||||
- "backlight" (i): (readonly, use the specific interface)
|
||||
the backlight value as a percentage
|
||||
(-1 if not supported)
|
||||
- "primary" (b): whether this output is primary
|
||||
or not
|
||||
- "presentation" (b): whether this output is
|
||||
for presentation only
|
||||
Note: properties might be ignored if not consistenly
|
||||
applied to all outputs in the same clone group. In
|
||||
general, it's expected that presentation or primary
|
||||
outputs will not be cloned.
|
||||
|
||||
A mode represents a set of parameters that are applied to
|
||||
each output, such as resolution and refresh rate. It is a separate
|
||||
object so that it can be referenced by CRTCs and outputs.
|
||||
Multiple outputs in the same CRTCs must all have the same mode.
|
||||
A mode is exposed as:
|
||||
* u ID: the ID in the API
|
||||
* x winsys_id: the low-level ID of this mode
|
||||
* u width, height: the resolution
|
||||
* d frequency: refresh rate
|
||||
|
||||
Output and modes are read-only objects (except for output properties),
|
||||
they can change only in accordance to HW changes (such as hotplugging
|
||||
a monitor), while CRTCs can be changed with ApplyConfiguration().
|
||||
|
||||
XXX: actually, if you insist enough, you can add new modes
|
||||
through xrandr command line or the KMS API, overriding what the
|
||||
kernel driver and the EDID say.
|
||||
Usually, it only matters with old cards with broken drivers, or
|
||||
old monitors with broken EDIDs, but it happens more often with
|
||||
projectors (if for example the kernel driver doesn't add the
|
||||
640x480 - 800x600 - 1024x768 default modes). Probably something
|
||||
that we need to handle in mutter anyway.
|
||||
-->
|
||||
<method name="GetResources">
|
||||
<arg name="serial" direction="out" type="u" />
|
||||
<arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
|
||||
<arg name="outputs" direction="out" type="a(uxiausauaua{sv})" />
|
||||
<arg name="modes" direction="out" type="a(uxuud)" />
|
||||
<arg name="max_screen_width" direction="out" type="i" />
|
||||
<arg name="max_screen_height" direction="out" type="i" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
ApplyConfiguration:
|
||||
@serial: configuration serial
|
||||
@persistent: whether this configuration should be saved on disk
|
||||
@crtcs: new data for CRTCs
|
||||
@outputs: new data for outputs
|
||||
|
||||
Applies the requested configuration changes.
|
||||
|
||||
@serial must match the serial from the last GetResources() call,
|
||||
or org.freedesktop.DBus.AccessDenied will be generated.
|
||||
|
||||
If @persistent is true, mutter will attempt to replicate this
|
||||
configuration the next time this HW layout appears.
|
||||
|
||||
@crtcs represents the new logical configuration, as a list
|
||||
of structures containing:
|
||||
- u ID: the API ID from the corresponding GetResources() call
|
||||
- i new_mode: the API ID of the new mode to configure the CRTC
|
||||
with, or -1 if the CRTC should be disabled
|
||||
- i x, y: the new coordinates of the top left corner
|
||||
the geometry will be completed with the size information
|
||||
from @new_mode
|
||||
- u transform: the desired transform
|
||||
- au outputs: the API ID of outputs that should be assigned to
|
||||
this CRTC
|
||||
- a{sv} properties: properties whose value should be changed
|
||||
|
||||
Note: CRTCs not referenced in the array will be disabled.
|
||||
|
||||
@outputs represent the output property changes as:
|
||||
- u ID: the API ID of the output to change
|
||||
- a{sv} properties: properties whose value should be changed
|
||||
|
||||
Note: both for CRTCs and outputs, properties not included in
|
||||
the dictionary will not be changed.
|
||||
|
||||
Note: unrecognized properties will have no effect, but if the
|
||||
configuration change succeeds the property will be reported
|
||||
by the next GetResources() call, and if @persistent is true,
|
||||
it will also be saved to disk.
|
||||
|
||||
If the configuration is invalid according to the previous
|
||||
GetResources() call, for example because a CRTC references
|
||||
an output it cannot drive, or not all outputs support the
|
||||
chosen mode, the error org.freedesktop.DBus.InvalidArgs will
|
||||
be generated.
|
||||
|
||||
If the configuration cannot be applied for any other reason
|
||||
(eg. the screen size would exceed texture limits), the error
|
||||
org.freedesktop.DBus.Error.LimitsExceeded will be generated.
|
||||
-->
|
||||
<method name="ApplyConfiguration">
|
||||
<arg name="serial" direction="in" type="u" />
|
||||
<arg name="persistent" direction="in" type="b" />
|
||||
<arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
|
||||
<arg name="outputs" direction="in" type="a(ua{sv})" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
ChangeBacklight:
|
||||
@serial: configuration serial
|
||||
@output: the API id of the output
|
||||
@value: the new backlight value
|
||||
|
||||
Changes the backlight of @output to @value, which is
|
||||
expressed as a percentage and rounded to the HW limits.
|
||||
-->
|
||||
<method name="ChangeBacklight">
|
||||
<arg name="serial" direction="in" type="u" />
|
||||
<arg name="output" direction="in" type="u" />
|
||||
<arg name="value" direction="in" type="i" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
GetCrtcGamma:
|
||||
@serial: configuration serial
|
||||
@crtc: API id of the crtc
|
||||
@red: red gamma ramp
|
||||
@green: green gamma ramp
|
||||
@blue: blue gamma ramp
|
||||
|
||||
Requests the current gamma ramps of @crtc.
|
||||
-->
|
||||
<method name="GetCrtcGamma">
|
||||
<arg name="serial" direction="in" type="u" />
|
||||
<arg name="crtc" direction="in" type="u" />
|
||||
<arg name="red" direction="out" type="aq" />
|
||||
<arg name="green" direction="out" type="aq" />
|
||||
<arg name="blue" direction="out" type="aq" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
SetCrtcGamma:
|
||||
@serial: configuration serial
|
||||
@crtc: API id of the crtc
|
||||
@red: red gamma ramp
|
||||
@green: green gamma ramp
|
||||
@blue: blue gamma ramp
|
||||
|
||||
Changes the gamma ramps of @crtc.
|
||||
-->
|
||||
<method name="SetCrtcGamma">
|
||||
<arg name="serial" direction="in" type="u" />
|
||||
<arg name="crtc" direction="in" type="u" />
|
||||
<arg name="red" direction="in" type="aq" />
|
||||
<arg name="green" direction="in" type="aq" />
|
||||
<arg name="blue" direction="in" type="aq" />
|
||||
</method>
|
||||
|
||||
<!--
|
||||
PowerSaveMode:
|
||||
|
||||
Contains the current power saving mode for the screen, and
|
||||
allows changing it.
|
||||
|
||||
Possible values:
|
||||
- 0: on
|
||||
- 1: standby
|
||||
- 2: suspend
|
||||
- 3: off
|
||||
- -1: unknown (unsupported)
|
||||
|
||||
A client should not attempt to change the powersave mode
|
||||
from -1 (unknown) to any other value, and viceversa.
|
||||
Note that the actual effects of the different values
|
||||
depend on the hardware and the kernel driver in use, and
|
||||
it's perfectly possible that all values different than on
|
||||
have the same effect.
|
||||
Also, setting the PowerSaveMode to 3 (off) may or may
|
||||
not have the same effect as disabling all outputs by
|
||||
setting no CRTC on them with ApplyConfiguration(), and
|
||||
may or may not cause a configuration change.
|
||||
|
||||
Also note that this property might become out of date
|
||||
if changed through different means (for example using the
|
||||
XRandR interface directly).
|
||||
-->
|
||||
<property name="PowerSaveMode" type="i" access="readwrite" />
|
||||
</interface>
|
||||
</node>
|
Reference in New Issue
Block a user