Compare commits
26 Commits
wip/displa
...
3.8.4
Author | SHA1 | Date | |
---|---|---|---|
![]() |
17185452c6 | ||
![]() |
534774a72f | ||
![]() |
efefb40e70 | ||
![]() |
ca4e1fd4c9 | ||
![]() |
74fb5a83dd | ||
![]() |
02ecca502e | ||
![]() |
e36eb3e91a | ||
![]() |
de6d9591c4 | ||
![]() |
a20401782e | ||
![]() |
79ea9f0b0f | ||
![]() |
7b36dcf4a0 | ||
![]() |
edfde6221f | ||
![]() |
1ad1357745 | ||
![]() |
fb0999a1a9 | ||
![]() |
7186ddff49 | ||
![]() |
d664cfcc90 | ||
![]() |
056cc16b82 | ||
![]() |
6c4bcecc00 | ||
![]() |
f531960b6a | ||
![]() |
e15792c983 | ||
![]() |
1627044c39 | ||
![]() |
5615e36112 | ||
![]() |
2c210e0e25 | ||
![]() |
1c06f0dc09 | ||
![]() |
51d98be1f2 | ||
![]() |
859d231129 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -46,6 +46,7 @@ POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
inlinepixbufs.h
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-theme-viewer
|
||||
@@ -61,7 +62,6 @@ mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-attached
|
||||
test-focus
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
|
63
NEWS
63
NEWS
@@ -1,61 +1,38 @@
|
||||
3.9.5
|
||||
3.8.4
|
||||
=====
|
||||
* 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]
|
||||
* Workaround failure to bring back shell interface after fullscreen game in some situations [Adel; #701224]
|
||||
* Fix sluggish and stuck pointers moving windows [Adel, Jasper: #699777]
|
||||
* Reduce log spew [Adel, Jasper; #702564, #703970]
|
||||
* Touch screen fixes [Jasper: #697192]
|
||||
* Fix rendering of large background images [Jasper, Ray: #702283]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
|
||||
Adel Gadllah, Jasper St. Pierre, Ray Strode
|
||||
|
||||
3.9.4
|
||||
=====
|
||||
* Tweak window shadows [Allan; #702141]
|
||||
* Ignore our own focus events for focus prediction [Jasper; #701017]
|
||||
* Add API to query if the stage is focused [Jasper; #700735]
|
||||
* Add API to query the monitor for a given position [Adel]
|
||||
* Don't force attached dialogs to be border-only [Florian; #702764]
|
||||
* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283]
|
||||
* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564]
|
||||
|
||||
Contributors:
|
||||
Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode
|
||||
|
||||
3.9.3
|
||||
3.8.3
|
||||
=====
|
||||
* Add support for string-array preferences [Florian; #700223]
|
||||
* Fix shade window action [Stef; #693714]
|
||||
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
|
||||
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
|
||||
* Ensure events are always reported to the grab window [Rui; #701219]
|
||||
* Use new clutter_stage_set_paint_callback() function to prevent dropping
|
||||
frames with frame synced toolkits [Owen; #698794]
|
||||
|
||||
Contributors:
|
||||
Rui Matos, Owen W. Taylor
|
||||
Rui Matos, Florian Müllner, Stef Walter, Owen W. Taylor
|
||||
|
||||
3.9.2
|
||||
=====
|
||||
* Add meta_window_can_close() function [Jasper; #699269]
|
||||
* Add support for string-array preferences [Florian; #700223]
|
||||
* Fix a potential race condition with _NET_WM_MOVERESIZE [Jasper; #699777]
|
||||
* Fix shade window action [Stef; #693714]
|
||||
* Remove overlay_group [Giovanni; #700735]
|
||||
* Improve tracking of the focus window [Dan, Jasper; #647706]
|
||||
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
|
||||
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
|
||||
* Misc bug fixes and cleanups [Dieter, Jasper, Rui; #699636, #700735, #697000]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre,
|
||||
Dieter Verfaillie, Stef Walter, Dan Winship
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb], Ján Kyselica [sk]
|
||||
|
||||
3.9.1
|
||||
3.8.2
|
||||
=====
|
||||
* Fix miscellaneous memory leaks [Pavel; #698710]
|
||||
* Misc fixes and cleanups [Stef, Simon; #698179, #697758]
|
||||
* Fix binding remaining grabbed after clearing all strokes [Rui; #697000]
|
||||
* Misc fixes [Stef; #698179]
|
||||
|
||||
Contributors:
|
||||
Simon McVittie, Pavel Vasin, Stef Walter
|
||||
Rui Matos, Pavel Vasin, Stef Walter
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb]
|
||||
|
||||
3.8.1
|
||||
=====
|
||||
|
14
configure.ac
14
configure.ac
@@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.50)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [9])
|
||||
m4_define([mutter_micro_version], [5])
|
||||
m4_define([mutter_minor_version], [8])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -75,8 +75,6 @@ MUTTER_PC_MODULES="
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.14.3
|
||||
cogl-1.0 >= 1.13.3
|
||||
upower-glib > 0.9.11
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
|
||||
GLIB_GSETTINGS
|
||||
@@ -120,6 +118,9 @@ 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"
|
||||
@@ -306,6 +307,9 @@ if test "x$found_xsync" = "xyes"; then
|
||||
fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
|
||||
|
||||
found_sm=no
|
||||
case "$MUTTER_LIBS" in
|
||||
@@ -435,8 +439,10 @@ 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,6 +409,7 @@ meta_prefs_get_theme
|
||||
meta_prefs_get_titlebar_font
|
||||
meta_prefs_get_num_workspaces
|
||||
meta_prefs_get_dynamic_workspaces
|
||||
meta_prefs_get_application_based
|
||||
meta_prefs_get_disable_workarounds
|
||||
meta_prefs_get_auto_raise
|
||||
meta_prefs_get_auto_raise_delay
|
||||
|
@@ -23,9 +23,12 @@ src/core/xprops.c
|
||||
src/mutter.desktop.in
|
||||
src/mutter-wm.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/tools/mutter-message.c
|
||||
src/ui/frames.c
|
||||
src/ui/menu.c
|
||||
src/ui/metaaccellabel.c
|
||||
src/ui/resizepopup.c
|
||||
src/ui/theme.c
|
||||
src/ui/theme-parser.c
|
||||
src/ui/theme-viewer.c
|
||||
|
||||
|
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-07-30 12:29+0000\n"
|
||||
"PO-Revision-Date: 2013-07-30 23:01+0900\n"
|
||||
"POT-Creation-Date: 2013-03-22 10:02+0000\n"
|
||||
"PO-Revision-Date: 2013-03-25 17:02+0000\n"
|
||||
"Last-Translator: Jiro Matsuzawa <jmatsuzawa@gnome.org>\n"
|
||||
"Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n"
|
||||
"Language: ja\n"
|
||||
@@ -133,7 +133,7 @@ msgstr "コマンド実行プロンプトを表示する"
|
||||
|
||||
#: ../src/50-mutter-system.xml.in.h:3
|
||||
msgid "Show the activities overview"
|
||||
msgstr "アクティビティ画面を表示する"
|
||||
msgstr "アクティビティを表示する"
|
||||
|
||||
#: ../src/50-mutter-windows.xml.in.h:1
|
||||
msgid "Windows"
|
||||
@@ -213,12 +213,12 @@ msgstr "画面右半分に表示する"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:589
|
||||
#: ../src/compositor/compositor.c:568
|
||||
#, c-format
|
||||
msgid "Another compositing manager is already running on screen %i on display \"%s\"."
|
||||
msgstr "既に別の合成マネージャーがディスプレイ \"%2$s\" 上のスクリーン %1$i で起動中です"
|
||||
|
||||
#: ../src/compositor/meta-background.c:1076
|
||||
#: ../src/compositor/meta-background.c:1191
|
||||
msgid "background texture could not be created from file"
|
||||
msgstr ""
|
||||
|
||||
@@ -252,22 +252,22 @@ msgstr "待機する(_W)"
|
||||
msgid "_Force Quit"
|
||||
msgstr "強制終了する(_F)"
|
||||
|
||||
#: ../src/core/display.c:421
|
||||
#: ../src/core/display.c:401
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "ウィンドウの合成に必要な %s という拡張モジュールが存在しません"
|
||||
|
||||
#: ../src/core/display.c:513
|
||||
#: ../src/core/display.c:493
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "X Window System のディスプレイ '%s' のオープンに失敗しました\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1138
|
||||
#: ../src/core/keybindings.c:935
|
||||
#, c-format
|
||||
msgid "Some other program is already using the key %s with modifiers %x as a binding\n"
|
||||
msgstr "既にバインディングとして別のプログラムでキー %s (修飾キー %x) を使っています\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1335
|
||||
#: ../src/core/keybindings.c:1135
|
||||
#, fuzzy, c-format
|
||||
msgid "\"%s\" is not a valid accelerator\n"
|
||||
msgstr "\"%s\" はフォーカス属性のためには有効な値ではありません"
|
||||
@@ -328,26 +328,26 @@ msgstr "バージョンを表示する"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "使用する Mutter のプラグイン"
|
||||
|
||||
#: ../src/core/prefs.c:1202
|
||||
#: ../src/core/prefs.c:1095
|
||||
msgid "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
|
||||
msgstr "仕様に準拠していないアプリケーションに対する次善策は無効になっています。一部のアプリケーションは正常に動作しない可能性があります\n"
|
||||
|
||||
#: ../src/core/prefs.c:1277
|
||||
#: ../src/core/prefs.c:1170
|
||||
#, c-format
|
||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||
msgstr "GSettings の %2$s キーからフォント名 \"%1$s\" を解析できませんでした\n"
|
||||
|
||||
#: ../src/core/prefs.c:1343
|
||||
#: ../src/core/prefs.c:1236
|
||||
#, c-format
|
||||
msgid "\"%s\" found in configuration database is not a valid value for mouse button modifier\n"
|
||||
msgstr "設定データベース中の \"%s\" はマウスボタンの修飾キーとして妥当な値ではありません\n"
|
||||
|
||||
#: ../src/core/prefs.c:1909
|
||||
#: ../src/core/prefs.c:1788
|
||||
#, c-format
|
||||
msgid "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
|
||||
msgstr "設定データベース中の \"%s\" はキーバインド \"%s\" に有効な値ではありません\n"
|
||||
|
||||
#: ../src/core/prefs.c:1999
|
||||
#: ../src/core/prefs.c:1887
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "ワークスペース %d"
|
||||
@@ -465,7 +465,7 @@ msgid "Window manager error: "
|
||||
msgstr "ウィンドウマネージャーのエラー: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7513
|
||||
#: ../src/core/window.c:7596
|
||||
#, c-format
|
||||
msgid "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"
|
||||
msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT_LEADER ウィンドウの代わりに自分自身で SM_CLIENT_ID を設定しています\n"
|
||||
@@ -477,7 +477,7 @@ msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT
|
||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||
#. * about these apps but make them work.
|
||||
#.
|
||||
#: ../src/core/window.c:8237
|
||||
#: ../src/core/window.c:8320
|
||||
#, c-format
|
||||
msgid "Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"
|
||||
msgstr "ウィンドウ %s はリサイズ可能ではない MWM ヒント指示を設定していますが、最小サイズ %d x %d と最大サイズ %d x %dも設定しています。これはあまり意味がありません\n"
|
||||
|
30
po/nb.po
30
po/nb.po
@@ -4,10 +4,10 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter 3.9.x\n"
|
||||
"Project-Id-Version: mutter 3.8.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-08-08 22:14+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 09:48+0200\n"
|
||||
"POT-Creation-Date: 2013-05-13 10:30+0200\n"
|
||||
"PO-Revision-Date: 2013-04-03 14:11+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
|
||||
"Language: \n"
|
||||
@@ -205,7 +205,7 @@ msgstr "Visning delt til høyre"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:589
|
||||
#: ../src/compositor/compositor.c:568
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
@@ -250,17 +250,17 @@ msgstr "_Vent"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Tvungen nedstenging"
|
||||
|
||||
#: ../src/core/display.c:421
|
||||
#: ../src/core/display.c:401
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "Mangler utvidelsen %s som kreves for komposittfunksjon"
|
||||
|
||||
#: ../src/core/display.c:513
|
||||
#: ../src/core/display.c:493
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1138
|
||||
#: ../src/core/keybindings.c:970
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Some other program is already using the key %s with modifiers %x as a "
|
||||
@@ -269,7 +269,7 @@ msgstr ""
|
||||
"Et annet program bruker allerede nøkkelen %s med modifikatorer %x som "
|
||||
"binding\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1335
|
||||
#: ../src/core/keybindings.c:1151
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid accelerator\n"
|
||||
msgstr "«%s» er ikke en gyldig aksellerator\n"
|
||||
@@ -333,7 +333,7 @@ msgstr "Skriv versjonsnummer"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Mutter-tillegg som skal brukes"
|
||||
|
||||
#: ../src/core/prefs.c:1202
|
||||
#: ../src/core/prefs.c:1095
|
||||
msgid ""
|
||||
"Workarounds for broken applications disabled. Some applications may not "
|
||||
"behave properly.\n"
|
||||
@@ -341,12 +341,12 @@ msgstr ""
|
||||
"Funksjonalitet for å gå rundt ødelagte programmer er deaktivert. Noen "
|
||||
"programmer vil kanskje ikke oppføre seg korrekt.\n"
|
||||
|
||||
#: ../src/core/prefs.c:1277
|
||||
#: ../src/core/prefs.c:1170
|
||||
#, c-format
|
||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||
msgstr "Kunne ikke tolke skriftbeskrivelsen «%s» fra GSettings-nøkkel %s\n"
|
||||
|
||||
#: ../src/core/prefs.c:1343
|
||||
#: ../src/core/prefs.c:1236
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for mouse button "
|
||||
@@ -355,7 +355,7 @@ msgstr ""
|
||||
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for endring av "
|
||||
"musknapp\n"
|
||||
|
||||
#: ../src/core/prefs.c:1909
|
||||
#: ../src/core/prefs.c:1789
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for keybinding "
|
||||
@@ -364,7 +364,7 @@ msgstr ""
|
||||
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for "
|
||||
"tastaturbinding «%s»\n"
|
||||
|
||||
#: ../src/core/prefs.c:1999
|
||||
#: ../src/core/prefs.c:1888
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Arbeidsområde %d"
|
||||
@@ -492,7 +492,7 @@ msgid "Window manager error: "
|
||||
msgstr "Feil i vindushåndterer: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7513
|
||||
#: ../src/core/window.c:7598
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
||||
@@ -508,7 +508,7 @@ msgstr ""
|
||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||
#. * about these apps but make them work.
|
||||
#.
|
||||
#: ../src/core/window.c:8237
|
||||
#: ../src/core/window.c:8322
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
SUBDIRS=wm-tester tools 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,7 +30,6 @@ INCLUDES= \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
|
||||
@@ -95,8 +94,6 @@ 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 \
|
||||
@@ -113,11 +110,6 @@ 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 \
|
||||
@@ -147,6 +139,7 @@ libmutter_la_SOURCES = \
|
||||
meta/common.h \
|
||||
core/core.h \
|
||||
ui/ui.h \
|
||||
inlinepixbufs.h \
|
||||
ui/frames.c \
|
||||
ui/frames.h \
|
||||
ui/menu.c \
|
||||
@@ -164,6 +157,8 @@ 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
|
||||
@@ -201,6 +196,7 @@ 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
|
||||
@@ -209,7 +205,10 @@ libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
mutter_theme_viewer_SOURCES= \
|
||||
ui/theme-viewer.c
|
||||
|
||||
bin_PROGRAMS=mutter mutter-theme-viewer
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
@@ -247,6 +246,8 @@ 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
|
||||
@@ -283,7 +284,14 @@ 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 \
|
||||
@@ -292,6 +300,9 @@ 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
|
||||
@@ -309,7 +320,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)
|
||||
|
||||
@@ -331,12 +342,3 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
|
||||
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
|
||||
cp xgen-tetc mutter-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
|
||||
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
|
||||
|
||||
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--interface-prefix org.gnome.Mutter \
|
||||
--c-namespace MetaDBus \
|
||||
--generate-c-code meta-dbus-xrandr \
|
||||
xrandr.xml
|
||||
|
@@ -53,15 +53,17 @@
|
||||
*
|
||||
* # Containers #
|
||||
*
|
||||
* There's two containers in the stage that are used to place window actors, here
|
||||
* There's three containers in the stage that can be used to place actors, here
|
||||
* are listed in the order in which they are painted:
|
||||
*
|
||||
* - window group, accessible with meta_get_window_group_for_screen()
|
||||
* - top window group, accessible with meta_get_top_window_group_for_screen()
|
||||
* - overlay group, accessible with meta_get_overlay_group_for_screen()
|
||||
*
|
||||
* Mutter will place actors representing windows in the window group, except for
|
||||
* override-redirect windows (ie. popups and menus) which will be placed in the
|
||||
* top window group.
|
||||
* top window group. Mutter won't put any actors in the overlay group, but it's
|
||||
* intended for compositors to place there panel, dashes, status bars, etc.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@@ -253,6 +255,23 @@ meta_get_stage_for_screen (MetaScreen *screen)
|
||||
return info->stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_overlay_group_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none): The overlay group corresponding to @screen
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_get_overlay_group_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return info->overlay_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_window_group_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
@@ -369,46 +388,6 @@ meta_empty_stage_input_region (MetaScreen *screen)
|
||||
meta_set_stage_input_region (screen, region);
|
||||
}
|
||||
|
||||
void
|
||||
meta_focus_stage_window (MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
Window window;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return;
|
||||
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
window,
|
||||
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,
|
||||
@@ -674,9 +653,11 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
|
||||
info->window_group = meta_window_group_new (screen);
|
||||
info->top_window_group = meta_window_group_new (screen);
|
||||
info->overlay_group = clutter_actor_new ();
|
||||
|
||||
clutter_actor_add_child (info->stage, info->window_group);
|
||||
clutter_actor_add_child (info->stage, info->top_window_group);
|
||||
clutter_actor_add_child (info->stage, info->overlay_group);
|
||||
|
||||
info->plugin_mgr = meta_plugin_manager_new (screen);
|
||||
|
||||
@@ -707,6 +688,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
info->pending_input_region = None;
|
||||
}
|
||||
|
||||
clutter_actor_show (info->overlay_group);
|
||||
|
||||
/* Map overlay window before redirecting windows offscreen so we catch their
|
||||
* contents until we show the stage.
|
||||
*/
|
||||
|
@@ -73,12 +73,13 @@ void
|
||||
meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *actor;
|
||||
GList *children, *l;
|
||||
|
||||
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self));
|
||||
while (clutter_actor_iter_next (&iter, &actor))
|
||||
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
ClutterActor *actor = l->data;
|
||||
|
||||
if (META_IS_BACKGROUND_ACTOR (actor))
|
||||
{
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
|
||||
@@ -95,6 +96,7 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||
cairo_region_translate (region, x, y);
|
||||
}
|
||||
}
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
|
@@ -891,7 +891,7 @@ meta_background_load_gradient (MetaBackground *self,
|
||||
pixels[7] = second_color->alpha;
|
||||
|
||||
texture = cogl_texture_new_from_data (width, height,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
4,
|
||||
@@ -1060,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
|
||||
|
||||
texture = cogl_texture_new_from_data (width,
|
||||
height,
|
||||
COGL_TEXTURE_NO_ATLAS,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
has_alpha ?
|
||||
COGL_PIXEL_FORMAT_RGBA_8888 :
|
||||
COGL_PIXEL_FORMAT_RGB_888,
|
||||
|
@@ -85,20 +85,12 @@ meta_plugin_manager_load (const gchar *plugin_name)
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
on_confirm_display_change (MetaMonitorManager *monitors,
|
||||
MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
meta_plugin_manager_confirm_display_change (plugin_mgr);
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
MetaPluginClass *klass;
|
||||
MetaPlugin *plugin;
|
||||
MetaMonitorManager *monitors;
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr->screen = screen;
|
||||
@@ -109,10 +101,6 @@ meta_plugin_manager_new (MetaScreen *screen)
|
||||
if (klass->start)
|
||||
klass->start (plugin);
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect (monitors, "confirm-display-change",
|
||||
G_CALLBACK (on_confirm_display_change), plugin_mgr);
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
@@ -332,15 +320,3 @@ 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,6 +73,4 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
|
||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
|
||||
|
||||
#endif
|
||||
|
@@ -41,7 +41,6 @@
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
@@ -339,13 +338,3 @@ meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok)
|
||||
{
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_confirm_configuration (manager, ok);
|
||||
}
|
||||
|
@@ -123,12 +123,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
||||
/* The first element in this array also defines the default parameters
|
||||
* for newly created classes */
|
||||
MetaShadowClassInfo default_shadow_classes[] = {
|
||||
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
|
||||
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
|
||||
{ "normal", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
|
||||
{ "dialog", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
|
||||
{ "modal_dialog", { 6, -1, 0, 1, 255 }, { 3, -1, 0, 3, 128 } },
|
||||
{ "utility", { 3, -1, 0, 1, 255 }, { 3, -1, 0, 1, 128 } },
|
||||
{ "border", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
|
||||
{ "menu", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 0, 128 } },
|
||||
|
||||
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
|
||||
|
@@ -69,6 +69,9 @@ 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;
|
||||
@@ -127,6 +130,8 @@ 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 */
|
||||
@@ -318,6 +323,9 @@ window_decorated_notify (MetaWindow *mw,
|
||||
priv->damage = None;
|
||||
}
|
||||
|
||||
g_free (priv->desc);
|
||||
priv->desc = NULL;
|
||||
|
||||
priv->xwindow = new_xwindow;
|
||||
|
||||
/*
|
||||
@@ -369,10 +377,10 @@ meta_window_actor_constructed (GObject *object)
|
||||
*/
|
||||
g_object_ref (priv->actor);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -449,6 +457,7 @@ 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);
|
||||
}
|
||||
@@ -843,6 +852,25 @@ 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
|
||||
@@ -1312,6 +1340,14 @@ 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));
|
||||
}
|
||||
@@ -1712,8 +1748,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_set_visible_region() and
|
||||
* meta_window_actor_set_visible_region_beneath()
|
||||
* Unsets the regions set by meta_window_actor_reset_visible_region() and
|
||||
* meta_window_actor_reset_visible_region_beneath()
|
||||
*/
|
||||
void
|
||||
meta_window_actor_reset_visible_regions (MetaWindowActor *self)
|
||||
@@ -1957,6 +1993,73 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
|
||||
}
|
||||
}
|
||||
|
||||
#define TAU (2*M_PI)
|
||||
|
||||
static void
|
||||
install_corners (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
cairo_t *cr)
|
||||
{
|
||||
float top_left, top_right, bottom_left, bottom_right;
|
||||
int x, y;
|
||||
MetaRectangle outer;
|
||||
|
||||
meta_frame_get_corner_radiuses (window->frame,
|
||||
&top_left,
|
||||
&top_right,
|
||||
&bottom_left,
|
||||
&bottom_right);
|
||||
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
|
||||
/* top left */
|
||||
x = borders->invisible.left;
|
||||
y = borders->invisible.top;
|
||||
|
||||
cairo_arc (cr,
|
||||
x + top_left,
|
||||
y + top_left,
|
||||
top_left,
|
||||
2 * TAU / 4,
|
||||
3 * TAU / 4);
|
||||
|
||||
/* top right */
|
||||
x = borders->invisible.left + outer.width - top_right;
|
||||
y = borders->invisible.top;
|
||||
|
||||
cairo_arc (cr,
|
||||
x,
|
||||
y + top_right,
|
||||
top_right,
|
||||
3 * TAU / 4,
|
||||
4 * TAU / 4);
|
||||
|
||||
/* bottom right */
|
||||
x = borders->invisible.left + outer.width - bottom_right;
|
||||
y = borders->invisible.top + outer.height - bottom_right;
|
||||
|
||||
cairo_arc (cr,
|
||||
x,
|
||||
y,
|
||||
bottom_right,
|
||||
0 * TAU / 4,
|
||||
1 * TAU / 4);
|
||||
|
||||
/* bottom left */
|
||||
x = borders->invisible.left;
|
||||
y = borders->invisible.top + outer.height - bottom_left;
|
||||
|
||||
cairo_arc (cr,
|
||||
x + bottom_left,
|
||||
y,
|
||||
bottom_left,
|
||||
1 * TAU / 4,
|
||||
2 * TAU / 4);
|
||||
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
scan_visible_region (guchar *mask_data,
|
||||
int stride,
|
||||
@@ -1996,6 +2099,7 @@ scan_visible_region (guchar *mask_data,
|
||||
|
||||
static void
|
||||
build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
MetaFrameBorders *borders,
|
||||
cairo_rectangle_int_t *client_area,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
@@ -2041,7 +2145,7 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
gdk_cairo_region (cr, frame_paint_region);
|
||||
cairo_clip (cr);
|
||||
|
||||
meta_frame_get_mask (priv->window->frame, cr);
|
||||
install_corners (priv->window, borders, cr);
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
scanned_region = scan_visible_region (mask_data, stride, frame_paint_region);
|
||||
@@ -2207,7 +2311,7 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
* and scans the mask looking for all opaque pixels,
|
||||
* adding it to region.
|
||||
*/
|
||||
build_and_scan_frame_mask (self, &client_area, region);
|
||||
build_and_scan_frame_mask (self, &borders, &client_area, region);
|
||||
}
|
||||
|
||||
priv->shape_region = region;
|
||||
|
@@ -91,9 +91,8 @@ 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;
|
||||
@@ -124,6 +123,13 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
paint_x_offset = paint_x_origin - actor_x_origin;
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
children = clutter_actor_get_children (actor);
|
||||
children = g_list_reverse (children);
|
||||
|
||||
/* Get the clipped redraw bounds from Clutter so that we can avoid
|
||||
* painting shadows on windows that don't need to be painted in this
|
||||
* frame. In the case of a multihead setup with mismatched monitor
|
||||
@@ -145,18 +151,12 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
|
||||
}
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_prev (&iter, &child))
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
continue;
|
||||
|
||||
if (info->unredirected_window != NULL &&
|
||||
child == CLUTTER_ACTOR (info->unredirected_window))
|
||||
if (l->data == info->unredirected_window)
|
||||
continue;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
@@ -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 (child))
|
||||
if (clutter_actor_has_effects (l->data))
|
||||
continue;
|
||||
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
@@ -204,12 +204,13 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (child) ||
|
||||
META_IS_BACKGROUND_GROUP (child))
|
||||
else if (META_IS_BACKGROUND_ACTOR (l->data) ||
|
||||
META_IS_BACKGROUND_GROUP (l->data))
|
||||
{
|
||||
ClutterActor *background_actor = l->data;
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (child, &x, &y))
|
||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
|
||||
continue;
|
||||
|
||||
x += paint_x_offset;
|
||||
@@ -217,10 +218,10 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
|
||||
cairo_region_translate (visible_region, - x, - y);
|
||||
|
||||
if (META_IS_BACKGROUND_GROUP (child))
|
||||
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
|
||||
if (META_IS_BACKGROUND_GROUP (background_actor))
|
||||
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
|
||||
else
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
|
||||
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
|
||||
cairo_region_translate (visible_region, x, y);
|
||||
}
|
||||
}
|
||||
@@ -232,20 +233,21 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
if (META_IS_WINDOW_ACTOR (l->data))
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
MetaWindowActor *window_actor = l->data;
|
||||
meta_window_actor_reset_visible_regions (window_actor);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (child))
|
||||
else if (META_IS_BACKGROUND_ACTOR (l->data))
|
||||
{
|
||||
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
|
||||
MetaBackgroundActor *background_actor = l->data;
|
||||
meta_background_actor_set_visible_region (background_actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@@ -24,8 +24,6 @@
|
||||
#include <meta/meta-plugin.h>
|
||||
#include <meta/window.h>
|
||||
#include <meta/util.h>
|
||||
#include <meta/meta-background-group.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
@@ -100,8 +98,6 @@ static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static void confirm_display_change (MetaPlugin *plugin);
|
||||
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
|
||||
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
|
||||
@@ -117,8 +113,6 @@ struct _MetaDefaultPluginPrivate
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
ClutterActor *background_group;
|
||||
|
||||
MetaPluginInfo info;
|
||||
};
|
||||
|
||||
@@ -209,7 +203,6 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
plugin_class->confirm_display_change = confirm_display_change;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
|
||||
}
|
||||
@@ -306,58 +299,9 @@ show_stage (MetaPlugin *plugin)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaScreen *screen,
|
||||
MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
int i, n;
|
||||
|
||||
clutter_actor_destroy_all_children (self->priv->background_group);
|
||||
|
||||
n = meta_screen_get_n_monitors (screen);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
MetaRectangle rect;
|
||||
ClutterActor *background;
|
||||
ClutterColor color;
|
||||
|
||||
meta_screen_get_monitor_geometry (screen, i, &rect);
|
||||
|
||||
background = meta_background_actor_new ();
|
||||
|
||||
clutter_actor_set_position (background, rect.x, rect.y);
|
||||
clutter_actor_set_size (background, rect.width, rect.height);
|
||||
|
||||
/* Don't use rand() here, mesa calls srand() internally when
|
||||
parsing the driconf XML, but it's nice if the colors are
|
||||
reproducible.
|
||||
*/
|
||||
clutter_color_init (&color,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
255);
|
||||
clutter_actor_set_background_color (background, &color);
|
||||
|
||||
clutter_actor_add_child (self->priv->background_group, background);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
start (MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
|
||||
self->priv->background_group = meta_background_group_new ();
|
||||
clutter_actor_insert_child_below (meta_get_window_group_for_screen (screen),
|
||||
self->priv->background_group, NULL);
|
||||
|
||||
g_signal_connect (screen, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), plugin);
|
||||
on_monitors_changed (screen, plugin);
|
||||
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
(GSourceFunc) show_stage,
|
||||
plugin,
|
||||
@@ -838,33 +782,3 @@ plugin_info (MetaPlugin *plugin)
|
||||
|
||||
return &priv->info;
|
||||
}
|
||||
|
||||
static void
|
||||
on_dialog_closed (GPid pid,
|
||||
gint status,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaPlugin *plugin = user_data;
|
||||
gboolean ok;
|
||||
|
||||
ok = g_spawn_check_exit_status (status, NULL);
|
||||
meta_plugin_complete_display_change (plugin, ok);
|
||||
}
|
||||
|
||||
static void
|
||||
confirm_display_change (MetaPlugin *plugin)
|
||||
{
|
||||
GPid pid;
|
||||
|
||||
pid = meta_show_dialog ("--question",
|
||||
"Does the display look OK?",
|
||||
"20",
|
||||
NULL,
|
||||
"_Keep This Configuration",
|
||||
"_Restore Previous Configuration",
|
||||
"preferences-desktop-display",
|
||||
0,
|
||||
NULL, NULL);
|
||||
|
||||
g_child_watch_add (pid, on_dialog_closed, plugin);
|
||||
}
|
||||
|
@@ -103,20 +103,19 @@ struct _MetaDisplay
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
|
||||
/* The window and serial of the most recent FocusIn event. */
|
||||
Window server_focus_window;
|
||||
gulong server_focus_serial;
|
||||
|
||||
/* Our best guess as to the "currently" focused window (that is, the
|
||||
* window that we expect will be focused at the point when the X
|
||||
* server processes our next request), and the serial of the request
|
||||
* or event that caused this.
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
*/
|
||||
MetaWindow *focus_window;
|
||||
/* For windows we've focused that don't necessarily have an X window,
|
||||
* like the no_focus_window or the stage X window. */
|
||||
Window focus_xwindow;
|
||||
gulong focus_serial;
|
||||
|
||||
/* window we are expecting a FocusIn event for or the current focus
|
||||
* window if we are not expecting any FocusIn/FocusOut events; not
|
||||
* perfect because applications can call XSetInputFocus directly.
|
||||
* (It could also be messed up if a timestamp later than current
|
||||
* time is sent to meta_display_set_input_focus_window, though that
|
||||
* would be a programming error). See bug 154598 for more info.
|
||||
*/
|
||||
MetaWindow *expected_focus_window;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
guint32 last_focus_time;
|
||||
@@ -460,8 +459,7 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
||||
void meta_display_overlay_key_activate (MetaDisplay *display);
|
||||
void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
guint deviceid,
|
||||
guint timestamp);
|
||||
guint deviceid);
|
||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
/* In above-tab-keycode.c */
|
||||
@@ -472,9 +470,4 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIBarrierEvent *event);
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
|
||||
#endif
|
||||
|
@@ -254,7 +254,7 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
||||
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
|
||||
|
||||
/**
|
||||
* MetaDisplay::modifiers-accelerator-activated:
|
||||
@@ -539,9 +539,7 @@ meta_display_open (void)
|
||||
the_display->autoraise_timeout_id = 0;
|
||||
the_display->autoraise_window = NULL;
|
||||
the_display->focus_window = NULL;
|
||||
the_display->focus_serial = 0;
|
||||
the_display->server_focus_window = None;
|
||||
the_display->server_focus_serial = 0;
|
||||
the_display->expected_focus_window = NULL;
|
||||
the_display->grab_old_window_stacking = NULL;
|
||||
|
||||
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
||||
@@ -1467,17 +1465,6 @@ meta_display_get_current_time (MetaDisplay *display)
|
||||
return display->current_time;
|
||||
}
|
||||
|
||||
static Bool
|
||||
find_timestamp_predicate (Display *xdisplay,
|
||||
XEvent *ev,
|
||||
XPointer arg)
|
||||
{
|
||||
MetaDisplay *display = (MetaDisplay *) arg;
|
||||
|
||||
return (ev->type == PropertyNotify &&
|
||||
ev->xproperty.atom == display->atom__MUTTER_TIMESTAMP_PING);
|
||||
}
|
||||
|
||||
/* Get a timestamp, even if it means a roundtrip */
|
||||
guint32
|
||||
meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
||||
@@ -1489,13 +1476,17 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
||||
{
|
||||
XEvent property_event;
|
||||
|
||||
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
|
||||
display->atom__MUTTER_TIMESTAMP_PING,
|
||||
XA_STRING, 8, PropModeAppend, NULL, 0);
|
||||
XIfEvent (display->xdisplay,
|
||||
&property_event,
|
||||
find_timestamp_predicate,
|
||||
(XPointer) display);
|
||||
/* Using the property XA_PRIMARY because it's safe; nothing
|
||||
* would use it as a property. The type doesn't matter.
|
||||
*/
|
||||
XChangeProperty (display->xdisplay,
|
||||
display->timestamp_pinging_window,
|
||||
XA_PRIMARY, XA_STRING, 8,
|
||||
PropModeAppend, NULL, 0);
|
||||
XWindowEvent (display->xdisplay,
|
||||
display->timestamp_pinging_window,
|
||||
PropertyChangeMask,
|
||||
&property_event);
|
||||
timestamp = property_event.xproperty.time;
|
||||
}
|
||||
|
||||
@@ -1661,12 +1652,12 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
|
||||
* alternative mechanism works great.
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
|
||||
display->focus_window != NULL)
|
||||
display->expected_focus_window != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Unsetting focus from %s due to mouse entering "
|
||||
"the DESKTOP window\n",
|
||||
display->focus_window->desc);
|
||||
display->expected_focus_window->desc);
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
window->screen,
|
||||
timestamp);
|
||||
@@ -1880,246 +1871,6 @@ get_input_event (MetaDisplay *display,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial)
|
||||
{
|
||||
display->focus_serial = serial;
|
||||
|
||||
if (display->focus_xwindow == xwindow)
|
||||
return;
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
MetaWindow *previous;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"%s is now the previous focus window due to being focused out or unmapped\n",
|
||||
display->focus_window->desc);
|
||||
|
||||
/* Make sure that signals handlers invoked by
|
||||
* meta_window_set_focused_internal() don't see
|
||||
* display->focus_window->has_focus == FALSE
|
||||
*/
|
||||
previous = display->focus_window;
|
||||
display->focus_window = NULL;
|
||||
display->focus_xwindow = None;
|
||||
|
||||
meta_window_set_focused_internal (previous, FALSE);
|
||||
}
|
||||
|
||||
display->focus_window = window;
|
||||
display->focus_xwindow = xwindow;
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
|
||||
display->focus_window->desc, serial);
|
||||
meta_window_set_focused_internal (display->focus_window, TRUE);
|
||||
}
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
||||
|
||||
g_object_notify (G_OBJECT (display), "focus-window");
|
||||
meta_display_update_active_window_hint (display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timestamp_too_old (MetaDisplay *display,
|
||||
guint32 *timestamp)
|
||||
{
|
||||
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
|
||||
* us to sanity check the timestamp here and ensure it doesn't correspond to
|
||||
* a future time (though we would want to rename to
|
||||
* timestamp_too_old_or_in_future).
|
||||
*/
|
||||
|
||||
if (*timestamp == CurrentTime)
|
||||
{
|
||||
*timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
return FALSE;
|
||||
}
|
||||
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
|
||||
{
|
||||
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
*timestamp = display->last_focus_time;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
request_xserver_input_focus_change (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *meta_window;
|
||||
gulong serial;
|
||||
|
||||
if (timestamp_too_old (display, ×tamp))
|
||||
return;
|
||||
|
||||
meta_window = meta_display_lookup_x_window (display, xwindow);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
/* In order for mutter to know that the focus request succeeded, we track
|
||||
* the serial of the "focus request" we made, but if we take the serial
|
||||
* of the XSetInputFocus request, then there's no way to determine the
|
||||
* difference between focus events as a result of the SetInputFocus and
|
||||
* focus events that other clients send around the same time. Ensure that
|
||||
* we know which is which by making two requests that the server will
|
||||
* process at the same time.
|
||||
*/
|
||||
meta_display_grab (display);
|
||||
|
||||
serial = XNextRequest (display->xdisplay);
|
||||
|
||||
XSetInputFocus (display->xdisplay,
|
||||
xwindow,
|
||||
RevertToPointerRoot,
|
||||
timestamp);
|
||||
|
||||
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
|
||||
display->atom__MUTTER_FOCUS_SET,
|
||||
XA_STRING, 8, PropModeAppend, NULL, 0);
|
||||
|
||||
meta_display_ungrab (display);
|
||||
|
||||
update_focus_window (display,
|
||||
meta_window,
|
||||
xwindow,
|
||||
serial);
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
display->last_focus_time = timestamp;
|
||||
display->active_screen = screen;
|
||||
|
||||
if (meta_window == NULL || meta_window != display->autoraise_window)
|
||||
meta_display_remove_autoraise_callback (display);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_window_focus_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XIEnterEvent *event,
|
||||
unsigned long serial)
|
||||
{
|
||||
MetaWindow *focus_window;
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
const char *window_type;
|
||||
|
||||
/* Note the event can be on either the window or the frame,
|
||||
* we focus the frame for shaded windows
|
||||
*/
|
||||
if (window)
|
||||
{
|
||||
if (event->event == window->xwindow)
|
||||
window_type = "client window";
|
||||
else if (window->frame && event->event == window->frame->xwindow)
|
||||
window_type = "frame window";
|
||||
else
|
||||
window_type = "unknown client window";
|
||||
}
|
||||
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
|
||||
window_type = "no_focus_window";
|
||||
else if (meta_display_screen_for_root (display, event->event))
|
||||
window_type = "root window";
|
||||
else
|
||||
window_type = "unknown window";
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on %s 0x%lx (%s) "
|
||||
"mode %s detail %s serial %lu\n",
|
||||
event->evtype == XI_FocusIn ? "in" :
|
||||
event->evtype == XI_FocusOut ? "out" :
|
||||
"???",
|
||||
window ? window->desc : "",
|
||||
event->event, window_type,
|
||||
meta_event_mode_to_string (event->mode),
|
||||
meta_event_detail_to_string (event->mode),
|
||||
event->serial);
|
||||
#endif
|
||||
|
||||
/* FIXME our pointer tracking is broken; see how
|
||||
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
|
||||
* for how to handle it the correct way. In brief you need to track
|
||||
* pointer focus and regular focus, and handle EnterNotify in
|
||||
* PointerRoot mode with no window manager. However as noted above,
|
||||
* accurate focus tracking will break things because we want to keep
|
||||
* windows "focused" when using keybindings on them, and also we
|
||||
* sometimes "focus" a window by focusing its frame or
|
||||
* no_focus_window; so this all needs rethinking massively.
|
||||
*
|
||||
* My suggestion is to change it so that we clearly separate
|
||||
* actual keyboard focus tracking using the xterm algorithm,
|
||||
* and mutter's "pretend" focus window, and go through all
|
||||
* the code and decide which one should be used in each place;
|
||||
* a hard bit is deciding on a policy for that.
|
||||
*
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
|
||||
*/
|
||||
|
||||
/* We ignore grabs, though this is questionable. It may be better to
|
||||
* increase the intelligence of the focus window tracking.
|
||||
*
|
||||
* The problem is that keybindings for windows are done with
|
||||
* XGrabKey, which means focus_window disappears and the front of
|
||||
* the MRU list gets confused from what the user expects once a
|
||||
* keybinding is used.
|
||||
*/
|
||||
|
||||
if (event->mode == XINotifyGrab ||
|
||||
event->mode == XINotifyUngrab ||
|
||||
/* From WindowMaker, ignore all funky pointer root events */
|
||||
event->detail > XINotifyNonlinearVirtual)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus event generated by a grab or other weirdness\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->evtype == XI_FocusIn)
|
||||
{
|
||||
display->server_focus_window = event->event;
|
||||
display->server_focus_serial = serial;
|
||||
focus_window = window;
|
||||
}
|
||||
else if (event->evtype == XI_FocusOut)
|
||||
{
|
||||
if (event->detail == XINotifyInferior)
|
||||
{
|
||||
/* This event means the client moved focus to a subwindow */
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus out with NotifyInferior\n");
|
||||
return;
|
||||
}
|
||||
|
||||
display->server_focus_window = None;
|
||||
display->server_focus_serial = serial;
|
||||
focus_window = NULL;
|
||||
}
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
if (display->server_focus_serial > display->focus_serial)
|
||||
{
|
||||
update_focus_window (display,
|
||||
focus_window,
|
||||
focus_window ? focus_window->xwindow : None,
|
||||
display->server_focus_serial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* event_callback:
|
||||
* @event: The event that just happened
|
||||
@@ -2146,7 +1897,6 @@ event_callback (XEvent *event,
|
||||
gboolean bypass_compositor;
|
||||
gboolean filter_out_event;
|
||||
XIEvent *input_event;
|
||||
MetaMonitorManager *monitor;
|
||||
|
||||
display = data;
|
||||
|
||||
@@ -2158,32 +1908,12 @@ 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;
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
if (event->xany.serial > display->focus_serial &&
|
||||
display->focus_window &&
|
||||
display->focus_window->xwindow != display->server_focus_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
|
||||
display->focus_window->desc);
|
||||
update_focus_window (display,
|
||||
meta_display_lookup_x_window (display, display->server_focus_window),
|
||||
display->server_focus_window,
|
||||
display->server_focus_serial);
|
||||
}
|
||||
|
||||
|
||||
modified = event_get_modified_window (display, event);
|
||||
|
||||
input_event = get_input_event (display, event);
|
||||
@@ -2503,12 +2233,30 @@ 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 time %u\n",
|
||||
meta_verbose ("Allowing events mode %s time %u\n",
|
||||
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
|
||||
(unsigned int)device_event->time);
|
||||
|
||||
XIAllowEvents (display->xdisplay, device_event->deviceid,
|
||||
XIReplayDevice, device_event->time);
|
||||
mode, device_event->time);
|
||||
}
|
||||
|
||||
if (begin_move && window->has_move_func)
|
||||
@@ -2622,19 +2370,40 @@ event_callback (XEvent *event,
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
/* libXi does not properly copy the serial to the XIEnterEvent, so pull it
|
||||
* from the parent XAnyEvent.
|
||||
* See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
|
||||
*/
|
||||
handle_window_focus_event (display, window, enter_event, event->xany.serial);
|
||||
if (!window)
|
||||
if (window)
|
||||
{
|
||||
meta_window_notify_focus (window, enter_event);
|
||||
}
|
||||
else if (meta_display_xwindow_is_a_no_focus_window (display,
|
||||
enter_event->event))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on no_focus_window 0x%lx "
|
||||
"mode %s detail %s\n",
|
||||
enter_event->evtype == XI_FocusIn ? "in" :
|
||||
enter_event->evtype == XI_FocusOut ? "out" :
|
||||
"???",
|
||||
enter_event->event,
|
||||
meta_event_mode_to_string (enter_event->mode),
|
||||
meta_event_detail_to_string (enter_event->detail));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the window is a root window. */
|
||||
MetaScreen *screen =
|
||||
meta_display_screen_for_root(display,
|
||||
enter_event->event);
|
||||
if (screen == NULL)
|
||||
break;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on root window 0x%lx "
|
||||
"mode %s detail %s\n",
|
||||
enter_event->evtype == XI_FocusIn ? "in" :
|
||||
enter_event->evtype == XI_FocusOut ? "out" :
|
||||
"???",
|
||||
enter_event->event,
|
||||
meta_event_mode_to_string (enter_event->mode),
|
||||
meta_event_detail_to_string (enter_event->detail));
|
||||
|
||||
if (enter_event->evtype == XI_FocusIn &&
|
||||
enter_event->mode == XINotifyDetailNone)
|
||||
@@ -2772,6 +2541,13 @@ event_callback (XEvent *event,
|
||||
window->unmaps_pending);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unfocus on UnmapNotify, do this after the possible
|
||||
* window_free above so that window_free can see if window->has_focus
|
||||
* and move focus to another window
|
||||
*/
|
||||
if (window)
|
||||
meta_window_lost_focus (window);
|
||||
}
|
||||
break;
|
||||
case MapNotify:
|
||||
@@ -2831,10 +2607,32 @@ 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 */
|
||||
@@ -3029,6 +2827,27 @@ 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)
|
||||
{
|
||||
@@ -5768,74 +5587,98 @@ sanity_check_timestamps (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timestamp_too_old (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
guint32 *timestamp)
|
||||
{
|
||||
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
|
||||
* us to sanity check the timestamp here and ensure it doesn't correspond to
|
||||
* a future time (though we would want to rename to
|
||||
* timestamp_too_old_or_in_future).
|
||||
*/
|
||||
|
||||
if (*timestamp == CurrentTime)
|
||||
{
|
||||
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
|
||||
"shouldn't happen!\n",
|
||||
window ? window->desc : "the no_focus_window");
|
||||
*timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
return FALSE;
|
||||
}
|
||||
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
|
||||
{
|
||||
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus request for %s since %u "
|
||||
"is less than %u and %u.\n",
|
||||
window ? window->desc : "the no_focus_window",
|
||||
*timestamp,
|
||||
display->last_user_time,
|
||||
display->last_focus_time);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Received focus request for %s which is newer than most "
|
||||
"recent user_time, but less recent than "
|
||||
"last_focus_time (%u < %u < %u); adjusting "
|
||||
"accordingly. (See bug 167358)\n",
|
||||
window ? window->desc : "the no_focus_window",
|
||||
display->last_user_time,
|
||||
*timestamp,
|
||||
display->last_focus_time);
|
||||
*timestamp = display->last_focus_time;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_set_input_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
window->screen,
|
||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_request_take_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
if (timestamp_too_old (display, ×tamp))
|
||||
if (timestamp_too_old (display, window, ×tamp))
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
|
||||
window->desc, timestamp);
|
||||
meta_error_trap_push (display);
|
||||
XSetInputFocus (display->xdisplay,
|
||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
||||
RevertToPointerRoot,
|
||||
timestamp);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (window != display->focus_window)
|
||||
{
|
||||
/* The "Globally Active Input" window case, where the window
|
||||
* doesn't want us to call XSetInputFocus on it, but does
|
||||
* want us to send a WM_TAKE_FOCUS.
|
||||
*
|
||||
* We can't just set display->focus_window to @window, since we
|
||||
* we don't know when (or even if) the window will actually take
|
||||
* focus, so we could end up being wrong for arbitrarily long.
|
||||
* But we also can't leave it set to the current window, or else
|
||||
* bug #597352 would come back. So we focus the no_focus_window
|
||||
* now (and set display->focus_window to that), send the
|
||||
* WM_TAKE_FOCUS, and then just forget about @window
|
||||
* until/unless we get a FocusIn.
|
||||
*/
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
window->screen,
|
||||
timestamp);
|
||||
}
|
||||
meta_window_send_icccm_message (window,
|
||||
display->atom_WM_TAKE_FOCUS,
|
||||
timestamp);
|
||||
display->expected_focus_window = window;
|
||||
display->last_focus_time = timestamp;
|
||||
display->active_screen = window->screen;
|
||||
|
||||
if (window != display->autoraise_window)
|
||||
meta_display_remove_autoraise_callback (window->display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
screen,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
||||
meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (display,
|
||||
screen,
|
||||
screen->no_focus_window,
|
||||
timestamp);
|
||||
if (timestamp_too_old (display, NULL, ×tamp))
|
||||
return;
|
||||
|
||||
XSetInputFocus (display->xdisplay,
|
||||
screen->no_focus_window,
|
||||
RevertToPointerRoot,
|
||||
timestamp);
|
||||
display->expected_focus_window = NULL;
|
||||
display->last_focus_time = timestamp;
|
||||
display->active_screen = screen;
|
||||
|
||||
meta_display_remove_autoraise_callback (display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5858,11 +5701,10 @@ meta_display_overlay_key_activate (MetaDisplay *display)
|
||||
void
|
||||
meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
guint deviceid,
|
||||
guint timestamp)
|
||||
guint deviceid)
|
||||
{
|
||||
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
|
||||
0, action, deviceid, timestamp);
|
||||
0, action, deviceid);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -5956,9 +5798,11 @@ meta_display_has_shape (MetaDisplay *display)
|
||||
* meta_display_get_focus_window:
|
||||
* @display: a #MetaDisplay
|
||||
*
|
||||
* Get our best guess as to the "currently" focused window (that is,
|
||||
* the window that we expect will be focused at the point when the X
|
||||
* server processes our next request).
|
||||
* Get the window that, according to events received from X server,
|
||||
* currently has the input focus. We may have already sent a request
|
||||
* to the X server to move the focus window elsewhere. (The
|
||||
* expected_focus_window records where we've last set the input
|
||||
* focus.)
|
||||
*
|
||||
* Return Value: (transfer none): The current focus window
|
||||
*/
|
||||
|
@@ -1,540 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Author: Soren Sandmann <sandmann@redhat.com> */
|
||||
|
||||
#include "edid.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <glib.h>
|
||||
|
||||
static int
|
||||
get_bit (int in, int bit)
|
||||
{
|
||||
return (in & (1 << bit)) >> bit;
|
||||
}
|
||||
|
||||
static int
|
||||
get_bits (int in, int begin, int end)
|
||||
{
|
||||
int mask = (1 << (end - begin + 1)) - 1;
|
||||
|
||||
return (in >> begin) & mask;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_header (const uchar *edid)
|
||||
{
|
||||
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int is_model_year;
|
||||
|
||||
/* Manufacturer Code */
|
||||
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
|
||||
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
|
||||
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
|
||||
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
|
||||
info->manufacturer_code[3] = '\0';
|
||||
|
||||
info->manufacturer_code[0] += 'A' - 1;
|
||||
info->manufacturer_code[1] += 'A' - 1;
|
||||
info->manufacturer_code[2] += 'A' - 1;
|
||||
|
||||
/* Product Code */
|
||||
info->product_code = edid[0x0b] << 8 | edid[0x0a];
|
||||
|
||||
/* Serial Number */
|
||||
info->serial_number =
|
||||
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
|
||||
|
||||
/* Week and Year */
|
||||
is_model_year = FALSE;
|
||||
switch (edid[0x10])
|
||||
{
|
||||
case 0x00:
|
||||
info->production_week = -1;
|
||||
break;
|
||||
|
||||
case 0xff:
|
||||
info->production_week = -1;
|
||||
is_model_year = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
info->production_week = edid[0x10];
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_model_year)
|
||||
{
|
||||
info->production_year = -1;
|
||||
info->model_year = 1990 + edid[0x11];
|
||||
}
|
||||
else
|
||||
{
|
||||
info->production_year = 1990 + edid[0x11];
|
||||
info->model_year = -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_edid_version (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->major_version = edid[0x12];
|
||||
info->minor_version = edid[0x13];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_display_parameters (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
/* Digital vs Analog */
|
||||
info->is_digital = get_bit (edid[0x14], 7);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
int bits;
|
||||
|
||||
static const int bit_depth[8] =
|
||||
{
|
||||
-1, 6, 8, 10, 12, 14, 16, -1
|
||||
};
|
||||
|
||||
static const Interface interfaces[6] =
|
||||
{
|
||||
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
|
||||
};
|
||||
|
||||
bits = get_bits (edid[0x14], 4, 6);
|
||||
info->connector.digital.bits_per_primary = bit_depth[bits];
|
||||
|
||||
bits = get_bits (edid[0x14], 0, 3);
|
||||
|
||||
if (bits <= 5)
|
||||
info->connector.digital.interface = interfaces[bits];
|
||||
else
|
||||
info->connector.digital.interface = UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x14], 5, 6);
|
||||
|
||||
static const double levels[][3] =
|
||||
{
|
||||
{ 0.7, 0.3, 1.0 },
|
||||
{ 0.714, 0.286, 1.0 },
|
||||
{ 1.0, 0.4, 1.4 },
|
||||
{ 0.7, 0.0, 0.7 },
|
||||
};
|
||||
|
||||
info->connector.analog.video_signal_level = levels[bits][0];
|
||||
info->connector.analog.sync_signal_level = levels[bits][1];
|
||||
info->connector.analog.total_signal_level = levels[bits][2];
|
||||
|
||||
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
|
||||
|
||||
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
|
||||
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
|
||||
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
|
||||
|
||||
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
|
||||
}
|
||||
|
||||
/* Screen Size / Aspect Ratio */
|
||||
if (edid[0x15] == 0 && edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = -1.0;
|
||||
}
|
||||
else if (edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
|
||||
}
|
||||
else if (edid[0x15] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
|
||||
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
|
||||
}
|
||||
else
|
||||
{
|
||||
info->width_mm = 10 * edid[0x15];
|
||||
info->height_mm = 10 * edid[0x16];
|
||||
}
|
||||
|
||||
/* Gamma */
|
||||
if (edid[0x17] == 0xFF)
|
||||
info->gamma = -1.0;
|
||||
else
|
||||
info->gamma = (edid[0x17] + 100.0) / 100.0;
|
||||
|
||||
/* Features */
|
||||
info->standby = get_bit (edid[0x18], 7);
|
||||
info->suspend = get_bit (edid[0x18], 6);
|
||||
info->active_off = get_bit (edid[0x18], 5);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
info->connector.digital.rgb444 = TRUE;
|
||||
if (get_bit (edid[0x18], 3))
|
||||
info->connector.digital.ycrcb444 = 1;
|
||||
if (get_bit (edid[0x18], 4))
|
||||
info->connector.digital.ycrcb422 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x18], 3, 4);
|
||||
ColorType color_type[4] =
|
||||
{
|
||||
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
|
||||
};
|
||||
|
||||
info->connector.analog.color_type = color_type[bits];
|
||||
}
|
||||
|
||||
info->srgb_is_standard = get_bit (edid[0x18], 2);
|
||||
|
||||
/* In 1.3 this is called "has preferred timing" */
|
||||
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
|
||||
|
||||
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
|
||||
info->continuous_frequency = get_bit (edid[0x18], 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static double
|
||||
decode_fraction (int high, int low)
|
||||
{
|
||||
double result = 0.0;
|
||||
int i;
|
||||
|
||||
high = (high << 2) | low;
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
result += get_bit (high, i) * pow (2, i - 10);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
|
||||
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
|
||||
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
|
||||
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
|
||||
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
|
||||
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
|
||||
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
|
||||
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_established_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
static const Timing established[][8] =
|
||||
{
|
||||
{
|
||||
{ 800, 600, 60 },
|
||||
{ 800, 600, 56 },
|
||||
{ 640, 480, 75 },
|
||||
{ 640, 480, 72 },
|
||||
{ 640, 480, 67 },
|
||||
{ 640, 480, 60 },
|
||||
{ 720, 400, 88 },
|
||||
{ 720, 400, 70 }
|
||||
},
|
||||
{
|
||||
{ 1280, 1024, 75 },
|
||||
{ 1024, 768, 75 },
|
||||
{ 1024, 768, 70 },
|
||||
{ 1024, 768, 60 },
|
||||
{ 1024, 768, 87 },
|
||||
{ 832, 624, 75 },
|
||||
{ 800, 600, 75 },
|
||||
{ 800, 600, 72 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 1152, 870, 75 }
|
||||
},
|
||||
};
|
||||
|
||||
int i, j, idx;
|
||||
|
||||
idx = 0;
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
for (j = 0; j < 8; ++j)
|
||||
{
|
||||
int byte = edid[0x23 + i];
|
||||
|
||||
if (get_bit (byte, j) && established[i][j].frequency != 0)
|
||||
info->established[idx++] = established[i][j];
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_standard_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
int first = edid[0x26 + 2 * i];
|
||||
int second = edid[0x27 + 2 * i];
|
||||
|
||||
if (first != 0x01 && second != 0x01)
|
||||
{
|
||||
int w = 8 * (first + 31);
|
||||
int h = 0;
|
||||
|
||||
switch (get_bits (second, 6, 7))
|
||||
{
|
||||
case 0x00: h = (w / 16) * 10; break;
|
||||
case 0x01: h = (w / 4) * 3; break;
|
||||
case 0x02: h = (w / 5) * 4; break;
|
||||
case 0x03: h = (w / 16) * 9; break;
|
||||
}
|
||||
|
||||
info->standard[i].width = w;
|
||||
info->standard[i].height = h;
|
||||
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_lf_string (const uchar *s, int n_chars, char *result)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n_chars; ++i)
|
||||
{
|
||||
if (s[i] == 0x0a)
|
||||
{
|
||||
*result++ = '\0';
|
||||
break;
|
||||
}
|
||||
else if (s[i] == 0x00)
|
||||
{
|
||||
/* Convert embedded 0's to spaces */
|
||||
*result++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*result++ = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_display_descriptor (const uchar *desc,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
switch (desc[0x03])
|
||||
{
|
||||
case 0xFC:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_product_name);
|
||||
break;
|
||||
case 0xFF:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
|
||||
break;
|
||||
case 0xFE:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_string);
|
||||
break;
|
||||
case 0xFD:
|
||||
/* Range Limits */
|
||||
break;
|
||||
case 0xFB:
|
||||
/* Color Point */
|
||||
break;
|
||||
case 0xFA:
|
||||
/* Timing Identifications */
|
||||
break;
|
||||
case 0xF9:
|
||||
/* Color Management */
|
||||
break;
|
||||
case 0xF8:
|
||||
/* Timing Codes */
|
||||
break;
|
||||
case 0xF7:
|
||||
/* Established Timings */
|
||||
break;
|
||||
case 0x10:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_detailed_timing (const uchar *timing,
|
||||
DetailedTiming *detailed)
|
||||
{
|
||||
int bits;
|
||||
StereoType stereo[] =
|
||||
{
|
||||
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
|
||||
};
|
||||
|
||||
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
|
||||
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
|
||||
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
|
||||
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
|
||||
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
|
||||
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
|
||||
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
|
||||
detailed->v_front_porch =
|
||||
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
|
||||
detailed->v_sync =
|
||||
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
|
||||
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
|
||||
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
|
||||
detailed->right_border = timing[0x0f];
|
||||
detailed->top_border = timing[0x10];
|
||||
|
||||
detailed->interlaced = get_bit (timing[0x11], 7);
|
||||
|
||||
/* Stereo */
|
||||
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
|
||||
detailed->stereo = stereo[bits];
|
||||
|
||||
/* Sync */
|
||||
bits = timing[0x11];
|
||||
|
||||
detailed->digital_sync = get_bit (bits, 4);
|
||||
if (detailed->digital_sync)
|
||||
{
|
||||
detailed->connector.digital.composite = !get_bit (bits, 3);
|
||||
|
||||
if (detailed->connector.digital.composite)
|
||||
{
|
||||
detailed->connector.digital.serrations = get_bit (bits, 2);
|
||||
detailed->connector.digital.negative_vsync = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.digital.serrations = FALSE;
|
||||
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
|
||||
}
|
||||
|
||||
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.analog.bipolar = get_bit (bits, 3);
|
||||
detailed->connector.analog.serrations = get_bit (bits, 2);
|
||||
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decode_descriptors (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
int timing_idx;
|
||||
|
||||
timing_idx = 0;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
int index = 0x36 + i * 18;
|
||||
|
||||
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
|
||||
{
|
||||
decode_display_descriptor (edid + index, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode_detailed_timing (
|
||||
edid + index, &(info->detailed_timings[timing_idx++]));
|
||||
}
|
||||
}
|
||||
|
||||
info->n_detailed_timings = timing_idx;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_check_sum (const uchar *edid,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
uchar check = 0;
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
check += edid[i];
|
||||
|
||||
info->checksum = check;
|
||||
}
|
||||
|
||||
MonitorInfo *
|
||||
decode_edid (const uchar *edid)
|
||||
{
|
||||
MonitorInfo *info = g_new0 (MonitorInfo, 1);
|
||||
|
||||
decode_check_sum (edid, info);
|
||||
|
||||
if (decode_header (edid)
|
||||
&& decode_vendor_and_product_identification (edid, info)
|
||||
&& decode_edid_version (edid, info)
|
||||
&& decode_display_parameters (edid, info)
|
||||
&& decode_color_characteristics (edid, info)
|
||||
&& decode_established_timings (edid, info)
|
||||
&& decode_standard_timings (edid, info)
|
||||
&& decode_descriptors (edid, info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (info);
|
||||
return NULL;
|
||||
}
|
||||
}
|
195
src/core/edid.h
195
src/core/edid.h
@@ -1,195 +0,0 @@
|
||||
/* edid.h
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef EDID_H
|
||||
#define EDID_H
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef struct MonitorInfo MonitorInfo;
|
||||
typedef struct Timing Timing;
|
||||
typedef struct DetailedTiming DetailedTiming;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED,
|
||||
DVI,
|
||||
HDMI_A,
|
||||
HDMI_B,
|
||||
MDDI,
|
||||
DISPLAY_PORT
|
||||
} Interface;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED_COLOR,
|
||||
MONOCHROME,
|
||||
RGB,
|
||||
OTHER_COLOR
|
||||
} ColorType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_STEREO,
|
||||
FIELD_RIGHT,
|
||||
FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN,
|
||||
TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED,
|
||||
SIDE_BY_SIDE
|
||||
} StereoType;
|
||||
|
||||
struct Timing
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int frequency;
|
||||
};
|
||||
|
||||
struct DetailedTiming
|
||||
{
|
||||
int pixel_clock;
|
||||
int h_addr;
|
||||
int h_blank;
|
||||
int h_sync;
|
||||
int h_front_porch;
|
||||
int v_addr;
|
||||
int v_blank;
|
||||
int v_sync;
|
||||
int v_front_porch;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
int right_border;
|
||||
int top_border;
|
||||
int interlaced;
|
||||
StereoType stereo;
|
||||
|
||||
int digital_sync;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bipolar;
|
||||
int serrations;
|
||||
int sync_on_green;
|
||||
} analog;
|
||||
|
||||
struct
|
||||
{
|
||||
int composite;
|
||||
int serrations;
|
||||
int negative_vsync;
|
||||
int negative_hsync;
|
||||
} digital;
|
||||
} connector;
|
||||
};
|
||||
|
||||
struct MonitorInfo
|
||||
{
|
||||
int checksum;
|
||||
char manufacturer_code[4];
|
||||
int product_code;
|
||||
unsigned int serial_number;
|
||||
|
||||
int production_week; /* -1 if not specified */
|
||||
int production_year; /* -1 if not specified */
|
||||
int model_year; /* -1 if not specified */
|
||||
|
||||
int major_version;
|
||||
int minor_version;
|
||||
|
||||
int is_digital;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bits_per_primary;
|
||||
Interface interface;
|
||||
int rgb444;
|
||||
int ycrcb444;
|
||||
int ycrcb422;
|
||||
} digital;
|
||||
|
||||
struct
|
||||
{
|
||||
double video_signal_level;
|
||||
double sync_signal_level;
|
||||
double total_signal_level;
|
||||
|
||||
int blank_to_black;
|
||||
|
||||
int separate_hv_sync;
|
||||
int composite_sync_on_h;
|
||||
int composite_sync_on_green;
|
||||
int serration_on_vsync;
|
||||
ColorType color_type;
|
||||
} analog;
|
||||
} connector;
|
||||
|
||||
int width_mm; /* -1 if not specified */
|
||||
int height_mm; /* -1 if not specified */
|
||||
double aspect_ratio; /* -1.0 if not specififed */
|
||||
|
||||
double gamma; /* -1.0 if not specified */
|
||||
|
||||
int standby;
|
||||
int suspend;
|
||||
int active_off;
|
||||
|
||||
int srgb_is_standard;
|
||||
int preferred_timing_includes_native;
|
||||
int continuous_frequency;
|
||||
|
||||
double red_x;
|
||||
double red_y;
|
||||
double green_x;
|
||||
double green_y;
|
||||
double blue_x;
|
||||
double blue_y;
|
||||
double white_x;
|
||||
double white_y;
|
||||
|
||||
Timing established[24]; /* Terminated by 0x0x0 */
|
||||
Timing standard[8];
|
||||
|
||||
int n_detailed_timings;
|
||||
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
|
||||
* mode, it is the first one
|
||||
* (whether it has, is
|
||||
* determined by the
|
||||
* preferred_timing_includes
|
||||
* bit.
|
||||
*/
|
||||
|
||||
/* Optional product description */
|
||||
char dsc_serial_number[14];
|
||||
char dsc_product_name[14];
|
||||
char dsc_string[14]; /* Unspecified ASCII data */
|
||||
};
|
||||
|
||||
MonitorInfo *decode_edid (const uchar *data);
|
||||
char *make_display_name (const MonitorInfo *info);
|
||||
char *make_display_size_string (int width_mm, int height_mm);
|
||||
|
||||
#endif
|
@@ -332,6 +332,19 @@ meta_frame_calc_borders (MetaFrame *frame,
|
||||
borders);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_get_corner_radiuses (MetaFrame *frame,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right)
|
||||
{
|
||||
meta_ui_get_corner_radiuses (frame->window->screen->ui,
|
||||
frame->xwindow,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_frame_sync_to_window (MetaFrame *frame,
|
||||
int resize_gravity,
|
||||
@@ -387,14 +400,6 @@ meta_frame_get_frame_bounds (MetaFrame *frame)
|
||||
frame->rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_get_mask (MetaFrame *frame,
|
||||
cairo_t *cr)
|
||||
{
|
||||
meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
|
||||
frame->rect.width, frame->rect.height, cr);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_queue_draw (MetaFrame *frame)
|
||||
{
|
||||
|
@@ -63,6 +63,12 @@ Window meta_frame_get_xwindow (MetaFrame *frame);
|
||||
void meta_frame_calc_borders (MetaFrame *frame,
|
||||
MetaFrameBorders *borders);
|
||||
|
||||
void meta_frame_get_corner_radiuses (MetaFrame *frame,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right);
|
||||
|
||||
gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
||||
int gravity,
|
||||
gboolean need_move,
|
||||
@@ -70,9 +76,6 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
||||
|
||||
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
|
||||
|
||||
void meta_frame_get_mask (MetaFrame *frame,
|
||||
cairo_t *cr);
|
||||
|
||||
void meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaCursor cursor);
|
||||
|
||||
|
@@ -69,6 +69,7 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event);
|
||||
void meta_set_keybindings_disabled (gboolean setting);
|
||||
void meta_display_process_mapping_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
|
@@ -56,6 +56,8 @@
|
||||
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
|
||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
||||
|
||||
static gboolean all_bindings_disabled = FALSE;
|
||||
|
||||
static gboolean add_builtin_keybinding (MetaDisplay *display,
|
||||
const char *name,
|
||||
GSettings *settings,
|
||||
@@ -1310,7 +1312,7 @@ handle_external_grab (MetaDisplay *display,
|
||||
guint action = meta_display_get_keybinding_action (display,
|
||||
binding->keycode,
|
||||
binding->mask);
|
||||
meta_display_accelerator_activate (display, action, event->deviceid, event->time);
|
||||
meta_display_accelerator_activate (display, action, event->deviceid);
|
||||
}
|
||||
|
||||
|
||||
@@ -1965,23 +1967,6 @@ process_overlay_key (MetaDisplay *display,
|
||||
return TRUE;
|
||||
meta_display_overlay_key_activate (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In some rare race condition, mutter might not receive the Super_L
|
||||
* KeyRelease event because:
|
||||
* - the compositor might end the modal mode and call XIUngrabDevice
|
||||
* while the key is still down
|
||||
* - passive grabs are only activated on KeyPress and not KeyRelease.
|
||||
*
|
||||
* In this case, display->overlay_key_only_pressed might be wrong.
|
||||
* Mutter still ought to acknowledge events, otherwise the X server
|
||||
* will not send the next events.
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
|
||||
*/
|
||||
XIAllowEvents (display->xdisplay, event->deviceid,
|
||||
XIAsyncDevice, event->time);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -2061,6 +2046,21 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
const char *str;
|
||||
MetaScreen *screen;
|
||||
|
||||
if (all_bindings_disabled)
|
||||
{
|
||||
/* In this mode, we try to pretend we don't have grabs, so we
|
||||
* immediately replay events and drop the grab. (This still
|
||||
* messes up global passive grabs from other clients.) The
|
||||
* FALSE return here is a little suspect, but we don't really
|
||||
* know if we'll see the event again or not, and it's pretty
|
||||
* poorly defined how this mode is supposed to interact with
|
||||
* plugins.
|
||||
*/
|
||||
XIAllowEvents (display->xdisplay, event->deviceid,
|
||||
XIReplayDevice, event->time);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* if key event was on root window, we have a shortcut */
|
||||
screen = meta_display_screen_for_root (display, event->event);
|
||||
|
||||
@@ -4098,6 +4098,14 @@ handle_set_spew_mark (MetaDisplay *display,
|
||||
meta_verbose ("-- MARK MARK MARK MARK --\n");
|
||||
}
|
||||
|
||||
void
|
||||
meta_set_keybindings_disabled (gboolean setting)
|
||||
{
|
||||
all_bindings_disabled = setting;
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_keybindings_set_custom_handler:
|
||||
* @name: The name of the keybinding to set
|
||||
|
112
src/core/main.c
112
src/core/main.c
@@ -56,7 +56,6 @@
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <glib-object.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
@@ -94,6 +93,26 @@ static GMainLoop *meta_main_loop = NULL;
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* log_handler:
|
||||
* @log_domain: the domain the error occurred in (we ignore this)
|
||||
* @log_level: the log level so that we can filter out less
|
||||
* important messages
|
||||
* @message: the message to log
|
||||
* @user_data: arbitrary data (we ignore this)
|
||||
*
|
||||
* Prints log messages. If Mutter was compiled with backtrace support,
|
||||
* also prints a backtrace (see meta_print_backtrace()).
|
||||
*/
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_warning ("Log level %d: %s\n", log_level, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_print_compilation_info:
|
||||
*
|
||||
@@ -329,8 +348,23 @@ 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 (gpointer user_data)
|
||||
on_sigterm (void)
|
||||
{
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
return FALSE;
|
||||
@@ -347,7 +381,8 @@ 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;
|
||||
@@ -361,9 +396,20 @@ meta_init (void)
|
||||
g_strerror (errno));
|
||||
#endif
|
||||
|
||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
||||
if (pipe (sigterm_pipe_fds) != 0)
|
||||
g_printerr ("Failed to create SIGTERM pipe: %s\n",
|
||||
g_strerror (errno));
|
||||
|
||||
meta_debug_init ();
|
||||
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));
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
meta_set_verbose (TRUE);
|
||||
@@ -450,25 +496,63 @@ 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);
|
||||
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
|
||||
g_log_set_handler (log_domains[i],
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler, NULL);
|
||||
|
||||
/* If the theme preference does not exists, fallback to
|
||||
* Adwaita (the default theme), or abort if that doesn't
|
||||
* exists.
|
||||
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 (!meta_ui_have_a_theme ())
|
||||
meta_ui_set_current_theme ("Adwaita");
|
||||
|
||||
meta_ui_set_current_theme ("Simple", FALSE);
|
||||
|
||||
if (!meta_ui_have_a_theme ())
|
||||
meta_fatal ("Adwaita theme missing, please install the gnome-themes-standard package");
|
||||
{
|
||||
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");
|
||||
|
||||
if (!meta_display_open ())
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
|
||||
|
||||
g_main_loop_run (meta_main_loop);
|
||||
|
||||
meta_finalize ();
|
||||
@@ -514,7 +598,7 @@ prefs_changed_callback (MetaPreference pref,
|
||||
{
|
||||
case META_PREF_THEME:
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
|
||||
meta_display_retheme_all ();
|
||||
break;
|
||||
|
||||
|
@@ -1,40 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
|
||||
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
|
||||
|
||||
The canonical place for all changes is mutter.
|
||||
|
||||
There should be no includes in this file.
|
||||
*/
|
||||
|
||||
#ifndef META_XRANDR_SHARED_H
|
||||
#define META_XRANDR_SHARED_H
|
||||
|
||||
typedef enum {
|
||||
META_POWER_SAVE_UNKNOWN = -1,
|
||||
META_POWER_SAVE_ON = 0,
|
||||
META_POWER_SAVE_STANDBY,
|
||||
META_POWER_SAVE_SUSPEND,
|
||||
META_POWER_SAVE_OFF,
|
||||
} MetaPowerSave;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -1,390 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file screen-private.h Handling of monitor configuration
|
||||
*
|
||||
* Managing multiple monitors
|
||||
* This file contains structures and functions that handle
|
||||
* multiple monitors, including reading the current configuration
|
||||
* and available hardware, and applying it.
|
||||
*
|
||||
* This interface is private to mutter, API users should look
|
||||
* at MetaScreen instead.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_MONITOR_PRIVATE_H
|
||||
#define META_MONITOR_PRIVATE_H
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <libgnome-desktop/gnome-pnp-ids.h>
|
||||
|
||||
#include "display-private.h"
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
#endif
|
||||
#include "meta-xrandr-shared.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
||||
typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
|
||||
typedef struct _MetaMonitorConfig MetaMonitorConfig;
|
||||
|
||||
#ifndef HAVE_WAYLAND
|
||||
enum wl_output_transform {
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
WL_OUTPUT_TRANSFORM_90,
|
||||
WL_OUTPUT_TRANSFORM_180,
|
||||
WL_OUTPUT_TRANSFORM_270,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct _MetaOutput MetaOutput;
|
||||
typedef struct _MetaCRTC MetaCRTC;
|
||||
typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
MetaCRTC *crtc;
|
||||
/* The low-level ID of this output, used to apply back configuration */
|
||||
glong output_id;
|
||||
char *name;
|
||||
char *vendor;
|
||||
char *product;
|
||||
char *serial;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
CoglSubpixelOrder subpixel_order;
|
||||
|
||||
MetaMonitorMode *preferred_mode;
|
||||
MetaMonitorMode **modes;
|
||||
unsigned int n_modes;
|
||||
|
||||
MetaCRTC **possible_crtcs;
|
||||
unsigned int n_possible_crtcs;
|
||||
|
||||
MetaOutput **possible_clones;
|
||||
unsigned int n_possible_clones;
|
||||
|
||||
int backlight;
|
||||
int backlight_min;
|
||||
int backlight_max;
|
||||
|
||||
/* Used when changing configuration */
|
||||
gboolean 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
|
@@ -1,938 +0,0 @@
|
||||
/* -*- 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
1553
src/core/monitor.c
File diff suppressed because it is too large
Load Diff
@@ -89,6 +89,7 @@ static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_
|
||||
static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
|
||||
static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU;
|
||||
static gboolean dynamic_workspaces = FALSE;
|
||||
static gboolean application_based = FALSE;
|
||||
static gboolean disable_workarounds = FALSE;
|
||||
static gboolean auto_raise = FALSE;
|
||||
static gboolean auto_raise_delay = 500;
|
||||
@@ -297,6 +298,13 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&dynamic_workspaces,
|
||||
},
|
||||
{
|
||||
{ "application-based",
|
||||
SCHEMA_GENERAL,
|
||||
META_PREF_APPLICATION_BASED,
|
||||
},
|
||||
NULL, /* feature is known but disabled */
|
||||
},
|
||||
{
|
||||
{ "disable-workarounds",
|
||||
SCHEMA_GENERAL,
|
||||
@@ -1715,6 +1723,14 @@ meta_prefs_get_dynamic_workspaces (void)
|
||||
return dynamic_workspaces;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_application_based (void)
|
||||
{
|
||||
return FALSE; /* For now, we never want this to do anything */
|
||||
|
||||
return application_based;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_disable_workarounds (void)
|
||||
{
|
||||
@@ -1752,6 +1768,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_NUM_WORKSPACES:
|
||||
return "NUM_WORKSPACES";
|
||||
|
||||
case META_PREF_APPLICATION_BASED:
|
||||
return "APPLICATION_BASED";
|
||||
|
||||
case META_PREF_KEYBINDINGS:
|
||||
return "KEYBINDINGS";
|
||||
|
||||
|
@@ -38,7 +38,17 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
|
||||
struct _MetaMonitorInfo
|
||||
{
|
||||
int number;
|
||||
MetaRectangle rect;
|
||||
gboolean is_primary;
|
||||
gboolean in_fullscreen;
|
||||
XID output; /* The primary or first output for this crtc, None if no xrandr */
|
||||
};
|
||||
|
||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||
gpointer user_data);
|
||||
@@ -90,11 +100,10 @@ struct _MetaScreen
|
||||
Window wm_sn_selection_window;
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int n_monitor_infos;
|
||||
int primary_monitor_index;
|
||||
gboolean has_xinerama_indices;
|
||||
int n_monitor_infos;
|
||||
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
@@ -222,6 +231,10 @@ void meta_screen_calc_workspace_layout (MetaScreen *screen,
|
||||
MetaWorkspaceLayout *layout);
|
||||
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
|
||||
|
||||
void meta_screen_resize (MetaScreen *screen,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
|
||||
MetaWindow *keep);
|
||||
|
||||
@@ -244,9 +257,4 @@ 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,6 +48,10 @@
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
@@ -72,9 +76,6 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
|
||||
void *user_data);
|
||||
#endif
|
||||
|
||||
static void on_monitors_changed (MetaMonitorManager *manager,
|
||||
MetaScreen *screen);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_N_WORKSPACES = 1,
|
||||
@@ -349,93 +350,250 @@ set_wm_icon_size_hint (MetaScreen *screen)
|
||||
#undef N_VALS
|
||||
}
|
||||
|
||||
/* The list of monitors reported by the windowing system might include
|
||||
* mirrored monitors with identical bounds. Since mirrored monitors
|
||||
* shouldn't be treated as separate monitors for most purposes, we
|
||||
* filter them out here. (We ignore the possibility of partially
|
||||
* overlapping monitors because they are rare and it's hard to come
|
||||
* up with any sensible interpretation.)
|
||||
*/
|
||||
static void
|
||||
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
|
||||
filter_mirrored_monitors (MetaScreen *screen)
|
||||
{
|
||||
XineramaScreenInfo *infos;
|
||||
int n_infos, i, j;
|
||||
int i, j;
|
||||
|
||||
if (screen->has_xinerama_indices)
|
||||
return;
|
||||
/* Currently always true and simplifies things */
|
||||
g_assert (screen->primary_monitor_index == 0);
|
||||
|
||||
screen->has_xinerama_indices = TRUE;
|
||||
|
||||
if (!XineramaIsActive (screen->display->xdisplay))
|
||||
return;
|
||||
|
||||
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
|
||||
if (n_infos <= 0 || infos == NULL)
|
||||
for (i = 1; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
meta_XFree (infos);
|
||||
return;
|
||||
}
|
||||
/* In case we've filtered previous monitors */
|
||||
screen->monitor_infos[i].number = i;
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; ++i)
|
||||
{
|
||||
for (j = 0; j < n_infos; ++j)
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
|
||||
screen->monitor_infos[i].rect.y == infos[j].y_org &&
|
||||
screen->monitor_infos[i].rect.width == infos[j].width &&
|
||||
screen->monitor_infos[i].rect.height == infos[j].height)
|
||||
screen->monitor_infos[i].xinerama_index = j;
|
||||
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
|
||||
&screen->monitor_infos[j].rect))
|
||||
{
|
||||
memmove (&screen->monitor_infos[i],
|
||||
&screen->monitor_infos[i + 1],
|
||||
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
|
||||
screen->n_monitor_infos--;
|
||||
i--;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_XFree (infos);
|
||||
}
|
||||
|
||||
int
|
||||
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
||||
int index)
|
||||
{
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
return screen->monitor_infos[index].xinerama_index;
|
||||
}
|
||||
|
||||
int
|
||||
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
|
||||
int index)
|
||||
#ifdef HAVE_RANDR
|
||||
static MetaMonitorInfo *
|
||||
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
|
||||
{
|
||||
MetaMonitorInfo *info;
|
||||
int i;
|
||||
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
if (screen->monitor_infos[i].xinerama_index == index)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
{
|
||||
info = &screen->monitor_infos[i];
|
||||
if (x == info->rect.x &&
|
||||
y == info->rect.y &&
|
||||
w == info->rect.width &&
|
||||
h == info->rect.height)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
|
||||
* outputs the "main". This is the one we consider "owning" the windows, so if
|
||||
* the mirroring is changed to a dual monitor setup then the windows are moved to the
|
||||
* crtc that now has that main output. If one of the outputs is the primary that is
|
||||
* always the main, otherwise we just use the first.
|
||||
*/
|
||||
static XID
|
||||
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
|
||||
{
|
||||
XRROutputInfo *output;
|
||||
RROutput primary_output;
|
||||
int i;
|
||||
XID res;
|
||||
|
||||
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
|
||||
|
||||
res = None;
|
||||
for (i = 0; i < crtc->noutput; i++)
|
||||
{
|
||||
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
|
||||
if (output->connection != RR_Disconnected &&
|
||||
(res == None || crtc->outputs[i] == primary_output))
|
||||
res = crtc->outputs[i];
|
||||
XRRFreeOutputInfo (output);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
reload_monitor_infos (MetaScreen *screen)
|
||||
{
|
||||
GList *tmp;
|
||||
MetaMonitorManager *manager;
|
||||
MetaDisplay *display;
|
||||
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
|
||||
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
display = screen->display;
|
||||
|
||||
/* Any previous screen->monitor_infos is freed by the caller */
|
||||
|
||||
screen->monitor_infos = NULL;
|
||||
screen->n_monitor_infos = 0;
|
||||
screen->last_monitor_index = 0;
|
||||
screen->has_xinerama_indices = FALSE;
|
||||
|
||||
/* Xinerama doesn't have a concept of primary monitor, however XRandR
|
||||
* does. However, the XRandR xinerama compat code always sorts the
|
||||
* primary output first, so we rely on that here. We could use the
|
||||
* native XRandR calls instead of xinerama, but that would be
|
||||
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
|
||||
* that is defined in terms of xinerama monitor indexes.
|
||||
* So, since we don't need anything in xrandr except the primary
|
||||
* we can keep using xinerama and use the first monitor as the
|
||||
* primary.
|
||||
*/
|
||||
screen->primary_monitor_index = 0;
|
||||
|
||||
screen->display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Pretending a single monitor has two Xinerama screens\n");
|
||||
|
||||
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
|
||||
(unsigned*)&screen->n_monitor_infos);
|
||||
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
|
||||
screen->n_monitor_infos = 2;
|
||||
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
|
||||
screen->monitor_infos[1].number = 1;
|
||||
screen->monitor_infos[1].rect = screen->rect;
|
||||
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
|
||||
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
}
|
||||
|
||||
if (screen->n_monitor_infos == 0 &&
|
||||
XineramaIsActive (display->xdisplay))
|
||||
{
|
||||
XineramaScreenInfo *infos;
|
||||
int n_infos;
|
||||
int i;
|
||||
|
||||
n_infos = 0;
|
||||
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Found %d Xinerama screens on display %s\n",
|
||||
n_infos, display->name);
|
||||
|
||||
if (n_infos > 0)
|
||||
{
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
|
||||
screen->n_monitor_infos = n_infos;
|
||||
|
||||
i = 0;
|
||||
while (i < n_infos)
|
||||
{
|
||||
screen->monitor_infos[i].number = infos[i].screen_number;
|
||||
screen->monitor_infos[i].rect.x = infos[i].x_org;
|
||||
screen->monitor_infos[i].rect.y = infos[i].y_org;
|
||||
screen->monitor_infos[i].rect.width = infos[i].width;
|
||||
screen->monitor_infos[i].rect.height = infos[i].height;
|
||||
screen->monitor_infos[i].in_fullscreen = -1;
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Monitor %d is %d,%d %d x %d\n",
|
||||
screen->monitor_infos[i].number,
|
||||
screen->monitor_infos[i].rect.x,
|
||||
screen->monitor_infos[i].rect.y,
|
||||
screen->monitor_infos[i].rect.width,
|
||||
screen->monitor_infos[i].rect.height);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
meta_XFree (infos);
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
{
|
||||
XRRScreenResources *resources;
|
||||
|
||||
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
|
||||
if (resources)
|
||||
{
|
||||
for (i = 0; i < resources->ncrtc; i++)
|
||||
{
|
||||
XRRCrtcInfo *crtc;
|
||||
MetaMonitorInfo *info;
|
||||
|
||||
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
|
||||
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
|
||||
if (info)
|
||||
info->output = find_main_output_for_crtc (screen, resources, crtc);
|
||||
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
XRRFreeScreenResources (resources);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (screen->n_monitor_infos > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Xinerama extension or Xinerama inactive on display %s\n",
|
||||
display->name);
|
||||
}
|
||||
|
||||
/* If no Xinerama, fill in the single screen info so
|
||||
* we can use the field unconditionally
|
||||
*/
|
||||
if (screen->n_monitor_infos == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Xinerama screens, using default screen info\n");
|
||||
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
|
||||
screen->n_monitor_infos = 1;
|
||||
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
}
|
||||
|
||||
filter_mirrored_monitors (screen);
|
||||
|
||||
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
|
||||
|
||||
g_assert (screen->n_monitor_infos > 0);
|
||||
g_assert (screen->monitor_infos != NULL);
|
||||
}
|
||||
|
||||
/* The guard window allows us to leave minimized windows mapped so
|
||||
@@ -510,7 +668,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
char buf[128];
|
||||
guint32 manager_timestamp;
|
||||
gulong current_workspace;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
replace_current_wm = meta_get_replace_current_wm ();
|
||||
|
||||
@@ -669,17 +826,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->xroot = xroot;
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
|
||||
meta_monitor_manager_initialize ();
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
g_signal_connect (manager, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), screen);
|
||||
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
|
||||
screen->rect.width = WidthOfScreen (screen->xscreen);
|
||||
screen->rect.height = HeightOfScreen (screen->xscreen);
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
@@ -704,6 +852,10 @@ 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);
|
||||
@@ -789,7 +941,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
|
||||
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
|
||||
screen->number, screen->screen_name, screen->xroot);
|
||||
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
@@ -2845,15 +2997,19 @@ meta_screen_resize_func (MetaScreen *screen,
|
||||
meta_window_recalc_features (window);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *manager,
|
||||
MetaScreen *screen)
|
||||
void
|
||||
meta_screen_resize (MetaScreen *screen,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GSList *tmp, *windows;
|
||||
GSList *windows, *tmp;
|
||||
MetaMonitorInfo *old_monitor_infos;
|
||||
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
screen->rect.width = width;
|
||||
screen->rect.height = height;
|
||||
|
||||
/* Save the old monitor infos, so they stay valid during the update */
|
||||
old_monitor_infos = screen->monitor_infos;
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
set_desktop_geometry_hint (screen);
|
||||
@@ -2865,8 +3021,8 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
|
||||
changes.x = 0;
|
||||
changes.y = 0;
|
||||
changes.width = screen->rect.width;
|
||||
changes.height = screen->rect.height;
|
||||
changes.width = width;
|
||||
changes.height = height;
|
||||
|
||||
XConfigureWindow(screen->display->xdisplay,
|
||||
screen->guard_window,
|
||||
@@ -2876,8 +3032,7 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
screen, width, height);
|
||||
|
||||
/* Queue a resize on all the windows */
|
||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||
@@ -2893,6 +3048,7 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
meta_window_update_for_monitors_changed (window);
|
||||
}
|
||||
|
||||
g_free (old_monitor_infos);
|
||||
g_slist_free (windows);
|
||||
|
||||
meta_screen_queue_check_fullscreen (screen);
|
||||
|
@@ -278,7 +278,7 @@ static gboolean
|
||||
is_focused_foreach (MetaWindow *window,
|
||||
void *data)
|
||||
{
|
||||
if (window->has_focus)
|
||||
if (window == window->display->expected_focus_window)
|
||||
{
|
||||
*((gboolean*) data) = TRUE;
|
||||
return FALSE;
|
||||
@@ -335,11 +335,11 @@ get_standalone_layer (MetaWindow *window)
|
||||
layer = META_LAYER_BOTTOM;
|
||||
else if (window->fullscreen &&
|
||||
(focused_transient ||
|
||||
window == window->display->focus_window ||
|
||||
window->display->focus_window == NULL ||
|
||||
(window->display->focus_window != NULL &&
|
||||
window == window->display->expected_focus_window ||
|
||||
window->display->expected_focus_window == NULL ||
|
||||
(window->display->expected_focus_window != NULL &&
|
||||
windows_on_different_monitor (window,
|
||||
window->display->focus_window))))
|
||||
window->display->expected_focus_window))))
|
||||
layer = META_LAYER_FULLSCREEN;
|
||||
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
|
||||
layer = META_LAYER_TOP;
|
||||
|
133
src/core/util.c
133
src/core/util.c
@@ -332,8 +332,6 @@ topic_name (MetaDebugTopic topic)
|
||||
return "COMPOSITOR";
|
||||
case META_DEBUG_EDGE_RESISTANCE:
|
||||
return "EDGE_RESISTANCE";
|
||||
case META_DEBUG_DBUS:
|
||||
return "DBUS";
|
||||
case META_DEBUG_VERBOSE:
|
||||
return "VERBOSE";
|
||||
}
|
||||
@@ -391,100 +389,91 @@ 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);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, stripped, args);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
g_free (stripped);
|
||||
#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 ();
|
||||
}
|
||||
|
||||
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);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, stripped, args);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
g_free (stripped);
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, stripped, args);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
g_free (stripped);
|
||||
#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);
|
||||
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
}
|
||||
@@ -506,6 +495,7 @@ meta_pop_no_msg_prefix (void)
|
||||
void
|
||||
meta_exit (MetaExitCode code)
|
||||
{
|
||||
|
||||
exit (code);
|
||||
}
|
||||
|
||||
@@ -647,13 +637,8 @@ meta_show_dialog (const char *type,
|
||||
|
||||
append_argument (args, "zenity");
|
||||
append_argument (args, type);
|
||||
|
||||
if (display)
|
||||
{
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
}
|
||||
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
append_argument (args, "--class");
|
||||
append_argument (args, "mutter-dialog");
|
||||
append_argument (args, "--title");
|
||||
|
@@ -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. */
|
||||
gint fullscreen_monitors[4];
|
||||
long fullscreen_monitors[4];
|
||||
|
||||
/* Whether we're trying to constrain the window to be fully onscreen */
|
||||
guint require_fully_onscreen : 1;
|
||||
@@ -277,7 +277,7 @@ struct _MetaWindow
|
||||
/* EWHH demands attention flag */
|
||||
guint wm_state_demands_attention : 1;
|
||||
|
||||
/* TRUE iff window == window->display->focus_window */
|
||||
/* this flag tracks receipt of focus_in focus_out */
|
||||
guint has_focus : 1;
|
||||
|
||||
/* Have we placed this window? */
|
||||
@@ -394,9 +394,6 @@ struct _MetaWindow
|
||||
*/
|
||||
MetaRectangle rect;
|
||||
|
||||
gboolean has_custom_frame_extents;
|
||||
GtkBorder custom_frame_extents;
|
||||
|
||||
/* The geometry to restore when we unmaximize. The position is in
|
||||
* root window coords, even if there's a frame, which contrasts with
|
||||
* window->rect above. Note that this gives the position and size
|
||||
@@ -593,8 +590,9 @@ gboolean meta_window_property_notify (MetaWindow *window,
|
||||
XEvent *event);
|
||||
gboolean meta_window_client_message (MetaWindow *window,
|
||||
XEvent *event);
|
||||
void meta_window_set_focused_internal (MetaWindow *window,
|
||||
gboolean focused);
|
||||
gboolean meta_window_notify_focus (MetaWindow *window,
|
||||
XIEnterEvent *event);
|
||||
void meta_window_lost_focus (MetaWindow *window);
|
||||
|
||||
void meta_window_set_current_workspace_hint (MetaWindow *window);
|
||||
|
||||
|
@@ -289,35 +289,6 @@ reload_icon_geometry (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reload_gtk_frame_extents (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
gboolean initial)
|
||||
{
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
{
|
||||
if (value->v.cardinal_list.n_cardinals != 4)
|
||||
{
|
||||
meta_verbose ("_GTK_FRAME_EXTENTS on %s has %d values instead of 4\n",
|
||||
window->desc, value->v.cardinal_list.n_cardinals);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkBorder *extents = &window->custom_frame_extents;
|
||||
|
||||
window->has_custom_frame_extents = TRUE;
|
||||
extents->left = (int)value->v.cardinal_list.cardinals[0];
|
||||
extents->right = (int)value->v.cardinal_list.cardinals[1];
|
||||
extents->top = (int)value->v.cardinal_list.cardinals[2];
|
||||
extents->bottom = (int)value->v.cardinal_list.cardinals[3];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
window->has_custom_frame_extents = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reload_struts (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
@@ -1795,7 +1766,6 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
|
||||
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, TRUE, FALSE },
|
||||
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, TRUE, FALSE },
|
||||
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, TRUE, FALSE },
|
||||
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, TRUE, FALSE },
|
||||
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
|
||||
{ display->atom_WM_STATE, META_PROP_VALUE_INVALID, NULL, FALSE, FALSE },
|
||||
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, FALSE, FALSE },
|
||||
|
@@ -1756,6 +1756,16 @@ meta_window_unmanage (MetaWindow *window,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else if (window->display->expected_focus_window == window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing default window since expected focus window freed %s\n",
|
||||
window->desc);
|
||||
window->display->expected_focus_window = NULL;
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
@@ -1763,8 +1773,6 @@ meta_window_unmanage (MetaWindow *window,
|
||||
window->desc);
|
||||
}
|
||||
|
||||
g_assert (window->display->focus_window != window);
|
||||
|
||||
if (window->struts)
|
||||
{
|
||||
meta_free_gslist_and_elements (window->struts);
|
||||
@@ -1787,6 +1795,12 @@ meta_window_unmanage (MetaWindow *window,
|
||||
|
||||
g_assert (window->display->grab_window != window);
|
||||
|
||||
if (window->display->focus_window == window)
|
||||
{
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
}
|
||||
|
||||
if (window->maximized_horizontally || window->maximized_vertically)
|
||||
unmaximize_window_before_freeing (window);
|
||||
|
||||
@@ -2108,14 +2122,10 @@ set_net_wm_state (MetaWindow *window)
|
||||
|
||||
if (window->fullscreen)
|
||||
{
|
||||
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]);
|
||||
data[0] = window->fullscreen_monitors[0];
|
||||
data[1] = window->fullscreen_monitors[1];
|
||||
data[2] = window->fullscreen_monitors[2];
|
||||
data[3] = window->fullscreen_monitors[3];
|
||||
|
||||
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
|
||||
meta_error_trap_push (window->display);
|
||||
@@ -3324,7 +3334,14 @@ meta_window_hide (MetaWindow *window)
|
||||
invalidate_work_areas (window);
|
||||
}
|
||||
|
||||
if (window->has_focus)
|
||||
/* The check on expected_focus_window is a temporary workaround for
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
|
||||
* We may have already switched away from this window but not yet
|
||||
* gotten FocusIn/FocusOut events. A more complete comprehensive
|
||||
* fix for these type of issues is described in the bug.
|
||||
*/
|
||||
if (window->has_focus &&
|
||||
window == window->display->expected_focus_window)
|
||||
{
|
||||
MetaWindow *not_this_one = NULL;
|
||||
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
|
||||
@@ -4789,8 +4806,7 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
{
|
||||
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
|
||||
|
||||
if (info->output_id != 0 &&
|
||||
info->output_id == old->output_id)
|
||||
if (info->output == old->output)
|
||||
{
|
||||
new = info;
|
||||
break;
|
||||
@@ -5826,18 +5842,7 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
||||
rect->height -= borders.invisible.top + borders.invisible.bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
*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;
|
||||
}
|
||||
}
|
||||
*rect = window->rect;
|
||||
}
|
||||
|
||||
const char*
|
||||
@@ -5978,10 +5983,10 @@ meta_window_focus (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
|
||||
window->desc);
|
||||
|
||||
meta_display_request_take_focus (window->display,
|
||||
window,
|
||||
timestamp);
|
||||
meta_window_send_icccm_message (window,
|
||||
window->display->atom_WM_TAKE_FOCUS,
|
||||
timestamp);
|
||||
window->display->expected_focus_window = window;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6521,7 +6526,7 @@ meta_window_configure_request (MetaWindow *window,
|
||||
if (event->xconfigurerequest.value_mask & CWStackMode)
|
||||
{
|
||||
MetaWindow *active_window;
|
||||
active_window = window->display->focus_window;
|
||||
active_window = window->display->expected_focus_window;
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
@@ -7135,14 +7140,10 @@ meta_window_client_message (MetaWindow *window,
|
||||
meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
|
||||
window->desc);
|
||||
|
||||
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]);
|
||||
top = event->xclient.data.l[0];
|
||||
bottom = event->xclient.data.l[1];
|
||||
left = event->xclient.data.l[2];
|
||||
right = event->xclient.data.l[3];
|
||||
/* source_indication = event->xclient.data.l[4]; */
|
||||
|
||||
meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
|
||||
@@ -7204,7 +7205,8 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
parent->attached_focus_window = NULL;
|
||||
}
|
||||
|
||||
if (child_focus_state_changed && !parent->has_focus)
|
||||
if (child_focus_state_changed && !parent->has_focus &&
|
||||
parent != window->display->expected_focus_window)
|
||||
{
|
||||
meta_window_appears_focused_changed (parent);
|
||||
}
|
||||
@@ -7215,85 +7217,23 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_focused_internal (MetaWindow *window,
|
||||
gboolean focused)
|
||||
meta_window_lost_focus (MetaWindow *window)
|
||||
{
|
||||
if (focused)
|
||||
if (window == window->display->focus_window)
|
||||
{
|
||||
window->has_focus = TRUE;
|
||||
if (window->override_redirect)
|
||||
return;
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"%s is now the previous focus window due to being focused out or unmapped\n",
|
||||
window->desc);
|
||||
|
||||
/* Move to the front of the focusing workspace's MRU list.
|
||||
* We should only be "removing" it from the MRU list if it's
|
||||
* not already there. Note that it's possible that we might
|
||||
* be processing this FocusIn after we've changed to a
|
||||
* different workspace; we should therefore update the MRU
|
||||
* list only if the window is actually on the active
|
||||
* workspace.
|
||||
*/
|
||||
if (window->screen->active_workspace &&
|
||||
meta_window_located_on_workspace (window,
|
||||
window->screen->active_workspace))
|
||||
{
|
||||
GList* link;
|
||||
link = g_list_find (window->screen->active_workspace->mru_list,
|
||||
window);
|
||||
g_assert (link);
|
||||
|
||||
window->screen->active_workspace->mru_list =
|
||||
g_list_remove_link (window->screen->active_workspace->mru_list,
|
||||
link);
|
||||
g_list_free (link);
|
||||
|
||||
window->screen->active_workspace->mru_list =
|
||||
g_list_prepend (window->screen->active_workspace->mru_list,
|
||||
window);
|
||||
}
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XInstallColormap (window->display->xdisplay,
|
||||
window->colormap);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* move into FOCUSED_WINDOW layer */
|
||||
meta_window_update_layer (window);
|
||||
|
||||
/* Ungrab click to focus button since the sync grab can interfere
|
||||
* with some things you might do inside the focused window, by
|
||||
* causing the client to get funky enter/leave events.
|
||||
*
|
||||
* The reason we usually have a passive grab on the window is
|
||||
* so that we can intercept clicks and raise the window in
|
||||
* response. For click-to-focus we don't need that since the
|
||||
* focused window is already raised. When raise_on_click is
|
||||
* FALSE we also don't need that since we don't do anything
|
||||
* when the window is clicked.
|
||||
*
|
||||
* There is dicussion in bugs 102209, 115072, and 461577
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
|
||||
!meta_prefs_get_raise_on_click())
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
|
||||
g_signal_emit (window, window_signals[FOCUS], 0);
|
||||
|
||||
if (!window->attached_focus_window)
|
||||
meta_window_appears_focused_changed (window);
|
||||
|
||||
meta_window_propagate_focus_appearance (window, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->has_focus = FALSE;
|
||||
if (window->override_redirect)
|
||||
return;
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"* Focus --> NULL (was %s)\n", window->desc);
|
||||
|
||||
meta_window_propagate_focus_appearance (window, FALSE);
|
||||
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
window->has_focus = FALSE;
|
||||
|
||||
if (!window->attached_focus_window)
|
||||
meta_window_appears_focused_changed (window);
|
||||
|
||||
@@ -7312,6 +7252,176 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_notify_focus (MetaWindow *window,
|
||||
XIEnterEvent *event)
|
||||
{
|
||||
/* note the event can be on either the window or the frame,
|
||||
* we focus the frame for shaded windows
|
||||
*/
|
||||
|
||||
/* The event can be FocusIn, FocusOut, or UnmapNotify.
|
||||
* On UnmapNotify we have to pretend it's focus out,
|
||||
* because we won't get a focus out if it occurs, apparently.
|
||||
*/
|
||||
|
||||
/* We ignore grabs, though this is questionable.
|
||||
* It may be better to increase the intelligence of
|
||||
* the focus window tracking.
|
||||
*
|
||||
* The problem is that keybindings for windows are done with
|
||||
* XGrabKey, which means focus_window disappears and the front of
|
||||
* the MRU list gets confused from what the user expects once a
|
||||
* keybinding is used.
|
||||
*/
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on %s 0x%lx (%s) "
|
||||
"mode %s detail %s\n",
|
||||
event->evtype == XI_FocusIn ? "in" :
|
||||
event->evtype == XI_FocusOut ? "out" :
|
||||
"???",
|
||||
window->desc, event->event,
|
||||
event->event == window->xwindow ?
|
||||
"client window" :
|
||||
(window->frame && event->event == window->frame->xwindow) ?
|
||||
"frame window" :
|
||||
"unknown window",
|
||||
meta_event_mode_to_string (event->mode),
|
||||
meta_event_detail_to_string (event->detail));
|
||||
|
||||
/* FIXME our pointer tracking is broken; see how
|
||||
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
|
||||
* handle it for the correct way. In brief you need to track
|
||||
* pointer focus and regular focus, and handle EnterNotify in
|
||||
* PointerRoot mode with no window manager. However as noted above,
|
||||
* accurate focus tracking will break things because we want to keep
|
||||
* windows "focused" when using keybindings on them, and also we
|
||||
* sometimes "focus" a window by focusing its frame or
|
||||
* no_focus_window; so this all needs rethinking massively.
|
||||
*
|
||||
* My suggestion is to change it so that we clearly separate
|
||||
* actual keyboard focus tracking using the xterm algorithm,
|
||||
* and mutter's "pretend" focus window, and go through all
|
||||
* the code and decide which one should be used in each place;
|
||||
* a hard bit is deciding on a policy for that.
|
||||
*
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
|
||||
*/
|
||||
|
||||
if ((event->evtype == XI_FocusIn ||
|
||||
event->evtype == XI_FocusOut) &&
|
||||
(event->mode == NotifyGrab ||
|
||||
event->mode == NotifyUngrab ||
|
||||
/* From WindowMaker, ignore all funky pointer root events */
|
||||
event->detail > NotifyNonlinearVirtual))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus event generated by a grab or other weirdness\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (event->evtype == XI_FocusIn)
|
||||
{
|
||||
if (window->override_redirect)
|
||||
{
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (window != window->display->focus_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"* Focus --> %s\n", window->desc);
|
||||
window->display->focus_window = window;
|
||||
window->has_focus = TRUE;
|
||||
|
||||
/* Move to the front of the focusing workspace's MRU list.
|
||||
* We should only be "removing" it from the MRU list if it's
|
||||
* not already there. Note that it's possible that we might
|
||||
* be processing this FocusIn after we've changed to a
|
||||
* different workspace; we should therefore update the MRU
|
||||
* list only if the window is actually on the active
|
||||
* workspace.
|
||||
*/
|
||||
if (window->screen->active_workspace &&
|
||||
meta_window_located_on_workspace (window,
|
||||
window->screen->active_workspace))
|
||||
{
|
||||
GList* link;
|
||||
link = g_list_find (window->screen->active_workspace->mru_list,
|
||||
window);
|
||||
g_assert (link);
|
||||
|
||||
window->screen->active_workspace->mru_list =
|
||||
g_list_remove_link (window->screen->active_workspace->mru_list,
|
||||
link);
|
||||
g_list_free (link);
|
||||
|
||||
window->screen->active_workspace->mru_list =
|
||||
g_list_prepend (window->screen->active_workspace->mru_list,
|
||||
window);
|
||||
}
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XInstallColormap (window->display->xdisplay,
|
||||
window->colormap);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* move into FOCUSED_WINDOW layer */
|
||||
meta_window_update_layer (window);
|
||||
|
||||
/* Ungrab click to focus button since the sync grab can interfere
|
||||
* with some things you might do inside the focused window, by
|
||||
* causing the client to get funky enter/leave events.
|
||||
*
|
||||
* The reason we usually have a passive grab on the window is
|
||||
* so that we can intercept clicks and raise the window in
|
||||
* response. For click-to-focus we don't need that since the
|
||||
* focused window is already raised. When raise_on_click is
|
||||
* FALSE we also don't need that since we don't do anything
|
||||
* when the window is clicked.
|
||||
*
|
||||
* There is dicussion in bugs 102209, 115072, and 461577
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
|
||||
!meta_prefs_get_raise_on_click())
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
|
||||
g_signal_emit (window, window_signals[FOCUS], 0);
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
|
||||
if (!window->attached_focus_window)
|
||||
meta_window_appears_focused_changed (window);
|
||||
|
||||
meta_window_propagate_focus_appearance (window, TRUE);
|
||||
}
|
||||
}
|
||||
else if (event->evtype == XI_FocusOut)
|
||||
{
|
||||
if (event->detail == NotifyInferior)
|
||||
{
|
||||
/* This event means the client moved focus to a subwindow */
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus out on %s with NotifyInferior\n",
|
||||
window->desc);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_lost_focus (window);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set _NET_ACTIVE_WINDOW hint */
|
||||
meta_display_update_active_window_hint (window->display);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_property_notify (MetaWindow *window,
|
||||
XPropertyEvent *event)
|
||||
@@ -8271,6 +8381,9 @@ 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)
|
||||
@@ -11003,7 +11116,7 @@ meta_window_get_frame_type (MetaWindow *window)
|
||||
/* can't add border if undecorated */
|
||||
return META_FRAME_TYPE_LAST;
|
||||
}
|
||||
else if (window->border_only ||
|
||||
else if ((window->border_only && base_type != META_FRAME_TYPE_ATTACHED) ||
|
||||
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)) ||
|
||||
(window->hide_titlebar_when_maximized && META_WINDOW_TILED_SIDE_BY_SIDE (window)))
|
||||
{
|
||||
@@ -11150,9 +11263,3 @@ meta_window_compute_tile_match (MetaWindow *window)
|
||||
window->tile_match = match;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_can_close (MetaWindow *window)
|
||||
{
|
||||
return window->has_close_func;
|
||||
}
|
||||
|
@@ -54,6 +54,9 @@ item(WM_WINDOW_ROLE)
|
||||
item(UTF8_STRING)
|
||||
item(WM_ICON_SIZE)
|
||||
item(_KWM_WIN_ICON)
|
||||
item(_MUTTER_RELOAD_THEME_MESSAGE)
|
||||
item(_MUTTER_SET_KEYBINDINGS_MESSAGE)
|
||||
item(_MUTTER_TOGGLE_VERBOSE)
|
||||
item(_MUTTER_HINTS)
|
||||
item(_GTK_THEME_VARIANT)
|
||||
item(_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED)
|
||||
@@ -63,16 +66,12 @@ item(_GTK_APPLICATION_OBJECT_PATH)
|
||||
item(_GTK_WINDOW_OBJECT_PATH)
|
||||
item(_GTK_APP_MENU_OBJECT_PATH)
|
||||
item(_GTK_MENUBAR_OBJECT_PATH)
|
||||
item(_GTK_FRAME_EXTENTS)
|
||||
item(_GNOME_WM_KEYBINDINGS)
|
||||
item(_GNOME_PANEL_ACTION)
|
||||
item(_GNOME_PANEL_ACTION_MAIN_MENU)
|
||||
item(_GNOME_PANEL_ACTION_RUN_DIALOG)
|
||||
item(_MUTTER_TIMESTAMP_PING)
|
||||
item(_MUTTER_FOCUS_SET)
|
||||
item(_MUTTER_SENTINEL)
|
||||
item(_MUTTER_VERSION)
|
||||
item(_MUTTER_PRESENTATION_OUTPUT)
|
||||
item(WM_CLIENT_MACHINE)
|
||||
item(MANAGER)
|
||||
item(TARGETS)
|
||||
@@ -80,7 +79,6 @@ item(MULTIPLE)
|
||||
item(TIMESTAMP)
|
||||
item(VERSION)
|
||||
item(ATOM_PAIR)
|
||||
item(BACKLIGHT)
|
||||
|
||||
/* Oddities: These are used, and we need atoms for them,
|
||||
* but when we need all _NET_WM hints (i.e. when we're making
|
||||
|
@@ -35,6 +35,7 @@
|
||||
|
||||
/* Public compositor API */
|
||||
ClutterActor *meta_get_stage_for_screen (MetaScreen *screen);
|
||||
ClutterActor *meta_get_overlay_group_for_screen (MetaScreen *screen);
|
||||
Window meta_get_overlay_window (MetaScreen *screen);
|
||||
GList *meta_get_window_actors (MetaScreen *screen);
|
||||
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
|
||||
@@ -46,8 +47,5 @@ void meta_enable_unredirect_for_screen (MetaScreen *screen);
|
||||
void meta_set_stage_input_region (MetaScreen *screen,
|
||||
XserverRegion region);
|
||||
void meta_empty_stage_input_region (MetaScreen *screen);
|
||||
void meta_focus_stage_window (MetaScreen *screen,
|
||||
guint32 timestamp);
|
||||
gboolean meta_stage_is_focused (MetaScreen *screen);
|
||||
|
||||
#endif
|
||||
|
@@ -165,10 +165,6 @@ void meta_display_set_input_focus_window (MetaDisplay *display,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_display_request_take_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
/* meta_display_focus_the_no_focus_window is called when the
|
||||
* designated no_focus_window should be focused, but is otherwise the
|
||||
* same as meta_display_set_input_focus_window
|
||||
|
@@ -205,21 +205,6 @@ struct _MetaPluginClass
|
||||
gboolean (*keybinding_filter) (MetaPlugin *plugin,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::confirm_display_config:
|
||||
* @plugin: a #MetaPlugin
|
||||
*
|
||||
* Virtual function called when the display configuration changes.
|
||||
* The common way to implement this function is to show some form
|
||||
* of modal dialog that should ask the user if everything was ok.
|
||||
*
|
||||
* When confirmed by the user, the plugin must call meta_plugin_complete_display_change()
|
||||
* to make the configuration permanent. If that function is not
|
||||
* called within the timeout, the previous configuration will be
|
||||
* reapplied.
|
||||
*/
|
||||
void (*confirm_display_change) (MetaPlugin *plugin);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::plugin_info:
|
||||
* @plugin: a #MetaPlugin
|
||||
@@ -229,7 +214,6 @@ struct _MetaPluginClass
|
||||
* Returns: a #MetaPluginInfo.
|
||||
*/
|
||||
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -376,10 +360,6 @@ void
|
||||
meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok);
|
||||
|
||||
/**
|
||||
* MetaModalOptions:
|
||||
* @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already
|
||||
|
@@ -64,6 +64,7 @@ gint meta_window_actor_get_workspace (MetaWindowActor *self
|
||||
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
|
||||
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
|
||||
gboolean meta_window_actor_is_override_redirect (MetaWindowActor *self);
|
||||
const char * meta_window_actor_get_description (MetaWindowActor *self);
|
||||
gboolean meta_window_actor_showing_on_its_workspace (MetaWindowActor *self);
|
||||
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);
|
||||
|
||||
|
@@ -49,6 +49,7 @@
|
||||
* @META_PREF_TITLEBAR_FONT: title-bar font
|
||||
* @META_PREF_NUM_WORKSPACES: number of workspaces
|
||||
* @META_PREF_DYNAMIC_WORKSPACES: dynamic workspaces
|
||||
* @META_PREF_APPLICATION_BASED: application-based
|
||||
* @META_PREF_KEYBINDINGS: keybindings
|
||||
* @META_PREF_DISABLE_WORKAROUNDS: disable workarounds
|
||||
* @META_PREF_BUTTON_LAYOUT: button layout
|
||||
@@ -87,6 +88,7 @@ typedef enum
|
||||
META_PREF_TITLEBAR_FONT,
|
||||
META_PREF_NUM_WORKSPACES,
|
||||
META_PREF_DYNAMIC_WORKSPACES,
|
||||
META_PREF_APPLICATION_BASED,
|
||||
META_PREF_KEYBINDINGS,
|
||||
META_PREF_DISABLE_WORKAROUNDS,
|
||||
META_PREF_BUTTON_LAYOUT,
|
||||
@@ -134,6 +136,7 @@ const char* meta_prefs_get_theme (void);
|
||||
const PangoFontDescription* meta_prefs_get_titlebar_font (void);
|
||||
int meta_prefs_get_num_workspaces (void);
|
||||
gboolean meta_prefs_get_dynamic_workspaces (void);
|
||||
gboolean meta_prefs_get_application_based (void);
|
||||
gboolean meta_prefs_get_disable_workarounds (void);
|
||||
gboolean meta_prefs_get_auto_raise (void);
|
||||
int meta_prefs_get_auto_raise_delay (void);
|
||||
|
87
src/meta/preview-widget.h
Normal file
87
src/meta/preview-widget.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity theme preview widget */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/common.h>
|
||||
#include <meta/theme.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifndef META_PREVIEW_WIDGET_H
|
||||
#define META_PREVIEW_WIDGET_H
|
||||
|
||||
#define META_TYPE_PREVIEW (meta_preview_get_type ())
|
||||
#define META_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PREVIEW, MetaPreview))
|
||||
#define META_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass))
|
||||
#define META_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PREVIEW))
|
||||
#define META_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW))
|
||||
#define META_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass))
|
||||
|
||||
typedef struct _MetaPreview MetaPreview;
|
||||
typedef struct _MetaPreviewClass MetaPreviewClass;
|
||||
|
||||
struct _MetaPreview
|
||||
{
|
||||
GtkBin bin;
|
||||
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
MetaTheme *theme;
|
||||
char *title;
|
||||
MetaFrameType type;
|
||||
MetaFrameFlags flags;
|
||||
|
||||
PangoLayout *layout;
|
||||
int text_height;
|
||||
|
||||
MetaFrameBorders borders;
|
||||
guint borders_cached : 1;
|
||||
|
||||
MetaButtonLayout button_layout;
|
||||
};
|
||||
|
||||
struct _MetaPreviewClass
|
||||
{
|
||||
/*< private >*/
|
||||
GtkBinClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType meta_preview_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget* meta_preview_new (void);
|
||||
|
||||
void meta_preview_set_theme (MetaPreview *preview,
|
||||
MetaTheme *theme);
|
||||
void meta_preview_set_title (MetaPreview *preview,
|
||||
const char *title);
|
||||
void meta_preview_set_frame_type (MetaPreview *preview,
|
||||
MetaFrameType type);
|
||||
void meta_preview_set_frame_flags (MetaPreview *preview,
|
||||
MetaFrameFlags flags);
|
||||
void meta_preview_set_button_layout (MetaPreview *preview,
|
||||
const MetaButtonLayout *button_layout);
|
||||
|
||||
GdkPixbuf* meta_preview_get_icon (void);
|
||||
GdkPixbuf* meta_preview_get_mini_icon (void);
|
||||
|
||||
#endif
|
@@ -33,7 +33,8 @@
|
||||
typedef struct _MetaTheme MetaTheme;
|
||||
|
||||
MetaTheme* meta_theme_get_current (void);
|
||||
void meta_theme_set_current (const char *name);
|
||||
void meta_theme_set_current (const char *name,
|
||||
gboolean force_reload);
|
||||
|
||||
MetaTheme* meta_theme_new (void);
|
||||
void meta_theme_free (MetaTheme *theme);
|
||||
|
@@ -100,8 +100,7 @@ typedef enum
|
||||
META_DEBUG_RESIZING = 1 << 18,
|
||||
META_DEBUG_SHAPES = 1 << 19,
|
||||
META_DEBUG_COMPOSITOR = 1 << 20,
|
||||
META_DEBUG_EDGE_RESISTANCE = 1 << 21,
|
||||
META_DEBUG_DBUS = 1 << 22
|
||||
META_DEBUG_EDGE_RESISTANCE = 1 << 21
|
||||
} MetaDebugTopic;
|
||||
|
||||
void meta_topic_real (MetaDebugTopic topic,
|
||||
@@ -110,8 +109,6 @@ 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);
|
||||
|
||||
|
@@ -237,6 +237,4 @@ void meta_window_begin_grab_op (MetaWindow *window,
|
||||
gboolean frame_action,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean meta_window_can_close (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
BIN
src/stock_delete.png
Normal file
BIN
src/stock_delete.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 220 B |
BIN
src/stock_maximize.png
Normal file
BIN
src/stock_maximize.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 166 B |
BIN
src/stock_minimize.png
Normal file
BIN
src/stock_minimize.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 145 B |
8
src/tools/.cvsignore
Normal file
8
src/tools/.cvsignore
Normal file
@@ -0,0 +1,8 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
metacity-grayscale
|
||||
metacity-message
|
||||
metacity-mag
|
||||
metacity-properties
|
||||
metacity-properties.desktop
|
||||
metacity-window-demo
|
34
src/tools/Makefile.am
Normal file
34
src/tools/Makefile.am
Normal file
@@ -0,0 +1,34 @@
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
icondir=$(pkgdatadir)/icons
|
||||
icon_DATA=mutter-window-demo.png
|
||||
|
||||
INCLUDES=@MUTTER_WINDOW_DEMO_CFLAGS@ @MUTTER_MESSAGE_CFLAGS@ \
|
||||
-I$(top_srcdir)/src \
|
||||
-DMUTTER_ICON_DIR=\"$(pkgdatadir)/icons\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"
|
||||
|
||||
mutter_message_SOURCES= \
|
||||
mutter-message.c
|
||||
|
||||
mutter_window_demo_SOURCES= \
|
||||
mutter-window-demo.c
|
||||
|
||||
mutter_mag_SOURCES= \
|
||||
mutter-mag.c
|
||||
|
||||
mutter_grayscale_SOURCES= \
|
||||
mutter-grayscale.c
|
||||
|
||||
bin_PROGRAMS=mutter-message mutter-window-demo
|
||||
|
||||
## cheesy hacks I use, don't really have any business existing. ;-)
|
||||
noinst_PROGRAMS=mutter-mag mutter-grayscale
|
||||
|
||||
mutter_message_LDADD= @MUTTER_MESSAGE_LIBS@
|
||||
mutter_window_demo_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
|
||||
mutter_mag_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
|
||||
mutter_grayscale_LDADD = @MUTTER_WINDOW_DEMO_LIBS@
|
||||
|
||||
EXTRA_DIST=$(icon_DATA)
|
||||
|
107
src/tools/mutter-grayscale.c
Normal file
107
src/tools/mutter-grayscale.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* Hack for grayscaling an image */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
|
||||
|
||||
static GdkPixbuf*
|
||||
grayscale_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GdkPixbuf *gray;
|
||||
guchar *pixels;
|
||||
int rowstride;
|
||||
int pixstride;
|
||||
int row;
|
||||
int n_rows;
|
||||
int width;
|
||||
|
||||
gray = gdk_pixbuf_copy (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (gray);
|
||||
pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (gray);
|
||||
n_rows = gdk_pixbuf_get_height (gray);
|
||||
width = gdk_pixbuf_get_width (gray);
|
||||
|
||||
row = 0;
|
||||
while (row < n_rows)
|
||||
{
|
||||
guchar *p = pixels + row * rowstride;
|
||||
guchar *end = p + (pixstride * width);
|
||||
|
||||
while (p != end)
|
||||
{
|
||||
double v = INTENSITY (p[0], p[1], p[2]);
|
||||
|
||||
p[0] = (guchar) v;
|
||||
p[1] = (guchar) v;
|
||||
p[2] = (guchar) v;
|
||||
|
||||
p += pixstride;
|
||||
}
|
||||
|
||||
++row;
|
||||
}
|
||||
|
||||
return gray;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *gray;
|
||||
GError *err;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("specify a single image on the command line\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = NULL;
|
||||
pixbuf = gdk_pixbuf_new_from_file (argv[1], &err);
|
||||
if (err != NULL)
|
||||
{
|
||||
g_printerr ("failed to load image: %s\n", err->message);
|
||||
g_error_free (err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gray = grayscale_pixbuf (pixbuf);
|
||||
|
||||
err = NULL;
|
||||
gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL);
|
||||
if (err != NULL)
|
||||
{
|
||||
g_printerr ("failed to save image: %s\n", err->message);
|
||||
g_error_free (err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_print ("wrote grayscale.png\n");
|
||||
|
||||
return 0;
|
||||
}
|
299
src/tools/mutter-mag.c
Normal file
299
src/tools/mutter-mag.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/* Hack for use instead of xmag */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _XOPEN_SOURCE 600 /* C99 -- for rint() */
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
static GtkWidget *grab_widget = NULL;
|
||||
static GtkWidget *display_window = NULL;
|
||||
static int last_grab_x = 0;
|
||||
static int last_grab_y = 0;
|
||||
static int last_grab_width = 150;
|
||||
static int last_grab_height = 150;
|
||||
static GtkAllocation last_grab_allocation;
|
||||
static double width_factor = 4.0;
|
||||
static double height_factor = 4.0;
|
||||
static GdkInterpType interp_mode = GDK_INTERP_NEAREST;
|
||||
static guint regrab_idle_id = 0;
|
||||
|
||||
static GdkPixbuf*
|
||||
get_pixbuf (void)
|
||||
{
|
||||
GdkPixbuf *screenshot;
|
||||
GdkPixbuf *magnified;
|
||||
|
||||
#if 0
|
||||
g_print ("Size %d x %d\n",
|
||||
last_grab_width, last_grab_height);
|
||||
#endif
|
||||
|
||||
screenshot = gdk_pixbuf_get_from_window (gdk_get_default_root_window (),
|
||||
last_grab_x, last_grab_y,
|
||||
last_grab_width, last_grab_height);
|
||||
|
||||
if (screenshot == NULL)
|
||||
{
|
||||
g_printerr ("Screenshot failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor,
|
||||
last_grab_height * height_factor,
|
||||
interp_mode);
|
||||
|
||||
|
||||
g_object_unref (G_OBJECT (screenshot));
|
||||
|
||||
return magnified;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
regrab_idle (GtkWidget *image)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
GdkPixbuf *magnified;
|
||||
|
||||
gtk_widget_get_allocation (image, &allocation);
|
||||
|
||||
if (allocation.width != last_grab_allocation.width ||
|
||||
allocation.height != last_grab_allocation.height)
|
||||
{
|
||||
last_grab_width = rint (allocation.width / width_factor);
|
||||
last_grab_height = rint (allocation.height / height_factor);
|
||||
last_grab_allocation = allocation;
|
||||
|
||||
magnified = get_pixbuf ();
|
||||
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified);
|
||||
|
||||
g_object_unref (G_OBJECT (magnified));
|
||||
}
|
||||
|
||||
regrab_idle_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
image_resized (GtkWidget *image)
|
||||
{
|
||||
if (regrab_idle_id == 0)
|
||||
regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle,
|
||||
image, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
grab_area_at_mouse (GtkWidget *invisible,
|
||||
int x_root,
|
||||
int y_root)
|
||||
{
|
||||
GdkPixbuf *magnified;
|
||||
int width, height;
|
||||
GtkWidget *widget;
|
||||
|
||||
width = last_grab_width;
|
||||
height = last_grab_height;
|
||||
|
||||
last_grab_x = x_root;
|
||||
last_grab_y = y_root;
|
||||
last_grab_width = width;
|
||||
last_grab_height = height;
|
||||
|
||||
magnified = get_pixbuf ();
|
||||
|
||||
display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (display_window),
|
||||
last_grab_width, last_grab_height);
|
||||
widget = gtk_image_new_from_pixbuf (magnified);
|
||||
gtk_widget_set_size_request (widget, 40, 40);
|
||||
gtk_container_add (GTK_CONTAINER (display_window), widget);
|
||||
g_object_unref (G_OBJECT (magnified));
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (display_window),
|
||||
(gpointer) &display_window);
|
||||
|
||||
g_signal_connect (G_OBJECT (display_window), "destroy",
|
||||
G_CALLBACK (gtk_main_quit), NULL);
|
||||
|
||||
g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL);
|
||||
|
||||
gtk_widget_show_all (display_window);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_grab (void)
|
||||
{
|
||||
GdkDeviceManager *manager;
|
||||
GdkDevice *device;
|
||||
|
||||
manager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
device = gdk_device_manager_get_client_pointer (manager);
|
||||
|
||||
gdk_device_ungrab (device, gtk_get_current_event_time ());
|
||||
gdk_device_ungrab (gdk_device_get_associated_device (device),
|
||||
gtk_get_current_event_time ());
|
||||
gtk_grab_remove (grab_widget);
|
||||
}
|
||||
|
||||
static void
|
||||
mouse_motion (GtkWidget *invisible,
|
||||
GdkEventMotion *event,
|
||||
gpointer data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mouse_release (GtkWidget *invisible,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (event->button != 1)
|
||||
return FALSE;
|
||||
|
||||
grab_area_at_mouse (invisible, event->x_root, event->y_root);
|
||||
|
||||
shutdown_grab ();
|
||||
|
||||
g_signal_handlers_disconnect_by_func (invisible, mouse_motion, NULL);
|
||||
g_signal_handlers_disconnect_by_func (invisible, mouse_release, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Helper Functions */
|
||||
|
||||
static gboolean mouse_press (GtkWidget *invisible,
|
||||
GdkEventButton *event,
|
||||
gpointer data);
|
||||
|
||||
static gboolean
|
||||
key_press (GtkWidget *invisible,
|
||||
GdkEventKey *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (event->keyval == GDK_KEY_Escape)
|
||||
{
|
||||
shutdown_grab ();
|
||||
|
||||
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
|
||||
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
|
||||
|
||||
gtk_main_quit ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mouse_press (GtkWidget *invisible,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (event->type == GDK_BUTTON_PRESS &&
|
||||
event->button == 1)
|
||||
{
|
||||
g_signal_connect (invisible, "motion_notify_event",
|
||||
G_CALLBACK (mouse_motion), NULL);
|
||||
g_signal_connect (invisible, "button_release_event",
|
||||
G_CALLBACK (mouse_release), NULL);
|
||||
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
|
||||
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
begin_area_grab (void)
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkDeviceManager *manager;
|
||||
GdkDevice *device;
|
||||
|
||||
if (grab_widget == NULL)
|
||||
{
|
||||
grab_widget = gtk_invisible_new ();
|
||||
|
||||
gtk_widget_add_events (grab_widget,
|
||||
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
|
||||
|
||||
gtk_widget_show (grab_widget);
|
||||
}
|
||||
|
||||
window = gtk_widget_get_window (grab_widget);
|
||||
manager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
device = gdk_device_manager_get_client_pointer (manager);
|
||||
|
||||
if (gdk_device_grab (device,
|
||||
window,
|
||||
GDK_OWNERSHIP_NONE,
|
||||
FALSE,
|
||||
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
|
||||
NULL,
|
||||
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
|
||||
{
|
||||
g_warning ("Failed to grab pointer to do eyedropper");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gdk_device_grab (gdk_device_get_associated_device (device),
|
||||
window,
|
||||
GDK_OWNERSHIP_NONE,
|
||||
FALSE,
|
||||
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
|
||||
NULL,
|
||||
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
|
||||
{
|
||||
gdk_device_ungrab (device, gtk_get_current_event_time ());
|
||||
g_warning ("Failed to grab keyboard to do eyedropper");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_grab_add (grab_widget);
|
||||
|
||||
g_signal_connect (grab_widget, "button_press_event",
|
||||
G_CALLBACK (mouse_press), NULL);
|
||||
g_signal_connect (grab_widget, "key_press_event",
|
||||
G_CALLBACK (key_press), NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
begin_area_grab ();
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
160
src/tools/mutter-message.c
Normal file
160
src/tools/mutter-message.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/* Mutter send-magic-messages app */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
#define N_(x) x
|
||||
|
||||
static Display *display;
|
||||
|
||||
static void
|
||||
send_reload_theme (void)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.display = display;
|
||||
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
|
||||
xev.xclient.message_type = XInternAtom (display,
|
||||
"_MUTTER_RELOAD_THEME_MESSAGE",
|
||||
False);
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 0;
|
||||
xev.xclient.data.l[1] = 0;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
|
||||
XSendEvent (display,
|
||||
gdk_x11_get_default_root_xwindow (),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
|
||||
XFlush (display);
|
||||
XSync (display, False);
|
||||
}
|
||||
|
||||
static void
|
||||
send_set_keybindings (gboolean enabled)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.display = display;
|
||||
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
|
||||
xev.xclient.message_type = XInternAtom (display,
|
||||
"_MUTTER_SET_KEYBINDINGS_MESSAGE",
|
||||
False);
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = enabled;
|
||||
xev.xclient.data.l[1] = 0;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
|
||||
XSendEvent (display,
|
||||
gdk_x11_get_default_root_xwindow (),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
|
||||
XFlush (display);
|
||||
XSync (display, False);
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static void
|
||||
send_toggle_verbose (void)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.display = display;
|
||||
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
|
||||
xev.xclient.message_type = XInternAtom (display,
|
||||
"_MUTTER_TOGGLE_VERBOSE",
|
||||
False);
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 0;
|
||||
xev.xclient.data.l[1] = 0;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
|
||||
XSendEvent (display,
|
||||
gdk_x11_get_default_root_xwindow (),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
|
||||
XFlush (display);
|
||||
XSync (display, False);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
g_printerr (_("Usage: %s\n"),
|
||||
"mutter-message (reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
if (argc < 2)
|
||||
usage ();
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
if (strcmp (argv[1], "reload-theme") == 0)
|
||||
send_reload_theme ();
|
||||
else if (strcmp (argv[1], "enable-keybindings") == 0)
|
||||
send_set_keybindings (TRUE);
|
||||
else if (strcmp (argv[1], "disable-keybindings") == 0)
|
||||
send_set_keybindings (FALSE);
|
||||
else if (strcmp (argv[1], "toggle-verbose") == 0)
|
||||
{
|
||||
#ifndef WITH_VERBOSE_MODE
|
||||
g_printerr (_("Mutter was compiled without support for verbose mode\n"));
|
||||
return 1;
|
||||
#else
|
||||
send_toggle_verbose ();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
usage ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1049
src/tools/mutter-window-demo.c
Normal file
1049
src/tools/mutter-window-demo.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/tools/mutter-window-demo.png
Normal file
BIN
src/tools/mutter-window-demo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
112
src/ui/frames.c
112
src/ui/frames.c
@@ -739,6 +739,22 @@ meta_ui_frame_get_corner_radiuses (MetaFrames *frames,
|
||||
*bottom_right = fgeom.bottom_right_corner_rounded_radius + sqrt(fgeom.bottom_right_corner_rounded_radius);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_get_corner_radiuses (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right)
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
|
||||
frame = meta_frames_lookup_window (frames, xwindow);
|
||||
|
||||
meta_ui_frame_get_corner_radiuses (frames, frame, top_left, top_right,
|
||||
bottom_left, bottom_right);
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_reset_bg (MetaFrames *frames,
|
||||
Window xwindow)
|
||||
@@ -1835,102 +1851,6 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
|
||||
cairo_region_destroy (frame_border);
|
||||
}
|
||||
|
||||
#define TAU (2*M_PI)
|
||||
|
||||
/*
|
||||
* Draw the opaque and semi-opaque pixels of this frame into a mask.
|
||||
*
|
||||
* (0,0) in Cairo coordinates is assumed to be the top left corner of the
|
||||
* invisible border.
|
||||
*
|
||||
* The parts of @cr's surface in the clip region are assumed to be
|
||||
* initialized to fully-transparent, and the clip region is assumed to
|
||||
* contain the invisible border and the visible parts of the frame, but
|
||||
* not the client area.
|
||||
*
|
||||
* This function uses @cr to draw pixels of arbitrary color (it will
|
||||
* typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is
|
||||
* discarded anyway) with appropriate alpha values to reproduce this
|
||||
* frame's alpha channel, as a mask to be applied to an opaque pixmap.
|
||||
*
|
||||
* @frame: This frame
|
||||
* @xwindow: The X window for the frame, which has the client window as a child
|
||||
* @width: The width of the framed window including any invisible borders
|
||||
* @height: The height of the framed window including any invisible borders
|
||||
* @cr: Used to draw the resulting mask
|
||||
*/
|
||||
void
|
||||
meta_frames_get_mask (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
guint width,
|
||||
guint height,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
|
||||
float top_left, top_right, bottom_left, bottom_right;
|
||||
int x, y;
|
||||
MetaFrameBorders borders;
|
||||
|
||||
if (frame == NULL)
|
||||
meta_bug ("No such frame 0x%lx\n", xwindow);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
meta_ui_frame_get_borders (frames, frame, &borders);
|
||||
meta_ui_frame_get_corner_radiuses (frames, frame,
|
||||
&top_left, &top_right,
|
||||
&bottom_left, &bottom_right);
|
||||
|
||||
/* top left */
|
||||
x = borders.invisible.left;
|
||||
y = borders.invisible.top;
|
||||
|
||||
cairo_arc (cr,
|
||||
x + top_left,
|
||||
y + top_left,
|
||||
top_left,
|
||||
2 * TAU / 4,
|
||||
3 * TAU / 4);
|
||||
|
||||
/* top right */
|
||||
x = width - borders.invisible.right - top_right;
|
||||
y = borders.invisible.top;
|
||||
|
||||
cairo_arc (cr,
|
||||
x,
|
||||
y + top_right,
|
||||
top_right,
|
||||
3 * TAU / 4,
|
||||
4 * TAU / 4);
|
||||
|
||||
/* bottom right */
|
||||
x = width - borders.invisible.right - bottom_right;
|
||||
y = height - borders.invisible.bottom - bottom_right;
|
||||
|
||||
cairo_arc (cr,
|
||||
x,
|
||||
y,
|
||||
bottom_right,
|
||||
0 * TAU / 4,
|
||||
1 * TAU / 4);
|
||||
|
||||
/* bottom left */
|
||||
x = borders.invisible.left;
|
||||
y = height - borders.invisible.bottom - bottom_left;
|
||||
|
||||
cairo_arc (cr,
|
||||
x + bottom_left,
|
||||
y,
|
||||
bottom_left,
|
||||
1 * TAU / 4,
|
||||
2 * TAU / 4);
|
||||
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_frames_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
|
@@ -140,11 +140,12 @@ cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
|
||||
int window_width,
|
||||
int window_height);
|
||||
|
||||
void meta_frames_get_mask (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
guint width,
|
||||
guint height,
|
||||
cairo_t *cr);
|
||||
void meta_frames_get_corner_radiuses (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right);
|
||||
|
||||
void meta_frames_move_resize_frame (MetaFrames *frames,
|
||||
Window xwindow,
|
||||
|
@@ -40,6 +40,7 @@ typedef enum
|
||||
{
|
||||
MENU_ITEM_SEPARATOR = 0,
|
||||
MENU_ITEM_NORMAL,
|
||||
MENU_ITEM_IMAGE,
|
||||
MENU_ITEM_CHECKBOX,
|
||||
MENU_ITEM_RADIOBUTTON,
|
||||
MENU_ITEM_WORKSPACE_LIST,
|
||||
@@ -49,6 +50,7 @@ struct _MenuItem
|
||||
{
|
||||
MetaMenuOp op;
|
||||
MetaMenuItemType type;
|
||||
const char *stock_id;
|
||||
const gboolean checked;
|
||||
const char *label;
|
||||
};
|
||||
@@ -64,42 +66,42 @@ static void activate_cb (GtkWidget *menuitem, gpointer data);
|
||||
|
||||
static MenuItem menuitems[] = {
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
|
||||
{ META_MENU_OP_MINIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
|
||||
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
|
||||
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Unma_ximize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
|
||||
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Roll _Up") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
|
||||
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Unroll") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
|
||||
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Move") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
|
||||
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Resize") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
|
||||
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
|
||||
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move Titlebar On_screen") },
|
||||
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
|
||||
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, NULL, FALSE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
|
||||
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, NULL, TRUE, N_("Always on _Top") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Always on Visible Workspace") },
|
||||
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Always on Visible Workspace") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Only on This Workspace") },
|
||||
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Only on This Workspace") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Left") },
|
||||
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Left") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace R_ight") },
|
||||
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace R_ight") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Up") },
|
||||
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Up") },
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Down") },
|
||||
{ 0, MENU_ITEM_WORKSPACE_LIST, FALSE, NULL },
|
||||
{ 0, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
|
||||
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Down") },
|
||||
{ 0, MENU_ITEM_WORKSPACE_LIST, NULL, FALSE, NULL },
|
||||
{ 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
|
||||
/* Translators: Translate this string the same way as you do in libwnck! */
|
||||
{ META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
|
||||
{ META_MENU_OP_DELETE, MENU_ITEM_IMAGE, METACITY_STOCK_DELETE, FALSE, N_("_Close") }
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -272,6 +274,16 @@ menu_item_new (MenuItem *menuitem, int workspace_id)
|
||||
{
|
||||
mi = gtk_menu_item_new ();
|
||||
}
|
||||
else if (menuitem->type == MENU_ITEM_IMAGE)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new_from_stock (menuitem->stock_id, GTK_ICON_SIZE_MENU);
|
||||
mi = gtk_image_menu_item_new ();
|
||||
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
|
||||
gtk_widget_show (image);
|
||||
}
|
||||
else if (menuitem->type == MENU_ITEM_CHECKBOX)
|
||||
{
|
||||
mi = gtk_check_menu_item_new ();
|
||||
@@ -380,7 +392,8 @@ meta_window_menu_new (MetaFrames *frames,
|
||||
int j;
|
||||
|
||||
MenuItem to_another_workspace = {
|
||||
0, MENU_ITEM_NORMAL, FALSE,
|
||||
0, MENU_ITEM_NORMAL,
|
||||
NULL, FALSE,
|
||||
N_("Move to Another _Workspace")
|
||||
};
|
||||
|
||||
|
@@ -27,6 +27,11 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include "frames.h"
|
||||
|
||||
/* Stock icons */
|
||||
#define METACITY_STOCK_DELETE "metacity-delete"
|
||||
#define METACITY_STOCK_MINIMIZE "metacity-minimize"
|
||||
#define METACITY_STOCK_MAXIMIZE "metacity-maximize"
|
||||
|
||||
struct _MetaWindowMenu
|
||||
{
|
||||
MetaFrames *frames;
|
||||
|
496
src/ui/preview-widget.c
Normal file
496
src/ui/preview-widget.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SECTION:preview-widget
|
||||
* @title: MetaPreview
|
||||
* @short_description: Mutter theme preview widget
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _XOPEN_SOURCE 600 /* for the maths routines over floats */
|
||||
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <meta/preview-widget.h>
|
||||
#include "theme-private.h"
|
||||
|
||||
static void meta_preview_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum,
|
||||
gint *natural);
|
||||
static void meta_preview_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum,
|
||||
gint *natural);
|
||||
static void meta_preview_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static gboolean meta_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
static void meta_preview_realize (GtkWidget *widget);
|
||||
static void meta_preview_dispose (GObject *object);
|
||||
static void meta_preview_finalize (GObject *object);
|
||||
|
||||
G_DEFINE_TYPE (MetaPreview, meta_preview, GTK_TYPE_BIN);
|
||||
|
||||
static void
|
||||
meta_preview_class_init (MetaPreviewClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
|
||||
gobject_class->dispose = meta_preview_dispose;
|
||||
gobject_class->finalize = meta_preview_finalize;
|
||||
|
||||
widget_class->realize = meta_preview_realize;
|
||||
widget_class->draw = meta_preview_draw;
|
||||
widget_class->get_preferred_width = meta_preview_get_preferred_width;
|
||||
widget_class->get_preferred_height = meta_preview_get_preferred_height;
|
||||
widget_class->size_allocate = meta_preview_size_allocate;
|
||||
|
||||
gtk_container_class_handle_border_width (GTK_CONTAINER_CLASS (class));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_init (MetaPreview *preview)
|
||||
{
|
||||
int i;
|
||||
|
||||
gtk_widget_set_has_window (GTK_WIDGET (preview), FALSE);
|
||||
|
||||
i = 0;
|
||||
while (i < MAX_BUTTONS_PER_CORNER)
|
||||
{
|
||||
preview->button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
|
||||
preview->button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
|
||||
++i;
|
||||
}
|
||||
|
||||
preview->button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
|
||||
|
||||
preview->button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
|
||||
preview->button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
|
||||
preview->button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
|
||||
|
||||
preview->type = META_FRAME_TYPE_NORMAL;
|
||||
preview->flags =
|
||||
META_FRAME_ALLOWS_DELETE |
|
||||
META_FRAME_ALLOWS_MENU |
|
||||
META_FRAME_ALLOWS_MINIMIZE |
|
||||
META_FRAME_ALLOWS_MAXIMIZE |
|
||||
META_FRAME_ALLOWS_VERTICAL_RESIZE |
|
||||
META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
|
||||
META_FRAME_HAS_FOCUS |
|
||||
META_FRAME_ALLOWS_SHADE |
|
||||
META_FRAME_ALLOWS_MOVE;
|
||||
|
||||
preview->borders_cached = FALSE;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
meta_preview_new (void)
|
||||
{
|
||||
MetaPreview *preview;
|
||||
|
||||
preview = g_object_new (META_TYPE_PREVIEW, NULL);
|
||||
|
||||
return GTK_WIDGET (preview);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_dispose (GObject *object)
|
||||
{
|
||||
MetaPreview *preview = META_PREVIEW (object);
|
||||
|
||||
g_clear_object (&preview->style_context);
|
||||
|
||||
G_OBJECT_CLASS (meta_preview_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_finalize (GObject *object)
|
||||
{
|
||||
MetaPreview *preview;
|
||||
|
||||
preview = META_PREVIEW (object);
|
||||
|
||||
g_free (preview->title);
|
||||
preview->title = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_preview_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_info (MetaPreview *preview)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = GTK_WIDGET (preview);
|
||||
|
||||
if (preview->layout == NULL)
|
||||
{
|
||||
PangoFontDescription *font_desc;
|
||||
double scale;
|
||||
PangoAttrList *attrs;
|
||||
PangoAttribute *attr;
|
||||
|
||||
if (preview->theme)
|
||||
scale = meta_theme_get_title_scale (preview->theme,
|
||||
preview->type,
|
||||
preview->flags);
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
preview->layout = gtk_widget_create_pango_layout (widget,
|
||||
preview->title);
|
||||
|
||||
font_desc = meta_gtk_widget_get_font_desc (widget, scale, NULL);
|
||||
|
||||
preview->text_height =
|
||||
meta_pango_font_desc_get_text_height (font_desc,
|
||||
gtk_widget_get_pango_context (widget));
|
||||
|
||||
attrs = pango_attr_list_new ();
|
||||
|
||||
attr = pango_attr_size_new (pango_font_description_get_size (font_desc));
|
||||
attr->start_index = 0;
|
||||
attr->end_index = G_MAXINT;
|
||||
|
||||
pango_attr_list_insert (attrs, attr);
|
||||
|
||||
pango_layout_set_attributes (preview->layout, attrs);
|
||||
|
||||
pango_attr_list_unref (attrs);
|
||||
|
||||
pango_font_description_free (font_desc);
|
||||
}
|
||||
|
||||
if (!preview->borders_cached)
|
||||
{
|
||||
if (preview->theme)
|
||||
meta_theme_get_frame_borders (preview->theme,
|
||||
preview->type,
|
||||
preview->text_height,
|
||||
preview->flags,
|
||||
&preview->borders);
|
||||
else
|
||||
meta_frame_borders_clear (&preview->borders);
|
||||
preview->borders_cached = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaPreview *preview = META_PREVIEW (widget);
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (preview->theme)
|
||||
{
|
||||
int client_width;
|
||||
int client_height;
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
|
||||
{
|
||||
META_BUTTON_STATE_NORMAL,
|
||||
META_BUTTON_STATE_NORMAL,
|
||||
META_BUTTON_STATE_NORMAL,
|
||||
META_BUTTON_STATE_NORMAL
|
||||
};
|
||||
|
||||
ensure_info (preview);
|
||||
cairo_save (cr);
|
||||
|
||||
client_width = allocation.width - preview->borders.total.left - preview->borders.total.right;
|
||||
client_height = allocation.height - preview->borders.total.top - preview->borders.total.bottom;
|
||||
|
||||
if (client_width < 0)
|
||||
client_width = 1;
|
||||
if (client_height < 0)
|
||||
client_height = 1;
|
||||
|
||||
meta_theme_draw_frame (preview->theme,
|
||||
preview->style_context,
|
||||
cr,
|
||||
preview->type,
|
||||
preview->flags,
|
||||
client_width, client_height,
|
||||
preview->layout,
|
||||
preview->text_height,
|
||||
&preview->button_layout,
|
||||
button_states,
|
||||
meta_preview_get_mini_icon (),
|
||||
meta_preview_get_icon ());
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
/* draw child */
|
||||
return GTK_WIDGET_CLASS (meta_preview_parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_realize (GtkWidget *widget)
|
||||
{
|
||||
MetaPreview *preview = META_PREVIEW (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (meta_preview_parent_class)->realize (widget);
|
||||
|
||||
preview->style_context = meta_theme_create_style_context (gtk_widget_get_screen (widget),
|
||||
NULL);
|
||||
}
|
||||
|
||||
#define NO_CHILD_WIDTH 80
|
||||
#define NO_CHILD_HEIGHT 20
|
||||
|
||||
static void
|
||||
meta_preview_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum,
|
||||
gint *natural)
|
||||
{
|
||||
MetaPreview *preview;
|
||||
GtkWidget *child;
|
||||
|
||||
preview = META_PREVIEW (widget);
|
||||
|
||||
ensure_info (preview);
|
||||
|
||||
*minimum = *natural = preview->borders.total.left + preview->borders.total.right;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (preview));
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
|
||||
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
|
||||
|
||||
*minimum += child_min;
|
||||
*natural += child_nat;
|
||||
}
|
||||
else
|
||||
{
|
||||
*minimum += NO_CHILD_WIDTH;
|
||||
*natural += NO_CHILD_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum,
|
||||
gint *natural)
|
||||
{
|
||||
MetaPreview *preview;
|
||||
GtkWidget *child;
|
||||
|
||||
preview = META_PREVIEW (widget);
|
||||
|
||||
ensure_info (preview);
|
||||
|
||||
*minimum = *natural = preview->borders.total.top + preview->borders.total.bottom;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (preview));
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
|
||||
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
|
||||
|
||||
*minimum += child_min;
|
||||
*natural += child_nat;
|
||||
}
|
||||
else
|
||||
{
|
||||
*minimum += NO_CHILD_HEIGHT;
|
||||
*natural += NO_CHILD_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_preview_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
MetaPreview *preview;
|
||||
GtkAllocation widget_allocation, child_allocation;
|
||||
GtkWidget *child;
|
||||
|
||||
preview = META_PREVIEW (widget);
|
||||
|
||||
ensure_info (preview);
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (widget));
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_get_allocation (widget, &widget_allocation);
|
||||
child_allocation.x = widget_allocation.x + preview->borders.total.left;
|
||||
child_allocation.y = widget_allocation.y + preview->borders.total.top;
|
||||
|
||||
child_allocation.width = MAX (1, widget_allocation.width - preview->borders.total.left - preview->borders.total.right);
|
||||
child_allocation.height = MAX (1, widget_allocation.height - preview->borders.total.top - preview->borders.total.bottom);
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_cache (MetaPreview *preview)
|
||||
{
|
||||
if (preview->layout)
|
||||
{
|
||||
g_object_unref (G_OBJECT (preview->layout));
|
||||
preview->layout = NULL;
|
||||
}
|
||||
|
||||
preview->borders_cached = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_preview_set_theme (MetaPreview *preview,
|
||||
MetaTheme *theme)
|
||||
{
|
||||
g_return_if_fail (META_IS_PREVIEW (preview));
|
||||
|
||||
preview->theme = theme;
|
||||
|
||||
clear_cache (preview);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
void
|
||||
meta_preview_set_title (MetaPreview *preview,
|
||||
const char *title)
|
||||
{
|
||||
g_return_if_fail (META_IS_PREVIEW (preview));
|
||||
|
||||
g_free (preview->title);
|
||||
preview->title = g_strdup (title);
|
||||
|
||||
clear_cache (preview);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
void
|
||||
meta_preview_set_frame_type (MetaPreview *preview,
|
||||
MetaFrameType type)
|
||||
{
|
||||
g_return_if_fail (META_IS_PREVIEW (preview));
|
||||
|
||||
preview->type = type;
|
||||
|
||||
clear_cache (preview);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
void
|
||||
meta_preview_set_frame_flags (MetaPreview *preview,
|
||||
MetaFrameFlags flags)
|
||||
{
|
||||
g_return_if_fail (META_IS_PREVIEW (preview));
|
||||
|
||||
preview->flags = flags;
|
||||
|
||||
clear_cache (preview);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
void
|
||||
meta_preview_set_button_layout (MetaPreview *preview,
|
||||
const MetaButtonLayout *button_layout)
|
||||
{
|
||||
g_return_if_fail (META_IS_PREVIEW (preview));
|
||||
|
||||
preview->button_layout = *button_layout;
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (preview));
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_preview_get_icon (void)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"gtk-missing-image",
|
||||
META_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_preview_get_mini_icon (void)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
gboolean icon_exists;
|
||||
|
||||
theme = gtk_icon_theme_get_default ();
|
||||
|
||||
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
|
||||
|
||||
if (icon_exists)
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
META_DEFAULT_ICON_NAME,
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
else
|
||||
default_icon = gtk_icon_theme_load_icon (theme,
|
||||
"gtk-missing-image",
|
||||
META_MINI_ICON_WIDTH,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return default_icon;
|
||||
}
|
@@ -857,7 +857,10 @@ meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||
WnckWindowDisplayInfo wnck_window;
|
||||
wnck_window.icon = window->icon;
|
||||
wnck_window.mini_icon = window->mini_icon;
|
||||
wnck_window.is_active = window->has_focus;
|
||||
|
||||
wnck_window.is_active = FALSE;
|
||||
if (window == window->display->expected_focus_window)
|
||||
wnck_window.is_active = TRUE;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
|
1365
src/ui/theme-viewer.c
Normal file
1365
src/ui/theme-viewer.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1880,7 +1880,7 @@ debug_print_tokens (PosToken *tokens,
|
||||
/**
|
||||
* pos_tokenize:
|
||||
* @expr: The expression
|
||||
* @tokens_p: (out): The resulting tokens
|
||||
* @tokens_p: (out) The resulting tokens
|
||||
* @n_tokens_p: (out): The number of resulting tokens
|
||||
* @err: (out): set to the problem if there was a problem
|
||||
|
||||
@@ -5063,14 +5063,16 @@ meta_theme_get_current (void)
|
||||
}
|
||||
|
||||
void
|
||||
meta_theme_set_current (const char *name)
|
||||
meta_theme_set_current (const char *name,
|
||||
gboolean force_reload)
|
||||
{
|
||||
MetaTheme *new_theme;
|
||||
GError *err;
|
||||
|
||||
meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
|
||||
|
||||
if (meta_current_theme &&
|
||||
if (!force_reload &&
|
||||
meta_current_theme &&
|
||||
strcmp (name, meta_current_theme->name) == 0)
|
||||
return;
|
||||
|
||||
|
76
src/ui/ui.c
76
src/ui/ui.c
@@ -4,6 +4,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Havoc Pennington
|
||||
* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -30,10 +31,13 @@
|
||||
#include "core.h"
|
||||
#include "theme-private.h"
|
||||
|
||||
#include "inlinepixbufs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <cairo-xlib.h>
|
||||
|
||||
static void meta_stock_icons_init (void);
|
||||
static void meta_ui_accelerator_parse (const char *accel,
|
||||
guint *keysym,
|
||||
guint *keycode,
|
||||
@@ -58,6 +62,8 @@ 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*
|
||||
@@ -318,16 +324,6 @@ meta_ui_free (MetaUI *ui)
|
||||
g_free (ui);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_get_frame_mask (MetaUI *ui,
|
||||
Window frame_xwindow,
|
||||
guint width,
|
||||
guint height,
|
||||
cairo_t *cr)
|
||||
{
|
||||
meta_frames_get_mask (ui->frames, frame_xwindow, width, height, cr);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_get_frame_borders (MetaUI *ui,
|
||||
Window frame_xwindow,
|
||||
@@ -337,6 +333,19 @@ meta_ui_get_frame_borders (MetaUI *ui,
|
||||
borders);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_get_corner_radiuses (MetaUI *ui,
|
||||
Window xwindow,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right)
|
||||
{
|
||||
meta_frames_get_corner_radiuses (ui->frames, xwindow,
|
||||
top_left, top_right,
|
||||
bottom_left, bottom_right);
|
||||
}
|
||||
|
||||
Window
|
||||
meta_ui_create_frame_window (MetaUI *ui,
|
||||
Display *xdisplay,
|
||||
@@ -769,9 +778,10 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_set_current_theme (const char *name)
|
||||
meta_ui_set_current_theme (const char *name,
|
||||
gboolean force_reload)
|
||||
{
|
||||
meta_theme_set_current (name);
|
||||
meta_theme_set_current (name, force_reload);
|
||||
meta_invalidate_default_icons ();
|
||||
}
|
||||
|
||||
@@ -991,6 +1001,48 @@ meta_ui_window_is_widget (MetaUI *ui,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> */
|
||||
typedef struct
|
||||
{
|
||||
char *stock_id;
|
||||
const guint8 *icon_data;
|
||||
} MetaStockIcon;
|
||||
|
||||
static void
|
||||
meta_stock_icons_init (void)
|
||||
{
|
||||
GtkIconFactory *factory;
|
||||
int i;
|
||||
|
||||
MetaStockIcon items[] =
|
||||
{
|
||||
{ METACITY_STOCK_DELETE, stock_delete_data },
|
||||
{ METACITY_STOCK_MINIMIZE, stock_minimize_data },
|
||||
{ METACITY_STOCK_MAXIMIZE, stock_maximize_data }
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new ();
|
||||
gtk_icon_factory_add_default (factory);
|
||||
|
||||
for (i = 0; i < (gint) G_N_ELEMENTS (items); i++)
|
||||
{
|
||||
GtkIconSet *icon_set;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_inline (-1, items[i].icon_data,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
|
||||
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
|
||||
gtk_icon_set_unref (icon_set);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (factory));
|
||||
}
|
||||
|
||||
int
|
||||
meta_ui_get_drag_threshold (MetaUI *ui)
|
||||
{
|
||||
|
17
src/ui/ui.h
17
src/ui/ui.h
@@ -66,13 +66,6 @@ void meta_ui_theme_get_frame_borders (MetaUI *ui,
|
||||
void meta_ui_get_frame_borders (MetaUI *ui,
|
||||
Window frame_xwindow,
|
||||
MetaFrameBorders *borders);
|
||||
|
||||
void meta_ui_get_frame_mask (MetaUI *ui,
|
||||
Window frame_xwindow,
|
||||
guint width,
|
||||
guint height,
|
||||
cairo_t *cr);
|
||||
|
||||
Window meta_ui_create_frame_window (MetaUI *ui,
|
||||
Display *xdisplay,
|
||||
Visual *xvisual,
|
||||
@@ -109,6 +102,13 @@ cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
|
||||
int window_width,
|
||||
int window_height);
|
||||
|
||||
void meta_ui_get_corner_radiuses (MetaUI *ui,
|
||||
Window xwindow,
|
||||
float *top_left,
|
||||
float *top_right,
|
||||
float *bottom_left,
|
||||
float *bottom_right);
|
||||
|
||||
void meta_ui_queue_frame_draw (MetaUI *ui,
|
||||
Window xwindow);
|
||||
|
||||
@@ -154,7 +154,8 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
char* meta_text_property_to_utf8 (Display *xdisplay,
|
||||
const XTextProperty *prop);
|
||||
|
||||
void meta_ui_set_current_theme (const char *name);
|
||||
void meta_ui_set_current_theme (const char *name,
|
||||
gboolean force_reload);
|
||||
gboolean meta_ui_have_a_theme (void);
|
||||
|
||||
/* Not a real key symbol but means "key above the tab key"; this is
|
||||
|
7
src/wm-tester/.cvsignore
Normal file
7
src/wm-tester/.cvsignore
Normal file
@@ -0,0 +1,7 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
focus-window
|
||||
test-gravity
|
||||
test-resizing
|
||||
wm-tester
|
||||
test-size-hints
|
29
src/wm-tester/Makefile.am
Normal file
29
src/wm-tester/Makefile.am
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
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
|
||||
|
||||
noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window test-size-hints test-attached
|
||||
|
||||
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@
|
37
src/wm-tester/focus-window.c
Normal file
37
src/wm-tester/focus-window.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#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;
|
||||
}
|
||||
|
245
src/wm-tester/main.c
Normal file
245
src/wm-tester/main.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* 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;
|
||||
}
|
||||
}
|
100
src/wm-tester/test-attached.c
Normal file
100
src/wm-tester/test-attached.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#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;
|
||||
}
|
308
src/wm-tester/test-gravity.c
Normal file
308
src/wm-tester/test-gravity.c
Normal file
@@ -0,0 +1,308 @@
|
||||
#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.
|
||||
*/
|
||||
}
|
||||
|
257
src/wm-tester/test-resizing.c
Normal file
257
src/wm-tester/test-resizing.c
Normal file
@@ -0,0 +1,257 @@
|
||||
#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.
|
||||
*/
|
||||
}
|
||||
|
136
src/wm-tester/test-size-hints.c
Normal file
136
src/wm-tester/test-size-hints.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#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
281
src/xrandr.xml
@@ -1,281 +0,0 @@
|
||||
<!DOCTYPE node PUBLIC
|
||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
|
||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
|
||||
<node>
|
||||
<!--
|
||||
org.gnome.Mutter.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