Compare commits
46 Commits
wip/displa
...
wip/tower
Author | SHA1 | Date | |
---|---|---|---|
2b8e75ad48 | |||
ce0c6b8d9f | |||
9552ec89fb | |||
3a7c1e7b6c | |||
6980256a42 | |||
3f2dcf1698 | |||
44097c1b37 | |||
551b188c01 | |||
3a786542c4 | |||
bb2df9b2c6 | |||
7d1e149905 | |||
1dcd52838b | |||
909a6607c5 | |||
1bde397edf | |||
015c05fbf6 | |||
8ad5ccd2f8 | |||
115cc870c7 | |||
3112794d83 | |||
3528b067d0 | |||
0986b660be | |||
3bb5086173 | |||
69467842ab | |||
57077435ed | |||
46de0ed462 | |||
5086626805 | |||
bbbcd8c631 | |||
3b61b85f2c | |||
cd20f1bc0b | |||
8b52782ed4 | |||
849050be95 | |||
5c27a91684 | |||
764c472edb | |||
d0529b7482 | |||
8f4621240a | |||
e039add240 | |||
dbd8d4d598 | |||
522542c486 | |||
fc67c707e4 | |||
c354e7e81b | |||
bf40409d97 | |||
57d083730e | |||
dc242e46c2 | |||
7e1d1003c9 | |||
3bb33d384f | |||
214f31257b | |||
506ddc3d6c |
1
.gitignore
vendored
1
.gitignore
vendored
@ -74,6 +74,7 @@ src/mutter-enum-types.[ch]
|
||||
src/stamp-mutter-enum-types.h
|
||||
src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-xrandr.[ch]
|
||||
src/mutter-plugins.pc
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
|
@ -67,7 +67,7 @@ CANBERRA_GTK_VERSION=0.26
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.3.7
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gio-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
@ -75,6 +75,8 @@ 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
|
||||
|
@ -12,6 +12,7 @@ src/core/display.c
|
||||
src/core/errors.c
|
||||
src/core/keybindings.c
|
||||
src/core/main.c
|
||||
src/core/monitor.c
|
||||
src/core/mutter.c
|
||||
src/core/prefs.c
|
||||
src/core/screen.c
|
||||
|
353
po/cs.po
353
po/cs.po
@ -6,22 +6,23 @@
|
||||
# Petr Tomeš <ptomes@gmail.com>, 2006.
|
||||
# Jakub Friedl <jfriedl@suse.cz>, 2006, 2007.
|
||||
# Petr Kovar <pknbe@volny.cz>, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
|
||||
# Marek Černocký <marek@manet.cz>, 2012.
|
||||
# Marek Černocký <marek@manet.cz>, 2012, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter"
|
||||
"&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-03-22 10:02+0000\n"
|
||||
"PO-Revision-Date: 2013-03-24 20:55+0200\n"
|
||||
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
|
||||
"PO-Revision-Date: 2013-08-20 08:50+0200\n"
|
||||
"Last-Translator: Marek Černocký <marek@manet.cz>\n"
|
||||
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Virtaal 0.7.1\n"
|
||||
"X-Generator: Gtranslator 2.91.6\n"
|
||||
"X-Project-Style: gnome\n"
|
||||
|
||||
#: ../src/50-mutter-navigation.xml.in.h:1
|
||||
@ -186,7 +187,8 @@ msgstr "Přepnout výskyt okna na všech plochách nebo jen na jedné"
|
||||
|
||||
#: ../src/50-mutter-windows.xml.in.h:13
|
||||
msgid "Raise window if covered, otherwise lower it"
|
||||
msgstr "Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
|
||||
msgstr ""
|
||||
"Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
|
||||
|
||||
#: ../src/50-mutter-windows.xml.in.h:14
|
||||
msgid "Raise window above other windows"
|
||||
@ -214,14 +216,14 @@ msgstr "Zobrazit rozdělení napravo"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:568
|
||||
#: ../src/compositor/compositor.c:589
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
"\"."
|
||||
msgstr "Jiný kompozitní správce již běží na obrazovce %i displeje „%s“."
|
||||
|
||||
#: ../src/compositor/meta-background.c:1191
|
||||
#: ../src/compositor/meta-background.c:1076
|
||||
msgid "background texture could not be created from file"
|
||||
msgstr "textura pozadí nemohla být ze souboru vytvořena"
|
||||
|
||||
@ -259,17 +261,17 @@ msgstr "_Počkat"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Vynutit ukončení"
|
||||
|
||||
#: ../src/core/display.c:401
|
||||
#: ../src/core/display.c:421
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "Schází rozšíření %s vyžadované funkcemi kompozitoru"
|
||||
|
||||
#: ../src/core/display.c:493
|
||||
#: ../src/core/display.c:513
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Nelze otevřít displej X Window System „%s“\n"
|
||||
|
||||
#: ../src/core/keybindings.c:935
|
||||
#: ../src/core/keybindings.c:1136
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Some other program is already using the key %s with modifiers %x as a "
|
||||
@ -277,9 +279,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Klávesu %s s modifikátory %x již jako zkratku používá nějaký jiný program\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1135
|
||||
#: ../src/core/keybindings.c:1333
|
||||
#, c-format
|
||||
#| msgid "\"%s\" is not a valid value for focus attribute"
|
||||
msgid "\"%s\" is not a valid accelerator\n"
|
||||
msgstr "„%s“ není platný akcelerátor\n"
|
||||
|
||||
@ -320,6 +321,19 @@ msgstr ""
|
||||
"Nelze najít motiv! Ujistěte se prosím, že existuje %s a obsahuje obvyklé "
|
||||
"motivy.\n"
|
||||
|
||||
#: ../src/core/monitor.c:711
|
||||
msgid "Built-in display"
|
||||
msgstr "Vestavěný displej"
|
||||
|
||||
#. TRANSLATORS: this is a monitor name (in case we don't know
|
||||
#. the vendor), it's Unknown followed by a size in inches,
|
||||
#. like 'Unknown 15"'
|
||||
#.
|
||||
#: ../src/core/monitor.c:739
|
||||
#, c-format
|
||||
msgid "Unknown %s"
|
||||
msgstr "Neznámý %s"
|
||||
|
||||
#: ../src/core/mutter.c:40
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -344,7 +358,7 @@ msgstr "Vypíše verzi"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Zásuvný modul Mutter, který se má použít"
|
||||
|
||||
#: ../src/core/prefs.c:1095
|
||||
#: ../src/core/prefs.c:1202
|
||||
msgid ""
|
||||
"Workarounds for broken applications disabled. Some applications may not "
|
||||
"behave properly.\n"
|
||||
@ -352,12 +366,12 @@ msgstr ""
|
||||
"Bylo zakázáno obcházení chyb aplikací. Některé aplikace se možná nebudou "
|
||||
"chovat správně.\n"
|
||||
|
||||
#: ../src/core/prefs.c:1170
|
||||
#: ../src/core/prefs.c:1277
|
||||
#, c-format
|
||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||
msgstr "Nelze zpracovat popis písma „%s“ v klíči GSettings %s\n"
|
||||
|
||||
#: ../src/core/prefs.c:1236
|
||||
#: ../src/core/prefs.c:1343
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for mouse button "
|
||||
@ -366,7 +380,7 @@ msgstr ""
|
||||
"„%s“ nalezené v databázi nastavení není platnou hodnotou modifikátoru "
|
||||
"tlačítka myši\n"
|
||||
|
||||
#: ../src/core/prefs.c:1788
|
||||
#: ../src/core/prefs.c:1909
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for keybinding "
|
||||
@ -375,17 +389,17 @@ msgstr ""
|
||||
"„%s“ nalezené v databázi nastavení není platnou hodnotou klávesové zkratky "
|
||||
"„%s“\n"
|
||||
|
||||
#: ../src/core/prefs.c:1887
|
||||
#: ../src/core/prefs.c:1999
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Plocha %d"
|
||||
|
||||
#: ../src/core/screen.c:691
|
||||
#: ../src/core/screen.c:534
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Obrazovka %d na displeji „%s“ je neplatná\n"
|
||||
|
||||
#: ../src/core/screen.c:707
|
||||
#: ../src/core/screen.c:550
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||
@ -394,18 +408,18 @@ msgstr ""
|
||||
"Obrazovka %d na displeji „%s“ již správce oken má; zkuste prosím nahradit "
|
||||
"aktuálního správce oken pomocí přepínače --replace.\n"
|
||||
|
||||
#: ../src/core/screen.c:734
|
||||
#: ../src/core/screen.c:577
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not acquire window manager selection on screen %d display \"%s\"\n"
|
||||
msgstr "Nelze získat výběr správce oken na obrazovce %d displeje „%s“\n"
|
||||
|
||||
#: ../src/core/screen.c:812
|
||||
#: ../src/core/screen.c:655
|
||||
#, c-format
|
||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||
msgstr "Obrazovka %d na displeji „%s“ již má správce oken\n"
|
||||
|
||||
#: ../src/core/screen.c:998
|
||||
#: ../src/core/screen.c:846
|
||||
#, c-format
|
||||
msgid "Could not release screen %d on display \"%s\"\n"
|
||||
msgstr "Nelze uvolnit obrazovku %d na displeji „%s“\n"
|
||||
@ -480,8 +494,7 @@ msgstr "Nelze provést fdopen() soubor záznamu %s: %s\n"
|
||||
msgid "Opened log file %s\n"
|
||||
msgstr "Otevřen soubor záznamu %s\n"
|
||||
|
||||
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
|
||||
#, c-format
|
||||
#: ../src/core/util.c:119
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter bylo přeloženo bez podpory podrobného režimu\n"
|
||||
|
||||
@ -489,20 +502,20 @@ msgstr "Mutter bylo přeloženo bez podpory podrobného režimu\n"
|
||||
msgid "Window manager: "
|
||||
msgstr "Správce oken: "
|
||||
|
||||
#: ../src/core/util.c:412
|
||||
#: ../src/core/util.c:414
|
||||
msgid "Bug in window manager: "
|
||||
msgstr "Chyba ve správci oken: "
|
||||
|
||||
#: ../src/core/util.c:443
|
||||
#: ../src/core/util.c:445
|
||||
msgid "Window manager warning: "
|
||||
msgstr "Varování správce oken: "
|
||||
|
||||
#: ../src/core/util.c:471
|
||||
#: ../src/core/util.c:473
|
||||
msgid "Window manager error: "
|
||||
msgstr "Chyba správce oken: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7596
|
||||
#: ../src/core/window.c:7533
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
||||
@ -518,7 +531,7 @@ msgstr ""
|
||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||
#. * about these apps but make them work.
|
||||
#.
|
||||
#: ../src/core/window.c:8320
|
||||
#: ../src/core/window.c:8257
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||
@ -528,22 +541,22 @@ msgstr ""
|
||||
"velikost, ale nastavuje min. velikost %d × %d a max. velikost %d × %d; to "
|
||||
"nedává smysl.\n"
|
||||
|
||||
#: ../src/core/window-props.c:318
|
||||
#: ../src/core/window-props.c:347
|
||||
#, c-format
|
||||
msgid "Application set a bogus _NET_WM_PID %lu\n"
|
||||
msgstr "Aplikace nastavila neplatný _NET_WM_PID %lu\n"
|
||||
|
||||
#: ../src/core/window-props.c:434
|
||||
#: ../src/core/window-props.c:463
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (na %s)"
|
||||
|
||||
#: ../src/core/window-props.c:1517
|
||||
#: ../src/core/window-props.c:1546
|
||||
#, c-format
|
||||
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
|
||||
msgstr "Neplatné okno WM_TRANSIENT_FOR 0x%lx specifikováno pro %s.\n"
|
||||
|
||||
#: ../src/core/window-props.c:1528
|
||||
#: ../src/core/window-props.c:1557
|
||||
#, c-format
|
||||
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
|
||||
msgstr "Okno WM_TRANSIENT_FOR 0x%lx by vytvořilo smyčku pro %s.\n"
|
||||
@ -707,109 +720,104 @@ msgstr "Vybrat okno z překryvné nabídky tabulátoru"
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Zrušit překryvné okno tabulátoru"
|
||||
|
||||
#: ../src/tools/mutter-message.c:123
|
||||
#, c-format
|
||||
msgid "Usage: %s\n"
|
||||
msgstr "Použití: %s\n"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:69
|
||||
#: ../src/ui/menu.c:67
|
||||
msgid "Mi_nimize"
|
||||
msgstr "Mi_nimalizovat"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:71
|
||||
#: ../src/ui/menu.c:69
|
||||
msgid "Ma_ximize"
|
||||
msgstr "Ma_ximalizovat"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:73
|
||||
#: ../src/ui/menu.c:71
|
||||
msgid "Unma_ximize"
|
||||
msgstr "Zrušit ma_ximalizaci"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:75
|
||||
#: ../src/ui/menu.c:73
|
||||
msgid "Roll _Up"
|
||||
msgstr "Sv_inout"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:77
|
||||
#: ../src/ui/menu.c:75
|
||||
msgid "_Unroll"
|
||||
msgstr "Rozv_inout"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:79
|
||||
#: ../src/ui/menu.c:77
|
||||
msgid "_Move"
|
||||
msgstr "_Přesunout"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:81
|
||||
#: ../src/ui/menu.c:79
|
||||
msgid "_Resize"
|
||||
msgstr "Z_měnit velikost"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:83
|
||||
#: ../src/ui/menu.c:81
|
||||
msgid "Move Titlebar On_screen"
|
||||
msgstr "Přesunout záhlaví okna na _obrazovku"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
|
||||
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
|
||||
msgid "Always on _Top"
|
||||
msgstr "_Vždy navrchu"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:90
|
||||
#: ../src/ui/menu.c:88
|
||||
msgid "_Always on Visible Workspace"
|
||||
msgstr "Vžd_y na viditelné ploše"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:92
|
||||
#: ../src/ui/menu.c:90
|
||||
msgid "_Only on This Workspace"
|
||||
msgstr "_Jen na této ploše"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:94
|
||||
#: ../src/ui/menu.c:92
|
||||
msgid "Move to Workspace _Left"
|
||||
msgstr "Přesunout na plochu v_levo"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:96
|
||||
#: ../src/ui/menu.c:94
|
||||
msgid "Move to Workspace R_ight"
|
||||
msgstr "Přesunout na plochu vp_ravo"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:98
|
||||
#: ../src/ui/menu.c:96
|
||||
msgid "Move to Workspace _Up"
|
||||
msgstr "Přesunout na plochu na_hoře"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:100
|
||||
#: ../src/ui/menu.c:98
|
||||
msgid "Move to Workspace _Down"
|
||||
msgstr "Přesunout na plochu _dole"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:104
|
||||
#: ../src/ui/menu.c:102
|
||||
msgid "_Close"
|
||||
msgstr "_Zavřít"
|
||||
|
||||
#: ../src/ui/menu.c:204
|
||||
#: ../src/ui/menu.c:202
|
||||
#, c-format
|
||||
msgid "Workspace %d%n"
|
||||
msgstr "Plocha %d%n"
|
||||
|
||||
#: ../src/ui/menu.c:214
|
||||
#: ../src/ui/menu.c:212
|
||||
#, c-format
|
||||
msgid "Workspace 1_0"
|
||||
msgstr "Plocha 1_0"
|
||||
|
||||
#: ../src/ui/menu.c:216
|
||||
#: ../src/ui/menu.c:214
|
||||
#, c-format
|
||||
msgid "Workspace %s%d"
|
||||
msgstr "Plocha %s%d"
|
||||
|
||||
#: ../src/ui/menu.c:397
|
||||
#: ../src/ui/menu.c:384
|
||||
msgid "Move to Another _Workspace"
|
||||
msgstr "Přes_unout na jinou plochu"
|
||||
|
||||
@ -985,8 +993,8 @@ msgid ""
|
||||
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
|
||||
"where NORMAL is the state; could not parse \"%s\""
|
||||
msgstr ""
|
||||
"Specifikace GTK barvy musí mít stav v hranatých závorkách, např. gtk:fg"
|
||||
"[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
|
||||
"Specifikace GTK barvy musí mít stav v hranatých závorkách, např. gtk:"
|
||||
"fg[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
|
||||
|
||||
#: ../src/ui/theme.c:1292
|
||||
#, c-format
|
||||
@ -994,8 +1002,8 @@ msgid ""
|
||||
"GTK color specification must have a close bracket after the state, e.g. gtk:"
|
||||
"fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
|
||||
msgstr ""
|
||||
"Specifikace GTK barvy musí mít za stavem hranatou závorku, např. gtk:fg"
|
||||
"[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
|
||||
"Specifikace GTK barvy musí mít za stavem hranatou závorku, např. gtk:"
|
||||
"fg[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
|
||||
|
||||
#: ../src/ui/theme.c:1303
|
||||
#, c-format
|
||||
@ -1165,18 +1173,18 @@ msgid ""
|
||||
msgstr ""
|
||||
"Chybí <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"cokoliv\"/>"
|
||||
|
||||
#: ../src/ui/theme.c:5084
|
||||
#: ../src/ui/theme.c:5082
|
||||
#, c-format
|
||||
msgid "Failed to load theme \"%s\": %s\n"
|
||||
msgstr "Nelze načíst motiv „%s“: %s\n"
|
||||
|
||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
|
||||
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
|
||||
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
|
||||
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
|
||||
#, c-format
|
||||
msgid "No <%s> set for theme \"%s\""
|
||||
msgstr "Není nastaveno <%s> motivu „%s“"
|
||||
|
||||
#: ../src/ui/theme.c:5256
|
||||
#: ../src/ui/theme.c:5254
|
||||
#, c-format
|
||||
msgid ""
|
||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
||||
@ -1185,7 +1193,7 @@ msgstr ""
|
||||
"U typu okna „%s“ motivu „%s“ není nastaven typ rámu, přidejte prosím prvek "
|
||||
"<window type=\"%s\" style_set=\"cokoliv\"/>"
|
||||
|
||||
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
|
||||
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
|
||||
#, c-format
|
||||
msgid ""
|
||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
||||
@ -1193,7 +1201,7 @@ msgstr ""
|
||||
"Uživatelem definované konstanty musí začínat velkým písmenem; „%s“ toto "
|
||||
"nesplňuje"
|
||||
|
||||
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
|
||||
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
|
||||
#, c-format
|
||||
msgid "Constant \"%s\" has already been defined"
|
||||
msgstr "Konstanta „%s“ již byla definována"
|
||||
@ -1572,205 +1580,4 @@ msgstr "<%s> u tohoto motivu definováno dvakrát"
|
||||
#: ../src/ui/theme-parser.c:4336
|
||||
#, c-format
|
||||
msgid "Failed to find a valid file for theme %s\n"
|
||||
msgstr "Nelze nalézt platný soubor motivu %s\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:99
|
||||
msgid "_Windows"
|
||||
msgstr "_Okna"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:100
|
||||
msgid "_Dialog"
|
||||
msgstr "_Dialogové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:101
|
||||
msgid "_Modal dialog"
|
||||
msgstr "_Modální dialogové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:102
|
||||
msgid "_Utility"
|
||||
msgstr "_Nástroje"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:103
|
||||
msgid "_Splashscreen"
|
||||
msgstr "_Spouštěcí obrazovka"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:104
|
||||
msgid "_Top dock"
|
||||
msgstr "_Horní dok"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:105
|
||||
msgid "_Bottom dock"
|
||||
msgstr "Dolní do_k"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:106
|
||||
msgid "_Left dock"
|
||||
msgstr "_Levý dok"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:107
|
||||
msgid "_Right dock"
|
||||
msgstr "P_ravý dok"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:108
|
||||
msgid "_All docks"
|
||||
msgstr "_Všechny doky"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:109
|
||||
msgid "Des_ktop"
|
||||
msgstr "Pra_covní prostředí"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:115
|
||||
msgid "Open another one of these windows"
|
||||
msgstr "Otevřít další takové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:117
|
||||
msgid "This is a demo button with an 'open' icon"
|
||||
msgstr "Toto je demonstrační tlačítko s ikonou „otevřít“"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:119
|
||||
msgid "This is a demo button with a 'quit' icon"
|
||||
msgstr "Toto je demonstrační tlačítko s ikonou „ukončit“"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:248
|
||||
msgid "This is a sample message in a sample dialog"
|
||||
msgstr "Toto je ukázková zpráva v ukázkovém dialogu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:328
|
||||
#, c-format
|
||||
msgid "Fake menu item %d\n"
|
||||
msgstr "Falešná položka nabídky %d\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:363
|
||||
msgid "Border-only window"
|
||||
msgstr "Okno jen s okrajem"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:365
|
||||
msgid "Bar"
|
||||
msgstr "Lišta"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:382
|
||||
msgid "Normal Application Window"
|
||||
msgstr "Normální okno aplikace"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:386
|
||||
msgid "Dialog Box"
|
||||
msgstr "Dialogové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:390
|
||||
msgid "Modal Dialog Box"
|
||||
msgstr "Modální dialogové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:394
|
||||
msgid "Utility Palette"
|
||||
msgstr "Paleta nástrojů"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:398
|
||||
msgid "Torn-off Menu"
|
||||
msgstr "Odtržení nabídky"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:402
|
||||
msgid "Border"
|
||||
msgstr "Okraj"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:406
|
||||
msgid "Attached Modal Dialog"
|
||||
msgstr "Připojené modální dialogové okno"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:737
|
||||
#, c-format
|
||||
msgid "Button layout test %d"
|
||||
msgstr "Test rozložení tlačítek %d"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:766
|
||||
#, c-format
|
||||
msgid "%g milliseconds to draw one window frame"
|
||||
msgstr "%g milisekund na nakreslení jednoho rámu okna"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:811
|
||||
#, c-format
|
||||
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||
msgstr "Použití: metacity-theme-viewer [NÁZEVMOTIVU]\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:818
|
||||
#, c-format
|
||||
msgid "Error loading theme: %s\n"
|
||||
msgstr "Chyba při načítání motivu: %s\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:824
|
||||
#, c-format
|
||||
msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||
msgstr "Načten motiv „%s“ za %g sekund\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:869
|
||||
msgid "Normal Title Font"
|
||||
msgstr "Normální písmo nadpisu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:875
|
||||
msgid "Small Title Font"
|
||||
msgstr "Malé písmo nadpisu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:881
|
||||
msgid "Large Title Font"
|
||||
msgstr "Velké písmo nadpisu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:886
|
||||
msgid "Button Layouts"
|
||||
msgstr "Rozložení tlačítek"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:891
|
||||
msgid "Benchmark"
|
||||
msgstr "Test výkonnosti"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:947
|
||||
msgid "Window Title Goes Here"
|
||||
msgstr "Sem patří nadpis okna"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1053
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
|
||||
"seconds wall clock time including X server resources (%g milliseconds per "
|
||||
"frame)\n"
|
||||
msgstr ""
|
||||
"Nakresleno %d rámů za %g sekund na straně klienta (%g milisekund na rám) a "
|
||||
"%g sekund reálného času včetně zdrojů serveru X (%g milisekund na rám)\n"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1273
|
||||
msgid "position expression test returned TRUE but set error"
|
||||
msgstr "test výrazu umístění vrátil TRUE, ale nastavil chybu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1275
|
||||
msgid "position expression test returned FALSE but didn't set error"
|
||||
msgstr "test výrazu umístění vrátil FALSE, ale nenastavil chybu"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1279
|
||||
msgid "Error was expected but none given"
|
||||
msgstr "Byla očekávána chyba, ale nebyla přijata"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1281
|
||||
#, c-format
|
||||
msgid "Error %d was expected but %d given"
|
||||
msgstr "Byla očekávána chyba %d, ale bylo přijato %d"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1287
|
||||
#, c-format
|
||||
msgid "Error not expected but one was returned: %s"
|
||||
msgstr "Chyba nebyla očekávána, ale byla vrácena: %s"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1291
|
||||
#, c-format
|
||||
msgid "x value was %d, %d was expected"
|
||||
msgstr "Hodnota x byla %d, bylo očekáváno %d"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1294
|
||||
#, c-format
|
||||
msgid "y value was %d, %d was expected"
|
||||
msgstr "Hodnota y byla %d, bylo očekáváno %d"
|
||||
|
||||
#: ../src/ui/theme-viewer.c:1359
|
||||
#, c-format
|
||||
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||
msgstr "Zpracováno %d výrazů souřadnic za %g sekund (průměr %g sekund)\n"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Minimize window"
|
||||
#~ msgstr "Minimalizovat okno"
|
||||
msgstr "Nelze nalézt platný soubor motivu %s\n"
|
@ -30,6 +30,7 @@ INCLUDES= \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
|
||||
@ -64,8 +65,6 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-shaped-texture.c \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
compositor/meta-texture-tower.h \
|
||||
compositor/meta-window-actor.c \
|
||||
compositor/meta-window-actor-private.h \
|
||||
compositor/meta-window-group.c \
|
||||
@ -94,6 +93,8 @@ libmutter_la_SOURCES = \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/edid-parse.c \
|
||||
core/edid.h \
|
||||
core/errors.c \
|
||||
meta/errors.h \
|
||||
core/frame.c \
|
||||
@ -110,6 +111,13 @@ libmutter_la_SOURCES = \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
core/meta-cursor-tracker.c \
|
||||
core/meta-cursor-tracker-private.h \
|
||||
core/meta-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 \
|
||||
@ -178,6 +186,7 @@ libmutterinclude_base_headers = \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-background-group.h \
|
||||
meta/meta-background.h \
|
||||
meta/meta-cursor-tracker.h \
|
||||
meta/meta-plugin.h \
|
||||
meta/meta-shaped-texture.h \
|
||||
meta/meta-shadow-factory.h \
|
||||
@ -295,6 +304,7 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
xrandr.xml \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-plugins.pc.in \
|
||||
@ -323,3 +333,12 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
|
||||
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
|
||||
cp xgen-tetc mutter-enum-types.c && \
|
||||
rm -f xgen-tetc
|
||||
|
||||
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
|
||||
|
||||
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--interface-prefix org.gnome.Mutter \
|
||||
--c-namespace MetaDBus \
|
||||
--generate-c-code meta-dbus-xrandr \
|
||||
$(srcdir)/xrandr.xml
|
||||
|
@ -1,10 +0,0 @@
|
||||
Intro
|
||||
=====
|
||||
|
||||
Fix me.
|
||||
|
||||
|
||||
Env Vars
|
||||
========
|
||||
|
||||
MUTTER_DISABLE_MIPMAPS - set to disable use of mipmaped windows.
|
@ -31,7 +31,6 @@ struct _MetaCompositor
|
||||
guint server_time_is_monotonic_time : 1;
|
||||
guint show_redraw : 1;
|
||||
guint debug : 1;
|
||||
guint no_mipmaps : 1;
|
||||
};
|
||||
|
||||
struct _MetaCompScreen
|
||||
@ -66,8 +65,6 @@ void meta_switch_workspace_completed (MetaScreen *screen);
|
||||
|
||||
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
|
@ -412,8 +412,6 @@ meta_stage_is_focused (MetaScreen *screen)
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
@ -424,10 +422,19 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
ClutterStage *stage;
|
||||
Window grab_window;
|
||||
Cursor cursor = None;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
int result;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
|
||||
grab_window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
|
||||
@ -1525,9 +1532,6 @@ meta_compositor_new (MetaDisplay *display)
|
||||
|
||||
compositor->display = display;
|
||||
|
||||
if (g_getenv("META_DISABLE_MIPMAPS"))
|
||||
compositor->no_mipmaps = TRUE;
|
||||
|
||||
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
|
||||
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
||||
False, atoms);
|
||||
|
@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar *plugin_name)
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
on_confirm_display_change (MetaMonitorManager *monitors,
|
||||
MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
meta_plugin_manager_confirm_display_change (plugin_mgr);
|
||||
}
|
||||
|
||||
MetaPluginManager *
|
||||
meta_plugin_manager_new (MetaScreen *screen)
|
||||
{
|
||||
MetaPluginManager *plugin_mgr;
|
||||
MetaPluginClass *klass;
|
||||
MetaPlugin *plugin;
|
||||
MetaMonitorManager *monitors;
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr->screen = screen;
|
||||
@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen)
|
||||
if (klass->start)
|
||||
klass->start (plugin);
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect (monitors, "confirm-display-change",
|
||||
G_CALLBACK (on_confirm_display_change), plugin_mgr);
|
||||
|
||||
return plugin_mgr;
|
||||
}
|
||||
|
||||
@ -320,3 +332,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
|
||||
else
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->confirm_display_change)
|
||||
return klass->confirm_display_change (plugin);
|
||||
else
|
||||
return meta_plugin_complete_display_change (plugin, TRUE);
|
||||
}
|
||||
|
@ -73,4 +73,6 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
|
||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
|
||||
XEvent *xev);
|
||||
|
||||
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
|
||||
|
||||
#endif
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
|
||||
@ -266,10 +267,6 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
/**
|
||||
* meta_plugin_begin_modal:
|
||||
* @plugin: a #MetaPlugin
|
||||
* @grab_window: the X window to grab the keyboard and mouse on
|
||||
* @cursor: the cursor to use for the pointer grab, or None,
|
||||
* to use the normal cursor for the grab window and
|
||||
* its descendants.
|
||||
* @options: flags that modify the behavior of the modal grab
|
||||
* @timestamp: the timestamp used for establishing grabs
|
||||
*
|
||||
@ -290,15 +287,13 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
*/
|
||||
gboolean
|
||||
meta_plugin_begin_modal (MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return meta_begin_modal_for_plugin (priv->screen, plugin,
|
||||
grab_window, cursor, options, timestamp);
|
||||
options, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -338,3 +333,13 @@ meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok)
|
||||
{
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_confirm_configuration (manager, ok);
|
||||
}
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
@ -64,7 +63,6 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
|
||||
|
||||
struct _MetaShapedTexturePrivate
|
||||
{
|
||||
MetaTextureTower *paint_tower;
|
||||
Pixmap pixmap;
|
||||
CoglTexturePixmapX11 *texture;
|
||||
CoglTexture *mask_texture;
|
||||
@ -74,8 +72,6 @@ struct _MetaShapedTexturePrivate
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
guint tex_width, tex_height;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -102,10 +98,8 @@ meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
|
||||
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->paint_tower = meta_texture_tower_new ();
|
||||
priv->texture = NULL;
|
||||
priv->mask_texture = NULL;
|
||||
priv->create_mipmaps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -114,10 +108,6 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
@ -133,7 +123,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglTexture *paint_tex;
|
||||
guint tex_width, tex_height;
|
||||
ClutterActorBox alloc;
|
||||
|
||||
@ -148,29 +137,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* rarely supported. Also, even when it is supported there
|
||||
* are distinct performance implications from:
|
||||
*
|
||||
* - Updating mipmaps that we don't need
|
||||
* - Having to reallocate pixmaps on the server into larger buffers
|
||||
*
|
||||
* So, we just unconditionally use our mipmap emulation code. If we
|
||||
* wanted to use SGIS_generate_mipmap, we'd have to query COGL to
|
||||
* see if it was supported (no API currently), and then if and only
|
||||
* if that was the case, set the clutter texture quality to HIGH.
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
|
||||
tex_width = priv->tex_width;
|
||||
tex_height = priv->tex_height;
|
||||
|
||||
@ -212,7 +178,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR,
|
||||
COGL_PIPELINE_FILTER_LINEAR);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, priv->texture);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
@ -373,28 +342,6 @@ meta_shaped_texture_new (void)
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
create_mipmaps = create_mipmaps != FALSE;
|
||||
|
||||
if (create_mipmaps != priv->create_mipmaps)
|
||||
{
|
||||
CoglTexture *base_texture;
|
||||
priv->create_mipmaps = create_mipmaps;
|
||||
base_texture = create_mipmaps ?
|
||||
COGL_TEXTURE (priv->texture) : NULL;
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *mask_texture)
|
||||
@ -434,8 +381,6 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture,
|
||||
x, y, width, height);
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
|
||||
}
|
||||
|
||||
@ -514,10 +459,6 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
|
||||
}
|
||||
else
|
||||
set_cogl_texture (stex, NULL);
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower,
|
||||
COGL_TEXTURE (priv->texture));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,624 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "meta-texture-tower.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
#define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
|
||||
#define MAX_TEXTURE_LEVELS 12
|
||||
|
||||
/* If the texture format in memory doesn't match this, then Mesa
|
||||
* will do the conversion, so things will still work, but it might
|
||||
* be slow depending on how efficient Mesa is. These should be the
|
||||
* native formats unless the display is 16bpp. If conversions
|
||||
* here are a bottleneck, investigate whether we are converting when
|
||||
* storing window data *into* the texture before adding extra code
|
||||
* to handle multiple texture formats.
|
||||
*/
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
#else
|
||||
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint16 x1;
|
||||
guint16 y1;
|
||||
guint16 x2;
|
||||
guint16 y2;
|
||||
} Box;
|
||||
|
||||
struct _MetaTextureTower
|
||||
{
|
||||
int n_levels;
|
||||
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
||||
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_texture_tower_new:
|
||||
*
|
||||
* Creates a new texture tower. The base texture has to be set with
|
||||
* meta_texture_tower_set_base_texture() before use.
|
||||
*
|
||||
* Return value: the new texture tower. Free with meta_texture_tower_free()
|
||||
*/
|
||||
MetaTextureTower *
|
||||
meta_texture_tower_new (void)
|
||||
{
|
||||
MetaTextureTower *tower;
|
||||
|
||||
tower = g_slice_new0 (MetaTextureTower);
|
||||
|
||||
return tower;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_free:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Frees a texture tower created with meta_texture_tower_new().
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, NULL);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_set_base_texture:
|
||||
* @tower: a #MetaTextureTower
|
||||
* @texture: the new texture used as a base for scaled down versions
|
||||
*
|
||||
* Sets the base texture that is the scaled texture that the
|
||||
* scaled textures of the tower are derived from. The texture itself
|
||||
* will be used as level 0 of the tower and will be referenced until
|
||||
* unset or until the tower is freed.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (texture == tower->textures[0])
|
||||
return;
|
||||
|
||||
if (tower->textures[0] != NULL)
|
||||
{
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
if (tower->textures[i] != NULL)
|
||||
{
|
||||
cogl_object_unref (tower->textures[i]);
|
||||
tower->textures[i] = NULL;
|
||||
}
|
||||
|
||||
if (tower->fbos[i] != NULL)
|
||||
{
|
||||
cogl_object_unref (tower->fbos[i]);
|
||||
tower->fbos[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cogl_object_unref (tower->textures[0]);
|
||||
}
|
||||
|
||||
tower->textures[0] = texture;
|
||||
|
||||
if (tower->textures[0] != NULL)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
cogl_object_ref (tower->textures[0]);
|
||||
|
||||
width = cogl_texture_get_width (tower->textures[0]);
|
||||
height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
|
||||
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
|
||||
|
||||
meta_texture_tower_update_area (tower, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->n_levels = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_update_area:
|
||||
* @tower: a #MetaTextureTower
|
||||
* @x: X coordinate of upper left of rectangle that changed
|
||||
* @y: Y coordinate of upper left of rectangle that changed
|
||||
* @width: width of rectangle that changed
|
||||
* @height: height rectangle that changed
|
||||
*
|
||||
* Mark a region of the base texture as having changed; the next
|
||||
* time a scaled down version of the base texture is retrieved,
|
||||
* the appropriate area of the scaled down texture will be updated.
|
||||
*/
|
||||
void
|
||||
meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
Box invalid;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (tower->textures[0] == NULL)
|
||||
return;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
invalid.x1 = x;
|
||||
invalid.y1 = y;
|
||||
invalid.x2 = x + width;
|
||||
invalid.y2 = y + height;
|
||||
|
||||
for (i = 1; i < tower->n_levels; i++)
|
||||
{
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
invalid.x1 = invalid.x1 / 2;
|
||||
invalid.y1 = invalid.y1 / 2;
|
||||
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
|
||||
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
|
||||
|
||||
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
|
||||
tower->invalid[i].y1 == tower->invalid[i].y2)
|
||||
{
|
||||
tower->invalid[i] = invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
|
||||
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
|
||||
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
|
||||
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* It generally looks worse if we scale up a window texture by even a
|
||||
* small amount than if we scale it down using bilinear filtering, so
|
||||
* we always pick the *larger* adjacent level. */
|
||||
#define LOD_BIAS (-0.49)
|
||||
|
||||
/* This determines the appropriate level of detail to use when drawing the
|
||||
* texture, in a way that corresponds to what the GL specification does
|
||||
* when mip-mapping. This is probably fancier and slower than what we need,
|
||||
* but we do the computation only once each time we paint a window, and
|
||||
* its easier to just use the equations from the specification than to
|
||||
* come up with something simpler.
|
||||
*
|
||||
* If window is being painted at an angle from the viewer, then we have to
|
||||
* pick a point in the texture; we use the middle of the texture (which is
|
||||
* why the width/height are passed in.) This is not the normal case for
|
||||
* Meta.
|
||||
*/
|
||||
static int
|
||||
get_paint_level (int width, int height)
|
||||
{
|
||||
CoglMatrix projection, modelview, pm;
|
||||
float v[4];
|
||||
double viewport_width, viewport_height;
|
||||
double u0, v0;
|
||||
double xc, yc, wc;
|
||||
double dxdu_, dxdv_, dydu_, dydv_;
|
||||
double det_, det_sq;
|
||||
double rho_sq;
|
||||
double lambda;
|
||||
|
||||
/* See
|
||||
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
|
||||
* Section 3.8.9, p. 1.6.2. Here we have
|
||||
*
|
||||
* u(x,y) = x_o;
|
||||
* v(x,y) = y_o;
|
||||
*
|
||||
* Since we are mapping 1:1 from object coordinates into pixel
|
||||
* texture coordinates, the clip coordinates are:
|
||||
*
|
||||
* (x_c) (x_o) (u)
|
||||
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
|
||||
* (z_c) (z_o) (0)
|
||||
* (w_c) (w_o) (1)
|
||||
*/
|
||||
|
||||
cogl_get_projection_matrix (&projection);
|
||||
cogl_get_modelview_matrix (&modelview);
|
||||
|
||||
cogl_matrix_multiply (&pm, &projection, &modelview);
|
||||
|
||||
cogl_get_viewport (v);
|
||||
viewport_width = v[2];
|
||||
viewport_height = v[3];
|
||||
|
||||
u0 = width / 2.;
|
||||
v0 = height / 2.;
|
||||
|
||||
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
|
||||
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
|
||||
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
|
||||
|
||||
/* We'll simplify the equations below for a bit of micro-optimization.
|
||||
* The commented out code is the unsimplified version.
|
||||
|
||||
// Partial derivates of window coordinates:
|
||||
//
|
||||
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
|
||||
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
|
||||
//
|
||||
// with respect to u, v, using
|
||||
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
|
||||
|
||||
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
|
||||
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
|
||||
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
|
||||
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
|
||||
|
||||
// Compute the inverse partials as the matrix inverse
|
||||
det = dxdu * dydv - dxdv * dydu;
|
||||
|
||||
dudx = dydv / det;
|
||||
dudy = - dxdv / det;
|
||||
dvdx = - dydu / det;
|
||||
dvdy = dvdu / det;
|
||||
|
||||
// Scale factor; maximum of the distance in texels for a change of 1 pixel
|
||||
// in the X direction or 1 pixel in the Y direction
|
||||
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
|
||||
|
||||
// Level of detail
|
||||
lambda = log2 (rho) + LOD_BIAS;
|
||||
*/
|
||||
|
||||
/* dxdu * wc, etc */
|
||||
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
|
||||
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
|
||||
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
|
||||
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
|
||||
|
||||
/* det * wc^2 */
|
||||
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
|
||||
det_sq = det_ * det_;
|
||||
if (det_sq == 0.0)
|
||||
return -1;
|
||||
|
||||
/* (rho * det * wc)^2 */
|
||||
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
|
||||
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
|
||||
|
||||
#if 0
|
||||
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
|
||||
#endif
|
||||
|
||||
if (lambda <= 0.)
|
||||
return 0;
|
||||
else
|
||||
return (int)(0.5 + lambda);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_power_of_two (int x)
|
||||
{
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_create_texture (MetaTextureTower *tower,
|
||||
int level,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
|
||||
meta_texture_rectangle_check (tower->textures[level - 1]))
|
||||
{
|
||||
tower->textures[level] =
|
||||
meta_texture_rectangle_new (width, height,
|
||||
/* data format */
|
||||
TEXTURE_FORMAT,
|
||||
/* internal cogl format */
|
||||
TEXTURE_FORMAT,
|
||||
/* rowstride */
|
||||
width * 4,
|
||||
/* data */
|
||||
NULL,
|
||||
/* error */
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
tower->textures[level] = cogl_texture_new_with_size (width, height,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP,
|
||||
TEXTURE_FORMAT);
|
||||
}
|
||||
|
||||
tower->invalid[level].x1 = 0;
|
||||
tower->invalid[level].y1 = 0;
|
||||
tower->invalid[level].x2 = width;
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
CoglTexture *dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == NULL)
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
|
||||
if (tower->fbos[level] == NULL)
|
||||
return FALSE;
|
||||
|
||||
cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
|
||||
|
||||
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
|
||||
cogl_set_source_texture (tower->textures[level - 1]);
|
||||
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_copy (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
memcpy (buf, source, width * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_scale_down (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
while (width > 1)
|
||||
{
|
||||
buf[0] = (source[0] + source[4]) / 2;
|
||||
buf[1] = (source[1] + source[5]) / 2;
|
||||
buf[2] = (source[2] + source[6]) / 2;
|
||||
buf[3] = (source[3] + source[7]) / 2;
|
||||
|
||||
buf += 4;
|
||||
source += 8;
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
buf[0] = source[0] / 2;
|
||||
buf[1] = source[1] / 2;
|
||||
buf[2] = source[2] / 2;
|
||||
buf[3] = source[3] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
guint source_rowstride;
|
||||
guchar *source_data;
|
||||
CoglTexture *dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
int dest_x = tower->invalid[level].x1;
|
||||
int dest_y = tower->invalid[level].y1;
|
||||
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||
guchar *dest_data;
|
||||
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||
int i, j;
|
||||
|
||||
source_rowstride = source_texture_width * 4;
|
||||
|
||||
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||
source_data);
|
||||
|
||||
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
source_tmp1 = g_malloc (dest_width * 4);
|
||||
source_tmp2 = g_malloc (dest_width * 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
guchar *source1, *source2;
|
||||
guchar *dest;
|
||||
|
||||
if (dest_texture_width < source_texture_width)
|
||||
{
|
||||
fill_scale_down (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
fill_scale_down (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_copy (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
fill_copy (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
}
|
||||
|
||||
source1 = source_tmp1;
|
||||
source2 = source_tmp2;
|
||||
|
||||
dest = dest_row;
|
||||
for (j = 0; j < dest_width * 4; j++)
|
||||
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_texture_width < source_texture_width)
|
||||
fill_scale_down (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
else
|
||||
fill_copy (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride,
|
||||
dest_width);
|
||||
}
|
||||
}
|
||||
|
||||
cogl_texture_set_region (dest_texture,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
dest_width, dest_height,
|
||||
dest_width, dest_height,
|
||||
TEXTURE_FORMAT,
|
||||
4 * dest_width,
|
||||
dest_data);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
g_free (source_tmp1);
|
||||
g_free (source_tmp2);
|
||||
}
|
||||
|
||||
g_free (source_data);
|
||||
g_free (dest_data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_texture_tower_get_paint_texture:
|
||||
* @tower: a #MetaTextureTower
|
||||
*
|
||||
* Gets the texture from the tower that best matches the current
|
||||
* rendering scale. (On the assumption here the texture is going to
|
||||
* be rendered with vertex coordinates that correspond to its
|
||||
* size in pixels, so a 200x200 texture will be rendered on the
|
||||
* rectangle (0, 0, 200, 200).
|
||||
*
|
||||
* Return value: the COGL texture handle to use for painting, or
|
||||
* %NULL if no base texture has yet been set.
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
|
||||
{
|
||||
int texture_width, texture_height;
|
||||
int level;
|
||||
|
||||
g_return_val_if_fail (tower != NULL, NULL);
|
||||
|
||||
if (tower->textures[0] == NULL)
|
||||
return NULL;
|
||||
|
||||
texture_width = cogl_texture_get_width (tower->textures[0]);
|
||||
texture_height = cogl_texture_get_height (tower->textures[0]);
|
||||
|
||||
level = get_paint_level(texture_width, texture_height);
|
||||
if (level < 0) /* singular paint matrix, scaled to nothing */
|
||||
return NULL;
|
||||
level = MIN (level, tower->n_levels - 1);
|
||||
|
||||
if (tower->textures[level] == NULL ||
|
||||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
/* Use "floor" convention here to be consistent with the NPOT texture extension */
|
||||
texture_width = MAX (1, texture_width / 2);
|
||||
texture_height = MAX (1, texture_height / 2);
|
||||
|
||||
if (tower->textures[i] == NULL)
|
||||
texture_tower_create_texture (tower, i, texture_width, texture_height);
|
||||
}
|
||||
|
||||
for (i = 1; i <= level; i++)
|
||||
{
|
||||
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
|
||||
tower->invalid[level].y2 != tower->invalid[level].y1)
|
||||
texture_tower_revalidate (tower, i);
|
||||
}
|
||||
}
|
||||
|
||||
return tower->textures[level];
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* MetaTextureTower
|
||||
*
|
||||
* Mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __META_TEXTURE_TOWER_H__
|
||||
#define __META_TEXTURE_TOWER_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:MetaTextureTower
|
||||
* @short_description: mipmap emulation by creation of scaled down images
|
||||
*
|
||||
* A #MetaTextureTower is used to get good looking scaled down images when
|
||||
* we can't use the GL drivers mipmap support. There are two separate reasons
|
||||
*
|
||||
* - Some cards (including radeon cards <= r5xx) only support
|
||||
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
|
||||
* are defined not to support mipmapping.
|
||||
* - Even when NPOT textures are available, the combination of NPOT
|
||||
* textures, texture_from_pixmap, and mipmapping doesn't typically
|
||||
* work, since the X server doesn't allocate pixmaps in the right
|
||||
* layout for mipmapping.
|
||||
*
|
||||
* So, what we do is create the "mipmap" levels ourselves by successive
|
||||
* power-of-two scaledowns, and when rendering pick the single texture
|
||||
* that best matches the scale we are rendering at. (Since we aren't
|
||||
* typically using perspective transforms, we'll frequently have a single
|
||||
* scale for the entire texture.)
|
||||
*/
|
||||
|
||||
typedef struct _MetaTextureTower MetaTextureTower;
|
||||
|
||||
MetaTextureTower *meta_texture_tower_new (void);
|
||||
void meta_texture_tower_free (MetaTextureTower *tower);
|
||||
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
|
||||
CoglTexture *texture);
|
||||
void meta_texture_tower_update_area (MetaTextureTower *tower,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#endif /* __META_TEXTURE_TOWER_H__ */
|
@ -369,10 +369,10 @@ meta_window_actor_constructed (GObject *object)
|
||||
*/
|
||||
g_object_ref (priv->actor);
|
||||
|
||||
g_signal_connect (window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self);
|
||||
g_signal_connect (window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self);
|
||||
g_signal_connect_object (window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
g_signal_connect_object (window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1782,10 +1782,6 @@ check_needs_pixmap (MetaWindowActor *self)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (compositor->no_mipmaps)
|
||||
meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor),
|
||||
FALSE);
|
||||
|
||||
meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor),
|
||||
priv->back_pixmap);
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <meta/meta-plugin.h>
|
||||
#include <meta/window.h>
|
||||
#include <meta/util.h>
|
||||
#include <meta/meta-background-group.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
@ -98,6 +100,8 @@ static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static void confirm_display_change (MetaPlugin *plugin);
|
||||
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
|
||||
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
|
||||
@ -113,6 +117,8 @@ struct _MetaDefaultPluginPrivate
|
||||
ClutterActor *desktop1;
|
||||
ClutterActor *desktop2;
|
||||
|
||||
ClutterActor *background_group;
|
||||
|
||||
MetaPluginInfo info;
|
||||
};
|
||||
|
||||
@ -203,6 +209,7 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
plugin_class->confirm_display_change = confirm_display_change;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
|
||||
}
|
||||
@ -299,9 +306,58 @@ show_stage (MetaPlugin *plugin)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaScreen *screen,
|
||||
MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
int i, n;
|
||||
|
||||
clutter_actor_destroy_all_children (self->priv->background_group);
|
||||
|
||||
n = meta_screen_get_n_monitors (screen);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
MetaRectangle rect;
|
||||
ClutterActor *background;
|
||||
ClutterColor color;
|
||||
|
||||
meta_screen_get_monitor_geometry (screen, i, &rect);
|
||||
|
||||
background = meta_background_actor_new ();
|
||||
|
||||
clutter_actor_set_position (background, rect.x, rect.y);
|
||||
clutter_actor_set_size (background, rect.width, rect.height);
|
||||
|
||||
/* Don't use rand() here, mesa calls srand() internally when
|
||||
parsing the driconf XML, but it's nice if the colors are
|
||||
reproducible.
|
||||
*/
|
||||
clutter_color_init (&color,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
255);
|
||||
clutter_actor_set_background_color (background, &color);
|
||||
|
||||
clutter_actor_add_child (self->priv->background_group, background);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
start (MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
|
||||
self->priv->background_group = meta_background_group_new ();
|
||||
clutter_actor_insert_child_below (meta_get_window_group_for_screen (screen),
|
||||
self->priv->background_group, NULL);
|
||||
|
||||
g_signal_connect (screen, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), plugin);
|
||||
on_monitors_changed (screen, plugin);
|
||||
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
(GSourceFunc) show_stage,
|
||||
plugin,
|
||||
@ -782,3 +838,33 @@ plugin_info (MetaPlugin *plugin)
|
||||
|
||||
return &priv->info;
|
||||
}
|
||||
|
||||
static void
|
||||
on_dialog_closed (GPid pid,
|
||||
gint status,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaPlugin *plugin = user_data;
|
||||
gboolean ok;
|
||||
|
||||
ok = g_spawn_check_exit_status (status, NULL);
|
||||
meta_plugin_complete_display_change (plugin, ok);
|
||||
}
|
||||
|
||||
static void
|
||||
confirm_display_change (MetaPlugin *plugin)
|
||||
{
|
||||
GPid pid;
|
||||
|
||||
pid = meta_show_dialog ("--question",
|
||||
"Does the display look OK?",
|
||||
"20",
|
||||
NULL,
|
||||
"_Keep This Configuration",
|
||||
"_Restore Previous Configuration",
|
||||
"preferences-desktop-display",
|
||||
0,
|
||||
NULL, NULL);
|
||||
|
||||
g_child_watch_add (pid, on_dialog_closed, plugin);
|
||||
}
|
||||
|
@ -2146,6 +2146,8 @@ event_callback (XEvent *event,
|
||||
gboolean bypass_compositor;
|
||||
gboolean filter_out_event;
|
||||
XIEvent *input_event;
|
||||
MetaMonitorManager *monitor;
|
||||
MetaScreen *screen;
|
||||
|
||||
display = data;
|
||||
|
||||
@ -2157,6 +2159,14 @@ event_callback (XEvent *event,
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
sn_display_process_event (display->sn_display, event);
|
||||
#endif
|
||||
|
||||
/* Intercept XRandR events early and don't attempt any
|
||||
processing for them. We still let them through to Gdk though,
|
||||
so it can update its own internal state.
|
||||
*/
|
||||
monitor = meta_monitor_manager_get ();
|
||||
if (meta_monitor_manager_handle_xevent (monitor, event))
|
||||
return FALSE;
|
||||
|
||||
bypass_compositor = FALSE;
|
||||
filter_out_event = FALSE;
|
||||
@ -2175,6 +2185,13 @@ event_callback (XEvent *event,
|
||||
display->server_focus_serial);
|
||||
}
|
||||
|
||||
screen = meta_display_screen_for_root (display, event->xany.window);
|
||||
if (screen)
|
||||
{
|
||||
if (meta_screen_handle_xevent (screen, event))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
modified = event_get_modified_window (display, event);
|
||||
|
||||
input_event = get_input_event (display, event);
|
||||
@ -2822,32 +2839,10 @@ event_callback (XEvent *event,
|
||||
meta_stack_tracker_configure_event (screen->stack_tracker,
|
||||
&event->xconfigure);
|
||||
}
|
||||
|
||||
if (window && window->override_redirect)
|
||||
meta_window_configure_notify (window, &event->xconfigure);
|
||||
else
|
||||
/* Handle screen resize */
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_display_screen_for_root (display,
|
||||
event->xconfigure.window);
|
||||
|
||||
if (screen != NULL)
|
||||
{
|
||||
#ifdef HAVE_RANDR
|
||||
/* do the resize the official way */
|
||||
XRRUpdateConfiguration (event);
|
||||
#else
|
||||
/* poke around in Xlib */
|
||||
screen->xscreen->width = event->xconfigure.width;
|
||||
screen->xscreen->height = event->xconfigure.height;
|
||||
#endif
|
||||
|
||||
meta_screen_resize (screen,
|
||||
event->xconfigure.width,
|
||||
event->xconfigure.height);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ConfigureRequest:
|
||||
/* This comment and code is found in both twm and fvwm */
|
||||
|
539
src/core/edid-parse.c
Normal file
539
src/core/edid-parse.c
Normal file
@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||
* the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Author: Soren Sandmann <sandmann@redhat.com> */
|
||||
|
||||
#include "edid.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <glib.h>
|
||||
|
||||
static int
|
||||
get_bit (int in, int bit)
|
||||
{
|
||||
return (in & (1 << bit)) >> bit;
|
||||
}
|
||||
|
||||
static int
|
||||
get_bits (int in, int begin, int end)
|
||||
{
|
||||
int mask = (1 << (end - begin + 1)) - 1;
|
||||
|
||||
return (in >> begin) & mask;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_header (const uchar *edid)
|
||||
{
|
||||
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int is_model_year;
|
||||
|
||||
/* Manufacturer Code */
|
||||
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
|
||||
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
|
||||
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
|
||||
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
|
||||
info->manufacturer_code[3] = '\0';
|
||||
|
||||
info->manufacturer_code[0] += 'A' - 1;
|
||||
info->manufacturer_code[1] += 'A' - 1;
|
||||
info->manufacturer_code[2] += 'A' - 1;
|
||||
|
||||
/* Product Code */
|
||||
info->product_code = edid[0x0b] << 8 | edid[0x0a];
|
||||
|
||||
/* Serial Number */
|
||||
info->serial_number =
|
||||
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
|
||||
|
||||
/* Week and Year */
|
||||
is_model_year = FALSE;
|
||||
switch (edid[0x10])
|
||||
{
|
||||
case 0x00:
|
||||
info->production_week = -1;
|
||||
break;
|
||||
|
||||
case 0xff:
|
||||
info->production_week = -1;
|
||||
is_model_year = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
info->production_week = edid[0x10];
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_model_year)
|
||||
{
|
||||
info->production_year = -1;
|
||||
info->model_year = 1990 + edid[0x11];
|
||||
}
|
||||
else
|
||||
{
|
||||
info->production_year = 1990 + edid[0x11];
|
||||
info->model_year = -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_edid_version (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->major_version = edid[0x12];
|
||||
info->minor_version = edid[0x13];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_display_parameters (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
/* Digital vs Analog */
|
||||
info->is_digital = get_bit (edid[0x14], 7);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
int bits;
|
||||
|
||||
static const int bit_depth[8] =
|
||||
{
|
||||
-1, 6, 8, 10, 12, 14, 16, -1
|
||||
};
|
||||
|
||||
static const Interface interfaces[6] =
|
||||
{
|
||||
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
|
||||
};
|
||||
|
||||
bits = get_bits (edid[0x14], 4, 6);
|
||||
info->connector.digital.bits_per_primary = bit_depth[bits];
|
||||
|
||||
bits = get_bits (edid[0x14], 0, 3);
|
||||
|
||||
if (bits <= 5)
|
||||
info->connector.digital.interface = interfaces[bits];
|
||||
else
|
||||
info->connector.digital.interface = UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x14], 5, 6);
|
||||
|
||||
static const double levels[][3] =
|
||||
{
|
||||
{ 0.7, 0.3, 1.0 },
|
||||
{ 0.714, 0.286, 1.0 },
|
||||
{ 1.0, 0.4, 1.4 },
|
||||
{ 0.7, 0.0, 0.7 },
|
||||
};
|
||||
|
||||
info->connector.analog.video_signal_level = levels[bits][0];
|
||||
info->connector.analog.sync_signal_level = levels[bits][1];
|
||||
info->connector.analog.total_signal_level = levels[bits][2];
|
||||
|
||||
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
|
||||
|
||||
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
|
||||
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
|
||||
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
|
||||
|
||||
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
|
||||
}
|
||||
|
||||
/* Screen Size / Aspect Ratio */
|
||||
if (edid[0x15] == 0 && edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = -1.0;
|
||||
}
|
||||
else if (edid[0x16] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
|
||||
}
|
||||
else if (edid[0x15] == 0)
|
||||
{
|
||||
info->width_mm = -1;
|
||||
info->height_mm = -1;
|
||||
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
|
||||
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
|
||||
}
|
||||
else
|
||||
{
|
||||
info->width_mm = 10 * edid[0x15];
|
||||
info->height_mm = 10 * edid[0x16];
|
||||
}
|
||||
|
||||
/* Gamma */
|
||||
if (edid[0x17] == 0xFF)
|
||||
info->gamma = -1.0;
|
||||
else
|
||||
info->gamma = (edid[0x17] + 100.0) / 100.0;
|
||||
|
||||
/* Features */
|
||||
info->standby = get_bit (edid[0x18], 7);
|
||||
info->suspend = get_bit (edid[0x18], 6);
|
||||
info->active_off = get_bit (edid[0x18], 5);
|
||||
|
||||
if (info->is_digital)
|
||||
{
|
||||
info->connector.digital.rgb444 = TRUE;
|
||||
if (get_bit (edid[0x18], 3))
|
||||
info->connector.digital.ycrcb444 = 1;
|
||||
if (get_bit (edid[0x18], 4))
|
||||
info->connector.digital.ycrcb422 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int bits = get_bits (edid[0x18], 3, 4);
|
||||
ColorType color_type[4] =
|
||||
{
|
||||
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
|
||||
};
|
||||
|
||||
info->connector.analog.color_type = color_type[bits];
|
||||
}
|
||||
|
||||
info->srgb_is_standard = get_bit (edid[0x18], 2);
|
||||
|
||||
/* In 1.3 this is called "has preferred timing" */
|
||||
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
|
||||
|
||||
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
|
||||
info->continuous_frequency = get_bit (edid[0x18], 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static double
|
||||
decode_fraction (int high, int low)
|
||||
{
|
||||
double result = 0.0;
|
||||
int i;
|
||||
|
||||
high = (high << 2) | low;
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
result += get_bit (high, i) * pow (2, i - 10);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
|
||||
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
|
||||
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
|
||||
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
|
||||
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
|
||||
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
|
||||
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
|
||||
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_established_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
static const Timing established[][8] =
|
||||
{
|
||||
{
|
||||
{ 800, 600, 60 },
|
||||
{ 800, 600, 56 },
|
||||
{ 640, 480, 75 },
|
||||
{ 640, 480, 72 },
|
||||
{ 640, 480, 67 },
|
||||
{ 640, 480, 60 },
|
||||
{ 720, 400, 88 },
|
||||
{ 720, 400, 70 }
|
||||
},
|
||||
{
|
||||
{ 1280, 1024, 75 },
|
||||
{ 1024, 768, 75 },
|
||||
{ 1024, 768, 70 },
|
||||
{ 1024, 768, 60 },
|
||||
{ 1024, 768, 87 },
|
||||
{ 832, 624, 75 },
|
||||
{ 800, 600, 75 },
|
||||
{ 800, 600, 72 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 0, 0, 0 },
|
||||
{ 1152, 870, 75 }
|
||||
},
|
||||
};
|
||||
|
||||
int i, j, idx;
|
||||
|
||||
idx = 0;
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
for (j = 0; j < 8; ++j)
|
||||
{
|
||||
int byte = edid[0x23 + i];
|
||||
|
||||
if (get_bit (byte, j) && established[i][j].frequency != 0)
|
||||
info->established[idx++] = established[i][j];
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_standard_timings (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
int first = edid[0x26 + 2 * i];
|
||||
int second = edid[0x27 + 2 * i];
|
||||
|
||||
if (first != 0x01 && second != 0x01)
|
||||
{
|
||||
int w = 8 * (first + 31);
|
||||
int h = 0;
|
||||
|
||||
switch (get_bits (second, 6, 7))
|
||||
{
|
||||
case 0x00: h = (w / 16) * 10; break;
|
||||
case 0x01: h = (w / 4) * 3; break;
|
||||
case 0x02: h = (w / 5) * 4; break;
|
||||
case 0x03: h = (w / 16) * 9; break;
|
||||
}
|
||||
|
||||
info->standard[i].width = w;
|
||||
info->standard[i].height = h;
|
||||
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_lf_string (const uchar *s, int n_chars, char *result)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n_chars; ++i)
|
||||
{
|
||||
if (s[i] == 0x0a)
|
||||
{
|
||||
*result++ = '\0';
|
||||
break;
|
||||
}
|
||||
else if (s[i] == 0x00)
|
||||
{
|
||||
/* Convert embedded 0's to spaces */
|
||||
*result++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*result++ = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_display_descriptor (const uchar *desc,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
switch (desc[0x03])
|
||||
{
|
||||
case 0xFC:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_product_name);
|
||||
break;
|
||||
case 0xFF:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
|
||||
break;
|
||||
case 0xFE:
|
||||
decode_lf_string (desc + 5, 13, info->dsc_string);
|
||||
break;
|
||||
case 0xFD:
|
||||
/* Range Limits */
|
||||
break;
|
||||
case 0xFB:
|
||||
/* Color Point */
|
||||
break;
|
||||
case 0xFA:
|
||||
/* Timing Identifications */
|
||||
break;
|
||||
case 0xF9:
|
||||
/* Color Management */
|
||||
break;
|
||||
case 0xF8:
|
||||
/* Timing Codes */
|
||||
break;
|
||||
case 0xF7:
|
||||
/* Established Timings */
|
||||
break;
|
||||
case 0x10:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
decode_detailed_timing (const uchar *timing,
|
||||
DetailedTiming *detailed)
|
||||
{
|
||||
int bits;
|
||||
StereoType stereo[] =
|
||||
{
|
||||
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
|
||||
};
|
||||
|
||||
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
|
||||
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
|
||||
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
|
||||
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
|
||||
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
|
||||
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
|
||||
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
|
||||
detailed->v_front_porch =
|
||||
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
|
||||
detailed->v_sync =
|
||||
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
|
||||
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
|
||||
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
|
||||
detailed->right_border = timing[0x0f];
|
||||
detailed->top_border = timing[0x10];
|
||||
|
||||
detailed->interlaced = get_bit (timing[0x11], 7);
|
||||
|
||||
/* Stereo */
|
||||
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
|
||||
detailed->stereo = stereo[bits];
|
||||
|
||||
/* Sync */
|
||||
bits = timing[0x11];
|
||||
|
||||
detailed->digital_sync = get_bit (bits, 4);
|
||||
if (detailed->digital_sync)
|
||||
{
|
||||
detailed->connector.digital.composite = !get_bit (bits, 3);
|
||||
|
||||
if (detailed->connector.digital.composite)
|
||||
{
|
||||
detailed->connector.digital.serrations = get_bit (bits, 2);
|
||||
detailed->connector.digital.negative_vsync = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.digital.serrations = FALSE;
|
||||
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
|
||||
}
|
||||
|
||||
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
detailed->connector.analog.bipolar = get_bit (bits, 3);
|
||||
detailed->connector.analog.serrations = get_bit (bits, 2);
|
||||
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
decode_descriptors (const uchar *edid, MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
int timing_idx;
|
||||
|
||||
timing_idx = 0;
|
||||
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
int index = 0x36 + i * 18;
|
||||
|
||||
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
|
||||
{
|
||||
decode_display_descriptor (edid + index, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
decode_detailed_timing (edid + index, &(info->detailed_timings[timing_idx++]));
|
||||
}
|
||||
}
|
||||
|
||||
info->n_detailed_timings = timing_idx;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_check_sum (const uchar *edid,
|
||||
MonitorInfo *info)
|
||||
{
|
||||
int i;
|
||||
uchar check = 0;
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
check += edid[i];
|
||||
|
||||
info->checksum = check;
|
||||
}
|
||||
|
||||
MonitorInfo *
|
||||
decode_edid (const uchar *edid)
|
||||
{
|
||||
MonitorInfo *info = g_new0 (MonitorInfo, 1);
|
||||
|
||||
decode_check_sum (edid, info);
|
||||
|
||||
if (decode_header (edid)
|
||||
&& decode_vendor_and_product_identification (edid, info)
|
||||
&& decode_edid_version (edid, info)
|
||||
&& decode_display_parameters (edid, info)
|
||||
&& decode_color_characteristics (edid, info)
|
||||
&& decode_established_timings (edid, info)
|
||||
&& decode_standard_timings (edid, info)
|
||||
&& decode_descriptors (edid, info))
|
||||
{
|
||||
return info;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (info);
|
||||
return NULL;
|
||||
}
|
||||
}
|
195
src/core/edid.h
Normal file
195
src/core/edid.h
Normal file
@ -0,0 +1,195 @@
|
||||
/* edid.h
|
||||
*
|
||||
* Copyright 2007, 2008, Red Hat, Inc.
|
||||
*
|
||||
* This file is part of the Gnome Library.
|
||||
*
|
||||
* The Gnome Library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* The Gnome Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef EDID_H
|
||||
#define EDID_H
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef struct MonitorInfo MonitorInfo;
|
||||
typedef struct Timing Timing;
|
||||
typedef struct DetailedTiming DetailedTiming;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED,
|
||||
DVI,
|
||||
HDMI_A,
|
||||
HDMI_B,
|
||||
MDDI,
|
||||
DISPLAY_PORT
|
||||
} Interface;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNDEFINED_COLOR,
|
||||
MONOCHROME,
|
||||
RGB,
|
||||
OTHER_COLOR
|
||||
} ColorType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NO_STEREO,
|
||||
FIELD_RIGHT,
|
||||
FIELD_LEFT,
|
||||
TWO_WAY_RIGHT_ON_EVEN,
|
||||
TWO_WAY_LEFT_ON_EVEN,
|
||||
FOUR_WAY_INTERLEAVED,
|
||||
SIDE_BY_SIDE
|
||||
} StereoType;
|
||||
|
||||
struct Timing
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int frequency;
|
||||
};
|
||||
|
||||
struct DetailedTiming
|
||||
{
|
||||
int pixel_clock;
|
||||
int h_addr;
|
||||
int h_blank;
|
||||
int h_sync;
|
||||
int h_front_porch;
|
||||
int v_addr;
|
||||
int v_blank;
|
||||
int v_sync;
|
||||
int v_front_porch;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
int right_border;
|
||||
int top_border;
|
||||
int interlaced;
|
||||
StereoType stereo;
|
||||
|
||||
int digital_sync;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bipolar;
|
||||
int serrations;
|
||||
int sync_on_green;
|
||||
} analog;
|
||||
|
||||
struct
|
||||
{
|
||||
int composite;
|
||||
int serrations;
|
||||
int negative_vsync;
|
||||
int negative_hsync;
|
||||
} digital;
|
||||
} connector;
|
||||
};
|
||||
|
||||
struct MonitorInfo
|
||||
{
|
||||
int checksum;
|
||||
char manufacturer_code[4];
|
||||
int product_code;
|
||||
unsigned int serial_number;
|
||||
|
||||
int production_week; /* -1 if not specified */
|
||||
int production_year; /* -1 if not specified */
|
||||
int model_year; /* -1 if not specified */
|
||||
|
||||
int major_version;
|
||||
int minor_version;
|
||||
|
||||
int is_digital;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int bits_per_primary;
|
||||
Interface interface;
|
||||
int rgb444;
|
||||
int ycrcb444;
|
||||
int ycrcb422;
|
||||
} digital;
|
||||
|
||||
struct
|
||||
{
|
||||
double video_signal_level;
|
||||
double sync_signal_level;
|
||||
double total_signal_level;
|
||||
|
||||
int blank_to_black;
|
||||
|
||||
int separate_hv_sync;
|
||||
int composite_sync_on_h;
|
||||
int composite_sync_on_green;
|
||||
int serration_on_vsync;
|
||||
ColorType color_type;
|
||||
} analog;
|
||||
} connector;
|
||||
|
||||
int width_mm; /* -1 if not specified */
|
||||
int height_mm; /* -1 if not specified */
|
||||
double aspect_ratio; /* -1.0 if not specififed */
|
||||
|
||||
double gamma; /* -1.0 if not specified */
|
||||
|
||||
int standby;
|
||||
int suspend;
|
||||
int active_off;
|
||||
|
||||
int srgb_is_standard;
|
||||
int preferred_timing_includes_native;
|
||||
int continuous_frequency;
|
||||
|
||||
double red_x;
|
||||
double red_y;
|
||||
double green_x;
|
||||
double green_y;
|
||||
double blue_x;
|
||||
double blue_y;
|
||||
double white_x;
|
||||
double white_y;
|
||||
|
||||
Timing established[24]; /* Terminated by 0x0x0 */
|
||||
Timing standard[8];
|
||||
|
||||
int n_detailed_timings;
|
||||
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
|
||||
* mode, it is the first one
|
||||
* (whether it has, is
|
||||
* determined by the
|
||||
* preferred_timing_includes
|
||||
* bit.
|
||||
*/
|
||||
|
||||
/* Optional product description */
|
||||
char dsc_serial_number[14];
|
||||
char dsc_product_name[14];
|
||||
char dsc_string[14]; /* Unspecified ASCII data */
|
||||
};
|
||||
|
||||
MonitorInfo *decode_edid (const uchar *data);
|
||||
char *make_display_name (const MonitorInfo *info);
|
||||
char *make_display_size_string (int width_mm, int height_mm);
|
||||
|
||||
#endif
|
34
src/core/meta-cursor-tracker-private.h
Normal file
34
src/core/meta-cursor-tracker-private.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_TRACKER_PRIVATE_H
|
||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent);
|
||||
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor);
|
||||
#endif
|
275
src/core/meta-cursor-tracker.c
Normal file
275
src/core/meta-cursor-tracker.c
Normal file
@ -0,0 +1,275 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright 2013 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:cursor-tracker
|
||||
* @title: MetaCursorTracker
|
||||
* @short_description: Mutter cursor tracking helper
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/util.h>
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
|
||||
gboolean is_showing;
|
||||
|
||||
CoglTexture2D *sprite;
|
||||
int hot_x, hot_y;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
CURSOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
|
||||
* detecting if the system mouse cursor is showing or not.
|
||||
*
|
||||
* On wayland we start with the cursor showing
|
||||
*/
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
|
||||
|
||||
if (self->sprite)
|
||||
cogl_object_unref (self->sprite);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_cursor_tracker_finalize;
|
||||
|
||||
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
|
||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_get_for_screen:
|
||||
* @screen: the #MetaScreen
|
||||
*
|
||||
* Retrieves the cursor tracker object for @screen.
|
||||
*
|
||||
* Returns: (transfer none):
|
||||
*/
|
||||
MetaCursorTracker *
|
||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCursorTracker *self;
|
||||
|
||||
if (screen->cursor_tracker)
|
||||
return screen->cursor_tracker;
|
||||
|
||||
self = make_x11_cursor_tracker (screen);
|
||||
|
||||
screen->cursor_tracker = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
g_clear_pointer (&tracker->sprite, cogl_object_unref);
|
||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
XFixesCursorImage *cursor_image;
|
||||
CoglTexture2D *sprite;
|
||||
guint8 *cursor_data;
|
||||
gboolean free_cursor_data;
|
||||
CoglContext *ctx;
|
||||
|
||||
if (tracker->sprite)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
|
||||
* quantities as arrays of long; we need to convert on 64 bit */
|
||||
if (sizeof(long) == 4)
|
||||
{
|
||||
cursor_data = (guint8 *)cursor_image->pixels;
|
||||
free_cursor_data = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
guint32 *cursor_words;
|
||||
gulong *p;
|
||||
guint32 *q;
|
||||
|
||||
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
|
||||
cursor_data = (guint8 *)cursor_words;
|
||||
|
||||
p = cursor_image->pixels;
|
||||
q = cursor_words;
|
||||
for (j = 0; j < cursor_image->height; j++)
|
||||
for (i = 0; i < cursor_image->width; i++)
|
||||
*(q++) = *(p++);
|
||||
|
||||
free_cursor_data = TRUE;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
sprite = cogl_texture_2d_new_from_data (ctx,
|
||||
cursor_image->width,
|
||||
cursor_image->height,
|
||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
cursor_image->width * 4, /* stride */
|
||||
cursor_data,
|
||||
NULL);
|
||||
|
||||
if (free_cursor_data)
|
||||
g_free (cursor_data);
|
||||
|
||||
if (sprite != NULL)
|
||||
{
|
||||
tracker->sprite = sprite;
|
||||
tracker->hot_x = cursor_image->xhot;
|
||||
tracker->hot_y = cursor_image->yhot;
|
||||
}
|
||||
XFree (cursor_image);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_get_sprite:
|
||||
*
|
||||
* Returns: (transfer none):
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||
|
||||
ensure_xfixes_cursor (tracker);
|
||||
|
||||
return COGL_TEXTURE (tracker->sprite);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_get_hot:
|
||||
* @tracker:
|
||||
* @x: (out):
|
||||
* @y: (out):
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
ensure_xfixes_cursor (tracker);
|
||||
|
||||
if (x)
|
||||
*x = tracker->hot_x;
|
||||
if (y)
|
||||
*y = tracker->hot_y;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
MetaDisplay *display = tracker->screen->display;
|
||||
|
||||
/* First create a cursor for X11 applications that don't specify their own */
|
||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||
|
||||
XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
|
||||
XFlush (display->xdisplay);
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
}
|
40
src/core/meta-xrandr-shared.h
Normal file
40
src/core/meta-xrandr-shared.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
|
||||
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
|
||||
|
||||
The canonical place for all changes is mutter.
|
||||
|
||||
There should be no includes in this file.
|
||||
*/
|
||||
|
||||
#ifndef META_XRANDR_SHARED_H
|
||||
#define META_XRANDR_SHARED_H
|
||||
|
||||
typedef enum {
|
||||
META_POWER_SAVE_UNKNOWN = -1,
|
||||
META_POWER_SAVE_ON = 0,
|
||||
META_POWER_SAVE_STANDBY,
|
||||
META_POWER_SAVE_SUSPEND,
|
||||
META_POWER_SAVE_OFF,
|
||||
} MetaPowerSave;
|
||||
|
||||
#endif
|
1769
src/core/monitor-config.c
Normal file
1769
src/core/monitor-config.c
Normal file
File diff suppressed because it is too large
Load Diff
390
src/core/monitor-private.h
Normal file
390
src/core/monitor-private.h
Normal file
@ -0,0 +1,390 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file screen-private.h Handling of monitor configuration
|
||||
*
|
||||
* Managing multiple monitors
|
||||
* This file contains structures and functions that handle
|
||||
* multiple monitors, including reading the current configuration
|
||||
* and available hardware, and applying it.
|
||||
*
|
||||
* This interface is private to mutter, API users should look
|
||||
* at MetaScreen instead.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2003 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
* Copyright (C) 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_MONITOR_PRIVATE_H
|
||||
#define META_MONITOR_PRIVATE_H
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <libgnome-desktop/gnome-pnp-ids.h>
|
||||
|
||||
#include "display-private.h"
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
#endif
|
||||
#include "meta-xrandr-shared.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
||||
typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
|
||||
typedef struct _MetaMonitorConfig MetaMonitorConfig;
|
||||
|
||||
#ifndef HAVE_WAYLAND
|
||||
enum wl_output_transform {
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
WL_OUTPUT_TRANSFORM_90,
|
||||
WL_OUTPUT_TRANSFORM_180,
|
||||
WL_OUTPUT_TRANSFORM_270,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct _MetaOutput MetaOutput;
|
||||
typedef struct _MetaCRTC MetaCRTC;
|
||||
typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
MetaCRTC *crtc;
|
||||
/* The low-level ID of this output, used to apply back configuration */
|
||||
glong output_id;
|
||||
char *name;
|
||||
char *vendor;
|
||||
char *product;
|
||||
char *serial;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
CoglSubpixelOrder subpixel_order;
|
||||
|
||||
MetaMonitorMode *preferred_mode;
|
||||
MetaMonitorMode **modes;
|
||||
unsigned int n_modes;
|
||||
|
||||
MetaCRTC **possible_crtcs;
|
||||
unsigned int n_possible_crtcs;
|
||||
|
||||
MetaOutput **possible_clones;
|
||||
unsigned int n_possible_clones;
|
||||
|
||||
int backlight;
|
||||
int backlight_min;
|
||||
int backlight_max;
|
||||
|
||||
/* Used when changing configuration */
|
||||
gboolean is_dirty;
|
||||
|
||||
/* The low-level bits used to build the high-level info
|
||||
in MetaMonitorInfo
|
||||
|
||||
XXX: flags maybe?
|
||||
There is a lot of code that uses MonitorInfo->is_primary,
|
||||
but nobody uses MetaOutput yet
|
||||
*/
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
};
|
||||
|
||||
struct _MetaCRTC
|
||||
{
|
||||
glong crtc_id;
|
||||
MetaRectangle rect;
|
||||
MetaMonitorMode *current_mode;
|
||||
enum wl_output_transform transform;
|
||||
unsigned int all_transforms;
|
||||
|
||||
/* Only used to build the logical configuration
|
||||
from the HW one
|
||||
*/
|
||||
MetaMonitorInfo *logical_monitor;
|
||||
|
||||
/* Used when changing configuration */
|
||||
gboolean is_dirty;
|
||||
};
|
||||
|
||||
struct _MetaMonitorMode
|
||||
{
|
||||
/* The low-level ID of this mode, used to apply back configuration */
|
||||
glong mode_id;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
float refresh_rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaMonitorInfo:
|
||||
*
|
||||
* A structure with high-level information about monitors.
|
||||
* This corresponds to a subset of the compositor coordinate space.
|
||||
* Clones are only reported once, irrespective of the way
|
||||
* they're implemented (two CRTCs configured for the same
|
||||
* coordinates or one CRTCs driving two outputs). Inactive CRTCs
|
||||
* are ignored, and so are disabled outputs.
|
||||
*/
|
||||
struct _MetaMonitorInfo
|
||||
{
|
||||
int number;
|
||||
int xinerama_index;
|
||||
MetaRectangle rect;
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation; /* XXX: not yet used */
|
||||
gboolean in_fullscreen;
|
||||
|
||||
/* The primary or first output for this monitor, 0 if we can't figure out.
|
||||
It can be matched to an output_id of a MetaOutput.
|
||||
|
||||
This is used as an opaque token on reconfiguration when switching from
|
||||
clone to extened, to decide on what output the windows should go next
|
||||
(it's an attempt to keep windows on the same monitor, and preferably on
|
||||
the primary one).
|
||||
*/
|
||||
glong output_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* MetaCRTCInfo:
|
||||
* This represents the writable part of a CRTC, as deserialized from DBus
|
||||
* or built by MetaMonitorConfig
|
||||
*
|
||||
* Note: differently from the other structures in this file, MetaCRTCInfo
|
||||
* is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
|
||||
*/
|
||||
struct _MetaCRTCInfo {
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
int x;
|
||||
int y;
|
||||
enum wl_output_transform transform;
|
||||
GPtrArray *outputs;
|
||||
};
|
||||
|
||||
/*
|
||||
* MetaOutputInfo:
|
||||
* this is the same as MetaOutputInfo, but for CRTCs
|
||||
*/
|
||||
struct _MetaOutputInfo {
|
||||
MetaOutput *output;
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
};
|
||||
|
||||
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
|
||||
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
|
||||
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
|
||||
#define META_IS_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER))
|
||||
#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER))
|
||||
#define META_MONITOR_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
|
||||
|
||||
struct _MetaMonitorManager
|
||||
{
|
||||
MetaDBusDisplayConfigSkeleton parent_instance;
|
||||
|
||||
/* XXX: this structure is very badly
|
||||
packed, but I like the logical organization
|
||||
of fields */
|
||||
|
||||
gboolean in_init;
|
||||
unsigned int serial;
|
||||
|
||||
MetaPowerSave power_save_mode;
|
||||
|
||||
int max_screen_width;
|
||||
int max_screen_height;
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
|
||||
/* Outputs refer to physical screens,
|
||||
CRTCs refer to stuff that can drive outputs
|
||||
(like encoders, but less tied to the HW),
|
||||
while monitor_infos refer to logical ones.
|
||||
|
||||
See also the comment in monitor-private.h
|
||||
*/
|
||||
MetaOutput *outputs;
|
||||
unsigned int n_outputs;
|
||||
|
||||
MetaMonitorMode *modes;
|
||||
unsigned int n_modes;
|
||||
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int n_crtcs;
|
||||
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
unsigned int n_monitor_infos;
|
||||
int primary_monitor_index;
|
||||
|
||||
int dbus_name_id;
|
||||
|
||||
int persistent_timeout_id;
|
||||
MetaMonitorConfig *config;
|
||||
|
||||
GnomePnpIds *pnp_ids;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerClass
|
||||
{
|
||||
MetaDBusDisplayConfigSkeletonClass parent_class;
|
||||
|
||||
void (*read_current) (MetaMonitorManager *);
|
||||
|
||||
char* (*get_edid_file) (MetaMonitorManager *,
|
||||
MetaOutput *);
|
||||
GBytes* (*read_edid) (MetaMonitorManager *,
|
||||
MetaOutput *);
|
||||
|
||||
void (*apply_configuration) (MetaMonitorManager *,
|
||||
MetaCRTCInfo **,
|
||||
unsigned int ,
|
||||
MetaOutputInfo **,
|
||||
unsigned int);
|
||||
|
||||
void (*set_power_save_mode) (MetaMonitorManager *,
|
||||
MetaPowerSave);
|
||||
|
||||
void (*change_backlight) (MetaMonitorManager *,
|
||||
MetaOutput *,
|
||||
int);
|
||||
|
||||
void (*get_crtc_gamma) (MetaMonitorManager *,
|
||||
MetaCRTC *,
|
||||
gsize *,
|
||||
unsigned short **,
|
||||
unsigned short **,
|
||||
unsigned short **);
|
||||
void (*set_crtc_gamma) (MetaMonitorManager *,
|
||||
MetaCRTC *,
|
||||
gsize ,
|
||||
unsigned short *,
|
||||
unsigned short *,
|
||||
unsigned short *);
|
||||
|
||||
gboolean (*handle_xevent) (MetaMonitorManager *,
|
||||
XEvent *);
|
||||
};
|
||||
|
||||
GType meta_monitor_manager_get_type (void);
|
||||
|
||||
void meta_monitor_manager_initialize (void);
|
||||
MetaMonitorManager *meta_monitor_manager_get (void);
|
||||
|
||||
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
|
||||
unsigned int *n_infos);
|
||||
|
||||
MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
|
||||
unsigned int *n_outputs);
|
||||
|
||||
void meta_monitor_manager_get_resources (MetaMonitorManager *manager,
|
||||
MetaMonitorMode **modes,
|
||||
unsigned int *n_modes,
|
||||
MetaCRTC **crtcs,
|
||||
unsigned int *n_crtcs,
|
||||
MetaOutput **outputs,
|
||||
unsigned int *n_outputs);
|
||||
|
||||
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event);
|
||||
|
||||
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
void meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
|
||||
MetaCRTCInfo **crtcs,
|
||||
unsigned int n_crtcs,
|
||||
MetaOutputInfo **outputs,
|
||||
unsigned int n_outputs);
|
||||
|
||||
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
|
||||
gboolean ok);
|
||||
|
||||
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
|
||||
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
|
||||
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
||||
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
|
||||
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
|
||||
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
||||
|
||||
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
|
||||
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
||||
|
||||
GType meta_monitor_manager_xrandr_get_type (void);
|
||||
|
||||
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
||||
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
||||
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
|
||||
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
|
||||
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||
|
||||
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaMonitorConfig *meta_monitor_config_new (void);
|
||||
|
||||
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
void meta_monitor_config_make_default (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
void meta_monitor_config_update_current (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
|
||||
|
||||
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
void meta_crtc_info_free (MetaCRTCInfo *info);
|
||||
void meta_output_info_free (MetaOutputInfo *info);
|
||||
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
static inline gboolean
|
||||
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
|
||||
{
|
||||
return (transform % 2);
|
||||
}
|
||||
|
||||
#endif
|
1009
src/core/monitor-xrandr.c
Normal file
1009
src/core/monitor-xrandr.c
Normal file
File diff suppressed because it is too large
Load Diff
1548
src/core/monitor.c
Normal file
1548
src/core/monitor.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -38,17 +38,7 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
|
||||
struct _MetaMonitorInfo
|
||||
{
|
||||
int number;
|
||||
MetaRectangle rect;
|
||||
gboolean is_primary;
|
||||
gboolean in_fullscreen;
|
||||
XID output; /* The primary or first output for this crtc, None if no xrandr */
|
||||
};
|
||||
#include "monitor-private.h"
|
||||
|
||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||
gpointer user_data);
|
||||
@ -93,6 +83,7 @@ struct _MetaScreen
|
||||
MetaStack *stack;
|
||||
MetaStackTracker *stack_tracker;
|
||||
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
MetaCursor current_cursor;
|
||||
|
||||
Window flash_window;
|
||||
@ -100,10 +91,11 @@ struct _MetaScreen
|
||||
Window wm_sn_selection_window;
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
|
||||
|
||||
MetaMonitorInfo *monitor_infos;
|
||||
int primary_monitor_index;
|
||||
int n_monitor_infos;
|
||||
int primary_monitor_index;
|
||||
gboolean has_xinerama_indices;
|
||||
|
||||
/* Cache the current monitor */
|
||||
int last_monitor_index;
|
||||
@ -231,10 +223,6 @@ void meta_screen_calc_workspace_layout (MetaScreen *screen,
|
||||
MetaWorkspaceLayout *layout);
|
||||
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
|
||||
|
||||
void meta_screen_resize (MetaScreen *screen,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
|
||||
MetaWindow *keep);
|
||||
|
||||
@ -257,4 +245,12 @@ 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);
|
||||
|
||||
gboolean meta_screen_handle_xevent (MetaScreen *screen,
|
||||
XEvent *xevent);
|
||||
|
||||
#endif
|
||||
|
@ -45,13 +45,10 @@
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
@ -76,6 +73,9 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
|
||||
void *user_data);
|
||||
#endif
|
||||
|
||||
static void on_monitors_changed (MetaMonitorManager *manager,
|
||||
MetaScreen *screen);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_N_WORKSPACES = 1,
|
||||
@ -350,250 +350,93 @@ set_wm_icon_size_hint (MetaScreen *screen)
|
||||
#undef N_VALS
|
||||
}
|
||||
|
||||
/* The list of monitors reported by the windowing system might include
|
||||
* mirrored monitors with identical bounds. Since mirrored monitors
|
||||
* shouldn't be treated as separate monitors for most purposes, we
|
||||
* filter them out here. (We ignore the possibility of partially
|
||||
* overlapping monitors because they are rare and it's hard to come
|
||||
* up with any sensible interpretation.)
|
||||
*/
|
||||
static void
|
||||
filter_mirrored_monitors (MetaScreen *screen)
|
||||
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
|
||||
{
|
||||
int i, j;
|
||||
XineramaScreenInfo *infos;
|
||||
int n_infos, i, j;
|
||||
|
||||
/* Currently always true and simplifies things */
|
||||
g_assert (screen->primary_monitor_index == 0);
|
||||
if (screen->has_xinerama_indices)
|
||||
return;
|
||||
|
||||
for (i = 1; i < screen->n_monitor_infos; i++)
|
||||
screen->has_xinerama_indices = TRUE;
|
||||
|
||||
if (!XineramaIsActive (screen->display->xdisplay))
|
||||
return;
|
||||
|
||||
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
|
||||
if (n_infos <= 0 || infos == NULL)
|
||||
{
|
||||
/* In case we've filtered previous monitors */
|
||||
screen->monitor_infos[i].number = i;
|
||||
meta_XFree (infos);
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
for (i = 0; i < screen->n_monitor_infos; ++i)
|
||||
{
|
||||
for (j = 0; j < n_infos; ++j)
|
||||
{
|
||||
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
|
||||
&screen->monitor_infos[j].rect))
|
||||
{
|
||||
memmove (&screen->monitor_infos[i],
|
||||
&screen->monitor_infos[i + 1],
|
||||
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
|
||||
screen->n_monitor_infos--;
|
||||
i--;
|
||||
|
||||
continue;
|
||||
}
|
||||
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
|
||||
screen->monitor_infos[i].rect.y == infos[j].y_org &&
|
||||
screen->monitor_infos[i].rect.width == infos[j].width &&
|
||||
screen->monitor_infos[i].rect.height == infos[j].height)
|
||||
screen->monitor_infos[i].xinerama_index = j;
|
||||
}
|
||||
}
|
||||
|
||||
meta_XFree (infos);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
static MetaMonitorInfo *
|
||||
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
|
||||
int
|
||||
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
||||
int index)
|
||||
{
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
return screen->monitor_infos[index].xinerama_index;
|
||||
}
|
||||
|
||||
int
|
||||
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
|
||||
int index)
|
||||
{
|
||||
MetaMonitorInfo *info;
|
||||
int i;
|
||||
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
info = &screen->monitor_infos[i];
|
||||
if (x == info->rect.x &&
|
||||
y == info->rect.y &&
|
||||
w == info->rect.width &&
|
||||
h == info->rect.height)
|
||||
return info;
|
||||
}
|
||||
return NULL;
|
||||
if (screen->monitor_infos[i].xinerama_index == index)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
|
||||
* outputs the "main". This is the one we consider "owning" the windows, so if
|
||||
* the mirroring is changed to a dual monitor setup then the windows are moved to the
|
||||
* crtc that now has that main output. If one of the outputs is the primary that is
|
||||
* always the main, otherwise we just use the first.
|
||||
*/
|
||||
static XID
|
||||
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
|
||||
{
|
||||
XRROutputInfo *output;
|
||||
RROutput primary_output;
|
||||
int i;
|
||||
XID res;
|
||||
|
||||
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
|
||||
|
||||
res = None;
|
||||
for (i = 0; i < crtc->noutput; i++)
|
||||
{
|
||||
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
|
||||
if (output->connection != RR_Disconnected &&
|
||||
(res == None || crtc->outputs[i] == primary_output))
|
||||
res = crtc->outputs[i];
|
||||
XRRFreeOutputInfo (output);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
reload_monitor_infos (MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
GList *tmp;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
{
|
||||
GList *tmp;
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
|
||||
tmp = screen->workspaces;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWorkspace *space = tmp->data;
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
meta_workspace_invalidate_work_area (space);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
|
||||
|
||||
display = screen->display;
|
||||
|
||||
/* Any previous screen->monitor_infos is freed by the caller */
|
||||
|
||||
screen->monitor_infos = NULL;
|
||||
screen->n_monitor_infos = 0;
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
/* Xinerama doesn't have a concept of primary monitor, however XRandR
|
||||
* does. However, the XRandR xinerama compat code always sorts the
|
||||
* primary output first, so we rely on that here. We could use the
|
||||
* native XRandR calls instead of xinerama, but that would be
|
||||
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
|
||||
* that is defined in terms of xinerama monitor indexes.
|
||||
* So, since we don't need anything in xrandr except the primary
|
||||
* we can keep using xinerama and use the first monitor as the
|
||||
* primary.
|
||||
*/
|
||||
screen->primary_monitor_index = 0;
|
||||
|
||||
screen->has_xinerama_indices = FALSE;
|
||||
screen->display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Pretending a single monitor has two Xinerama screens\n");
|
||||
manager = meta_monitor_manager_get ();
|
||||
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
|
||||
screen->n_monitor_infos = 2;
|
||||
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
|
||||
screen->monitor_infos[1].number = 1;
|
||||
screen->monitor_infos[1].rect = screen->rect;
|
||||
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
|
||||
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
}
|
||||
|
||||
if (screen->n_monitor_infos == 0 &&
|
||||
XineramaIsActive (display->xdisplay))
|
||||
{
|
||||
XineramaScreenInfo *infos;
|
||||
int n_infos;
|
||||
int i;
|
||||
|
||||
n_infos = 0;
|
||||
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Found %d Xinerama screens on display %s\n",
|
||||
n_infos, display->name);
|
||||
|
||||
if (n_infos > 0)
|
||||
{
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
|
||||
screen->n_monitor_infos = n_infos;
|
||||
|
||||
i = 0;
|
||||
while (i < n_infos)
|
||||
{
|
||||
screen->monitor_infos[i].number = infos[i].screen_number;
|
||||
screen->monitor_infos[i].rect.x = infos[i].x_org;
|
||||
screen->monitor_infos[i].rect.y = infos[i].y_org;
|
||||
screen->monitor_infos[i].rect.width = infos[i].width;
|
||||
screen->monitor_infos[i].rect.height = infos[i].height;
|
||||
screen->monitor_infos[i].in_fullscreen = -1;
|
||||
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"Monitor %d is %d,%d %d x %d\n",
|
||||
screen->monitor_infos[i].number,
|
||||
screen->monitor_infos[i].rect.x,
|
||||
screen->monitor_infos[i].rect.y,
|
||||
screen->monitor_infos[i].rect.width,
|
||||
screen->monitor_infos[i].rect.height);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
meta_XFree (infos);
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
{
|
||||
XRRScreenResources *resources;
|
||||
|
||||
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
|
||||
if (resources)
|
||||
{
|
||||
for (i = 0; i < resources->ncrtc; i++)
|
||||
{
|
||||
XRRCrtcInfo *crtc;
|
||||
MetaMonitorInfo *info;
|
||||
|
||||
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
|
||||
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
|
||||
if (info)
|
||||
info->output = find_main_output_for_crtc (screen, resources, crtc);
|
||||
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
XRRFreeScreenResources (resources);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (screen->n_monitor_infos > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Xinerama extension or Xinerama inactive on display %s\n",
|
||||
display->name);
|
||||
}
|
||||
|
||||
/* If no Xinerama, fill in the single screen info so
|
||||
* we can use the field unconditionally
|
||||
*/
|
||||
if (screen->n_monitor_infos == 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_XINERAMA,
|
||||
"No Xinerama screens, using default screen info\n");
|
||||
|
||||
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
|
||||
screen->n_monitor_infos = 1;
|
||||
|
||||
screen->monitor_infos[0].number = 0;
|
||||
screen->monitor_infos[0].rect = screen->rect;
|
||||
screen->monitor_infos[0].in_fullscreen = -1;
|
||||
}
|
||||
|
||||
filter_mirrored_monitors (screen);
|
||||
|
||||
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
|
||||
|
||||
g_assert (screen->n_monitor_infos > 0);
|
||||
g_assert (screen->monitor_infos != NULL);
|
||||
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
|
||||
(unsigned*)&screen->n_monitor_infos);
|
||||
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
|
||||
}
|
||||
|
||||
/* The guard window allows us to leave minimized windows mapped so
|
||||
@ -668,6 +511,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
char buf[128];
|
||||
guint32 manager_timestamp;
|
||||
gulong current_workspace;
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
replace_current_wm = meta_get_replace_current_wm ();
|
||||
|
||||
@ -826,8 +670,17 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->xroot = xroot;
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
screen->rect.width = WidthOfScreen (screen->xscreen);
|
||||
screen->rect.height = HeightOfScreen (screen->xscreen);
|
||||
|
||||
meta_monitor_manager_initialize ();
|
||||
|
||||
manager = meta_monitor_manager_get ();
|
||||
g_signal_connect (manager, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), screen);
|
||||
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
@ -852,12 +705,9 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->compositor_data = NULL;
|
||||
screen->guard_window = None;
|
||||
|
||||
screen->monitor_infos = NULL;
|
||||
screen->n_monitor_infos = 0;
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
|
||||
meta_cursor_tracker_get_for_screen (screen);
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
|
||||
/* Handle creating a no_focus_window for this screen */
|
||||
@ -941,7 +791,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;
|
||||
}
|
||||
|
||||
@ -1613,29 +1463,18 @@ void
|
||||
meta_screen_set_cursor (MetaScreen *screen,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
|
||||
if (cursor == screen->current_cursor)
|
||||
return;
|
||||
|
||||
screen->current_cursor = cursor;
|
||||
|
||||
xcursor = meta_display_create_x_cursor (screen->display, cursor);
|
||||
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
|
||||
XFlush (screen->display->xdisplay);
|
||||
XFreeCursor (screen->display->xdisplay, xcursor);
|
||||
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_update_cursor (MetaScreen *screen)
|
||||
{
|
||||
Cursor xcursor;
|
||||
|
||||
xcursor = meta_display_create_x_cursor (screen->display,
|
||||
screen->current_cursor);
|
||||
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
|
||||
XFlush (screen->display->xdisplay);
|
||||
XFreeCursor (screen->display->xdisplay, xcursor);
|
||||
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
|
||||
screen->current_cursor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2997,19 +2836,15 @@ meta_screen_resize_func (MetaScreen *screen,
|
||||
meta_window_recalc_features (window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_resize (MetaScreen *screen,
|
||||
int width,
|
||||
int height)
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *manager,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
GSList *windows, *tmp;
|
||||
MetaMonitorInfo *old_monitor_infos;
|
||||
GSList *tmp, *windows;
|
||||
|
||||
screen->rect.width = width;
|
||||
screen->rect.height = height;
|
||||
|
||||
/* Save the old monitor infos, so they stay valid during the update */
|
||||
old_monitor_infos = screen->monitor_infos;
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
set_desktop_geometry_hint (screen);
|
||||
@ -3021,8 +2856,8 @@ meta_screen_resize (MetaScreen *screen,
|
||||
|
||||
changes.x = 0;
|
||||
changes.y = 0;
|
||||
changes.width = width;
|
||||
changes.height = height;
|
||||
changes.width = screen->rect.width;
|
||||
changes.height = screen->rect.height;
|
||||
|
||||
XConfigureWindow(screen->display->xdisplay,
|
||||
screen->guard_window,
|
||||
@ -3032,7 +2867,8 @@ meta_screen_resize (MetaScreen *screen,
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen, width, height);
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
|
||||
/* Queue a resize on all the windows */
|
||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||
@ -3048,7 +2884,6 @@ meta_screen_resize (MetaScreen *screen,
|
||||
meta_window_update_for_monitors_changed (window);
|
||||
}
|
||||
|
||||
g_free (old_monitor_infos);
|
||||
g_slist_free (windows);
|
||||
|
||||
meta_screen_queue_check_fullscreen (screen);
|
||||
@ -3844,3 +3679,17 @@ meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
|
||||
/* We use -1 as a flag to mean "not known yet" for notification purposes */
|
||||
return screen->monitor_infos[monitor].in_fullscreen == TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_screen_handle_xevent (MetaScreen *screen,
|
||||
XEvent *xevent)
|
||||
{
|
||||
/* Go through our helpers and see if they want this event.
|
||||
Currently, only MetaCursorTracker.
|
||||
*/
|
||||
|
||||
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -332,6 +332,8 @@ topic_name (MetaDebugTopic topic)
|
||||
return "COMPOSITOR";
|
||||
case META_DEBUG_EDGE_RESISTANCE:
|
||||
return "EDGE_RESISTANCE";
|
||||
case META_DEBUG_DBUS:
|
||||
return "DBUS";
|
||||
case META_DEBUG_VERBOSE:
|
||||
return "VERBOSE";
|
||||
}
|
||||
@ -637,8 +639,13 @@ meta_show_dialog (const char *type,
|
||||
|
||||
append_argument (args, "zenity");
|
||||
append_argument (args, type);
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
|
||||
if (display)
|
||||
{
|
||||
append_argument (args, "--display");
|
||||
append_argument (args, display);
|
||||
}
|
||||
|
||||
append_argument (args, "--class");
|
||||
append_argument (args, "mutter-dialog");
|
||||
append_argument (args, "--title");
|
||||
|
@ -165,7 +165,7 @@ struct _MetaWindow
|
||||
* been overridden (via a client message), the window will cover the union of
|
||||
* these monitors. If not, this is the single monitor which the window's
|
||||
* origin is on. */
|
||||
long fullscreen_monitors[4];
|
||||
gint fullscreen_monitors[4];
|
||||
|
||||
/* Whether we're trying to constrain the window to be fully onscreen */
|
||||
guint require_fully_onscreen : 1;
|
||||
|
@ -2108,10 +2108,14 @@ set_net_wm_state (MetaWindow *window)
|
||||
|
||||
if (window->fullscreen)
|
||||
{
|
||||
data[0] = window->fullscreen_monitors[0];
|
||||
data[1] = window->fullscreen_monitors[1];
|
||||
data[2] = window->fullscreen_monitors[2];
|
||||
data[3] = window->fullscreen_monitors[3];
|
||||
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[0]);
|
||||
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[1]);
|
||||
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[2]);
|
||||
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
|
||||
window->fullscreen_monitors[3]);
|
||||
|
||||
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
|
||||
meta_error_trap_push (window->display);
|
||||
@ -4785,7 +4789,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
{
|
||||
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
|
||||
|
||||
if (info->output == old->output)
|
||||
if (info->output_id != 0 &&
|
||||
info->output_id == old->output_id)
|
||||
{
|
||||
new = info;
|
||||
break;
|
||||
@ -7130,10 +7135,14 @@ meta_window_client_message (MetaWindow *window,
|
||||
meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
|
||||
window->desc);
|
||||
|
||||
top = event->xclient.data.l[0];
|
||||
bottom = event->xclient.data.l[1];
|
||||
left = event->xclient.data.l[2];
|
||||
right = event->xclient.data.l[3];
|
||||
top = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[0]);
|
||||
bottom = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[1]);
|
||||
left = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[2]);
|
||||
right = meta_screen_xinerama_index_to_monitor_index (window->screen,
|
||||
event->xclient.data.l[3]);
|
||||
/* source_indication = event->xclient.data.l[4]; */
|
||||
|
||||
meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
|
||||
|
@ -72,6 +72,7 @@ item(_MUTTER_TIMESTAMP_PING)
|
||||
item(_MUTTER_FOCUS_SET)
|
||||
item(_MUTTER_SENTINEL)
|
||||
item(_MUTTER_VERSION)
|
||||
item(_MUTTER_PRESENTATION_OUTPUT)
|
||||
item(WM_CLIENT_MACHINE)
|
||||
item(MANAGER)
|
||||
item(TARGETS)
|
||||
@ -79,6 +80,7 @@ item(MULTIPLE)
|
||||
item(TIMESTAMP)
|
||||
item(VERSION)
|
||||
item(ATOM_PAIR)
|
||||
item(BACKLIGHT)
|
||||
|
||||
/* Oddities: These are used, and we need atoms for them,
|
||||
* but when we need all _NET_WM hints (i.e. when we're making
|
||||
|
50
src/meta/meta-cursor-tracker.h
Normal file
50
src/meta/meta-cursor-tracker.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_TRACKER_H
|
||||
#define META_CURSOR_TRACKER_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <meta/types.h>
|
||||
#include <meta/workspace.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#define META_TYPE_CURSOR_TRACKER (meta_cursor_tracker_get_type ())
|
||||
#define META_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTracker))
|
||||
#define META_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER, MetaCursorTrackerClass))
|
||||
#define META_IS_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER))
|
||||
#define META_IS_CURSOR_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER))
|
||||
#define META_CURSOR_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTrackerClass))
|
||||
|
||||
typedef struct _MetaCursorTrackerClass MetaCursorTrackerClass;
|
||||
|
||||
GType meta_cursor_tracker_get_type (void);
|
||||
|
||||
MetaCursorTracker *meta_cursor_tracker_get_for_screen (MetaScreen *screen);
|
||||
|
||||
void meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y);
|
||||
CoglTexture *meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker);
|
||||
|
||||
#endif
|
@ -205,6 +205,21 @@ struct _MetaPluginClass
|
||||
gboolean (*keybinding_filter) (MetaPlugin *plugin,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::confirm_display_config:
|
||||
* @plugin: a #MetaPlugin
|
||||
*
|
||||
* Virtual function called when the display configuration changes.
|
||||
* The common way to implement this function is to show some form
|
||||
* of modal dialog that should ask the user if everything was ok.
|
||||
*
|
||||
* When confirmed by the user, the plugin must call meta_plugin_complete_display_change()
|
||||
* to make the configuration permanent. If that function is not
|
||||
* called within the timeout, the previous configuration will be
|
||||
* reapplied.
|
||||
*/
|
||||
void (*confirm_display_change) (MetaPlugin *plugin);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::plugin_info:
|
||||
* @plugin: a #MetaPlugin
|
||||
@ -214,6 +229,7 @@ struct _MetaPluginClass
|
||||
* Returns: a #MetaPluginInfo.
|
||||
*/
|
||||
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -360,6 +376,10 @@ void
|
||||
meta_plugin_destroy_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok);
|
||||
|
||||
/**
|
||||
* MetaModalOptions:
|
||||
* @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already
|
||||
@ -376,8 +396,6 @@ typedef enum {
|
||||
|
||||
gboolean
|
||||
meta_plugin_begin_modal (MetaPlugin *plugin,
|
||||
Window grab_window,
|
||||
Cursor cursor,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp);
|
||||
|
||||
|
@ -66,9 +66,6 @@ GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
|
||||
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||
gboolean create_mipmaps);
|
||||
|
||||
void meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -38,5 +38,6 @@ typedef struct _MetaWorkspace MetaWorkspace;
|
||||
*/
|
||||
typedef struct _MetaGroup MetaGroup;
|
||||
typedef struct _MetaKeyBinding MetaKeyBinding;
|
||||
typedef struct _MetaCursorTracker MetaCursorTracker;
|
||||
|
||||
#endif
|
||||
|
@ -100,7 +100,8 @@ typedef enum
|
||||
META_DEBUG_RESIZING = 1 << 18,
|
||||
META_DEBUG_SHAPES = 1 << 19,
|
||||
META_DEBUG_COMPOSITOR = 1 << 20,
|
||||
META_DEBUG_EDGE_RESISTANCE = 1 << 21
|
||||
META_DEBUG_EDGE_RESISTANCE = 1 << 21,
|
||||
META_DEBUG_DBUS = 1 << 22
|
||||
} MetaDebugTopic;
|
||||
|
||||
void meta_topic_real (MetaDebugTopic topic,
|
||||
|
@ -58,6 +58,11 @@ meta_ui_init (void)
|
||||
{
|
||||
if (!gtk_init_check (NULL, NULL))
|
||||
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
||||
|
||||
/* We need to be able to fully trust that the window and monitor sizes
|
||||
that Gdk reports corresponds to the X ones, so we disable the automatic
|
||||
scale handling */
|
||||
gdk_x11_display_set_window_scale (gdk_display_get_default (), 1);
|
||||
}
|
||||
|
||||
Display*
|
||||
|
290
src/xrandr.xml
Normal file
290
src/xrandr.xml
Normal file
@ -0,0 +1,290 @@
|
||||
<!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" />
|
||||
|
||||
<!--
|
||||
MonitorsChanged:
|
||||
|
||||
The signal is emitted every time the screen configuration
|
||||
changes.
|
||||
The client should then call GetResources() to read the new layout.
|
||||
-->
|
||||
<signal name="MonitorsChanged" />
|
||||
</interface>
|
||||
</node>
|
Reference in New Issue
Block a user