Compare commits

..

2 Commits

Author SHA1 Message Date
Jasper St. Pierre
c7b8f26cad compositor: Add an API to query if the stage is focused
gnome-shell needs to know whether the stage window is focused so
it can synchronize between stage window focus and Clutter key actor
focus. Track all X windows, even those without MetaWindows, when
tracking the focus window, and add a compositor-level API to determine
when the stage is focused.
2013-05-28 15:07:13 -04:00
Jasper St. Pierre
8747b97ba3 display: Ensure that we ignore our own focus events for focus predictions
When we set the input focus, we first set the predicted window,
and then try to process focus events. But as XI_FocusOut on the
existing window comes before XI_FocusIn on the new window, we'll
see the focus out on the old window and think the focus is going
to nothing, which makes mutter think the prediction failed.

This didn't really matter as nothing paid attention to the focus
window changing, but with gnome-shell's focus rework, we'll try
and drop keyboard focus in events like these.

Fix this by making sure that we ignore focus window changes of our
own cause when updating the focus window field, by ignoring all
focus events that have a serial the same as the focus request or
lower. Note that if mutter doens't make any requests after the
focus request, this could be racy, as another client could steal
the focus, but mutter would ignore it as the serial was the same.
Bump the serial by making a dummy ChangeProperty request to the
root window in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=701017
2013-05-28 14:59:20 -04:00
84 changed files with 7413 additions and 7362 deletions

2
.gitignore vendored
View File

@@ -46,6 +46,7 @@ POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
inlinepixbufs.h
libmutter.pc
mutter
mutter-theme-viewer
@@ -74,7 +75,6 @@ src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/mutter-plugins.pc
doc/reference/*.args
doc/reference/*.bak

32
NEWS
View File

@@ -1,35 +1,3 @@
3.9.5
=====
* Don't select for touch events on the stage [Jasper; #697192]
* Don't queue redraws for obscured regions [Adel; #703332]
* Export timestamp of global keybinding events [Bastien; #704858]
* Misc bug fixes and cleanups [Jasper, Rico; #703970]
Contributors:
Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
3.9.4
=====
* Tweak window shadows [Allan; #702141]
* Ignore our own focus events for focus prediction [Jasper; #701017]
* Add API to query if the stage is focused [Jasper; #700735]
* Add API to query the monitor for a given position [Adel]
* Don't force attached dialogs to be border-only [Florian; #702764]
* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283]
* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564]
Contributors:
Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode
3.9.3
=====
* Ensure events are always reported to the grab window [Rui; #701219]
* Use new clutter_stage_set_paint_callback() function to prevent dropping
frames with frame synced toolkits [Owen; #698794]
Contributors:
Rui Matos, Owen W. Taylor
3.9.2
=====
* Add meta_window_can_close() function [Jasper; #699269]

View File

@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [9])
m4_define([mutter_micro_version], [5])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -67,16 +67,14 @@ CANBERRA_GTK_VERSION=0.26
CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gtk+-3.0 >= 3.3.7
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.14.3
$CLUTTER_PACKAGE >= 1.13.5
cogl-1.0 >= 1.13.3
upower-glib > 0.9.11
gnome-desktop-3.0
"
GLIB_GSETTINGS
@@ -120,6 +118,9 @@ AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# gtk_window_set_icon_name requires gtk2+-2.6.0
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -306,6 +307,9 @@ if test "x$found_xsync" = "xyes"; then
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
case "$MUTTER_LIBS" in
@@ -435,8 +439,10 @@ doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/wm-tester/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/tools/Makefile
src/compositor/plugins/Makefile
po/Makefile.in
])

View File

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

View File

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

353
po/cs.po
View File

@@ -6,23 +6,22 @@
# 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, 2013.
#
# Marek Černocký <marek@manet.cz>, 2012.
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-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-08-20 08:50+0200\n"
"Last-Translator: Marek Černocký <marek@manet.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-03-22 10:02+0000\n"
"PO-Revision-Date: 2013-03-24 20:55+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.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: Gtranslator 2.91.6\n"
"X-Generator: Virtaal 0.7.1\n"
"X-Project-Style: gnome\n"
#: ../src/50-mutter-navigation.xml.in.h:1
@@ -187,8 +186,7 @@ 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"
@@ -216,14 +214,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:589
#: ../src/compositor/compositor.c:568
#, 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:1076
#: ../src/compositor/meta-background.c:1191
msgid "background texture could not be created from file"
msgstr "textura pozadí nemohla být ze souboru vytvořena"
@@ -261,17 +259,17 @@ msgstr "_Počkat"
msgid "_Force Quit"
msgstr "_Vynutit ukončení"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Schází rozšíření %s vyžadované funkcemi kompozitoru"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, 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:1136
#: ../src/core/keybindings.c:935
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@@ -279,8 +277,9 @@ msgid ""
msgstr ""
"Klávesu %s s modifikátory %x již jako zkratku používá nějaký jiný program\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1135
#, 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"
@@ -321,19 +320,6 @@ 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 ""
@@ -358,7 +344,7 @@ msgstr "Vypíše verzi"
msgid "Mutter plugin to use"
msgstr "Zásuvný modul Mutter, který se má použít"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1095
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@@ -366,12 +352,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:1277
#: ../src/core/prefs.c:1170
#, 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:1343
#: ../src/core/prefs.c:1236
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@@ -380,7 +366,7 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou modifikátoru "
"tlačítka myši\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1788
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@@ -389,17 +375,17 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou klávesové zkratky "
"„%s“\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "Plocha %d"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Obrazovka %d na displeji „%s“ je neplatná\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@@ -408,18 +394,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:577
#: ../src/core/screen.c:734
#, 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:655
#: ../src/core/screen.c:812
#, 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:846
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nelze uvolnit obrazovku %d na displeji „%s“\n"
@@ -494,7 +480,8 @@ 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/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter bylo přeloženo bez podpory podrobného režimu\n"
@@ -502,20 +489,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:414
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Chyba ve správci oken: "
#: ../src/core/util.c:445
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Varování správce oken: "
#: ../src/core/util.c:473
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Chyba správce oken: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7596
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@@ -531,7 +518,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8320
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@@ -541,22 +528,22 @@ msgstr ""
"velikost, ale nastavuje min. velikost %d × %d a max. velikost %d × %d; to "
"nedává smysl.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, 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:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, 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:1557
#: ../src/core/window-props.c:1528
#, 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"
@@ -720,104 +707,109 @@ 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:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Mi_nimalizovat"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Ma_ximalizovat"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Zrušit ma_ximalizaci"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "Sv_inout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "Rozv_inout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "_Přesunout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "Z_měnit velikost"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
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:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "_Vždy navrchu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
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:90
#: ../src/ui/menu.c:92
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:92
#: ../src/ui/menu.c:94
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:94
#: ../src/ui/menu.c:96
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:96
#: ../src/ui/menu.c:98
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:98
#: ../src/ui/menu.c:100
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:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Zavřít"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Plocha %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "Plocha 1_0"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Plocha %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Přes_unout na jinou plochu"
@@ -993,8 +985,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
@@ -1002,8 +994,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
@@ -1173,18 +1165,18 @@ msgid ""
msgstr ""
"Chybí <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"cokoliv\"/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Nelze načíst motiv „%s“: %s\n"
#: ../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
#: ../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
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Není nastaveno <%s> motivu „%s“"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@@ -1193,7 +1185,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:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
@@ -1201,7 +1193,7 @@ msgstr ""
"Uživatelem definované konstanty musí začínat velkým písmenem; „%s“ toto "
"nesplňuje"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstanta „%s“ již byla definována"
@@ -1580,4 +1572,205 @@ 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"
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"

503
po/es.po

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter 3.9.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-08 22:14+0200\n"
"POT-Creation-Date: 2013-05-28 09:47+0200\n"
"PO-Revision-Date: 2013-05-28 09:48+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
@@ -205,7 +205,7 @@ msgstr "Visning delt til høyre"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:571
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@@ -333,7 +333,7 @@ msgstr "Skriv versjonsnummer"
msgid "Mutter plugin to use"
msgstr "Mutter-tillegg som skal brukes"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1210
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@@ -341,12 +341,12 @@ msgstr ""
"Funksjonalitet for å gå rundt ødelagte programmer er deaktivert. Noen "
"programmer vil kanskje ikke oppføre seg korrekt.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1285
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Kunne ikke tolke skriftbeskrivelsen «%s» fra GSettings-nøkkel %s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1351
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@@ -355,7 +355,7 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for endring av "
"musknapp\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1928
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@@ -364,7 +364,7 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for "
"tastaturbinding «%s»\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:2018
#, c-format
msgid "Workspace %d"
msgstr "Arbeidsområde %d"
@@ -492,7 +492,7 @@ msgid "Window manager error: "
msgstr "Feil i vindushåndterer: "
#. first time through
#: ../src/core/window.c:7513
#: ../src/core/window.c:7505
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@@ -508,7 +508,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8237
#: ../src/core/window.c:8229
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "

501
po/sl.po

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
SUBDIRS=wm-tester tools compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
@@ -30,7 +30,6 @@ INCLUDES= \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c
@@ -65,6 +64,8 @@ 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 \
@@ -93,8 +94,6 @@ libmutter_la_SOURCES = \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
core/edid.h \
core/errors.c \
meta/errors.h \
core/frame.c \
@@ -111,13 +110,6 @@ 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 \
@@ -147,6 +139,7 @@ libmutter_la_SOURCES = \
meta/common.h \
core/core.h \
ui/ui.h \
inlinepixbufs.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
@@ -164,6 +157,8 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
meta/preview-widget.h \
ui/preview-widget.c \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
@@ -186,7 +181,6 @@ libmutterinclude_base_headers = \
meta/meta-background-actor.h \
meta/meta-background-group.h \
meta/meta-background.h \
meta/meta-cursor-tracker.h \
meta/meta-plugin.h \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
@@ -202,6 +196,7 @@ libmutterinclude_base_headers = \
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/preview-widget.h \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
@@ -210,7 +205,10 @@ libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
bin_PROGRAMS=mutter
mutter_theme_viewer_SOURCES= \
ui/theme-viewer.c
bin_PROGRAMS=mutter mutter-theme-viewer
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
@@ -248,6 +246,8 @@ Meta-$(api_version).gir: libmutter.la
endif
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
@@ -284,7 +284,14 @@ gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
stock_minimize_data $(srcdir)/stock_minimize.png \
stock_delete_data $(srcdir)/stock_delete.png
BUILT_SOURCES = inlinepixbufs.h
CLEANFILES = \
inlinepixbufs.h \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
@@ -293,6 +300,9 @@ CLEANFILES = \
$(typelib_DATA) \
$(gir_DATA)
inlinepixbufs.h: $(IMAGES)
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
@@ -304,14 +314,13 @@ 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 \
mutter-enum-types.h.in \
mutter-enum-types.c.in
BUILT_SOURCES = $(mutter_built_sources)
BUILT_SOURCES += $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
@@ -333,12 +342,3 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml

10
src/compositor/README Normal file
View File

@@ -0,0 +1,10 @@
Intro
=====
Fix me.
Env Vars
========
MUTTER_DISABLE_MIPMAPS - set to disable use of mipmaped windows.

View File

@@ -31,6 +31,7 @@ struct _MetaCompositor
guint server_time_is_monotonic_time : 1;
guint show_redraw : 1;
guint debug : 1;
guint no_mipmaps : 1;
};
struct _MetaCompScreen
@@ -65,6 +66,8 @@ void meta_switch_workspace_completed (MetaScreen *screen);
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaScreen *screen,

View File

@@ -412,6 +412,8 @@ 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)
{
@@ -422,19 +424,10 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
ClutterStage *stage;
Window grab_window;
Cursor cursor = None;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
grab_window = clutter_x11_get_stage_window (stage);
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
@@ -542,20 +535,20 @@ meta_check_end_modal (MetaScreen *screen)
{
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
CurrentTime);
}
}
static void
after_stage_paint (ClutterStage *stage,
gpointer data)
static gboolean
after_stage_paint (gpointer data)
{
MetaCompScreen *info = (MetaCompScreen*) data;
GList *l;
for (l = info->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
return TRUE;
}
static void
@@ -636,10 +629,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->stage = clutter_stage_new ();
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
after_stage_paint,
info,
NULL);
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
after_stage_paint,
info, NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
@@ -667,9 +659,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
@@ -1532,6 +1521,9 @@ 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);
@@ -1591,10 +1583,8 @@ void
meta_enable_unredirect_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info != NULL && info->disable_unredirect_count == 0)
g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
if (info != NULL && info->disable_unredirect_count > 0)
info->disable_unredirect_count = info->disable_unredirect_count - 1;
if (info != NULL)
info->disable_unredirect_count = MAX(0, info->disable_unredirect_count - 1);
}
#define FLASH_TIME_MS 50

View File

@@ -1060,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NO_ATLAS,
COGL_TEXTURE_NO_SLICING,
has_alpha ?
COGL_PIXEL_FORMAT_RGBA_8888 :
COGL_PIXEL_FORMAT_RGB_888,

View File

@@ -85,20 +85,12 @@ meta_plugin_manager_load (const gchar *plugin_name)
g_free (path);
}
static void
on_confirm_display_change (MetaMonitorManager *monitors,
MetaPluginManager *plugin_mgr)
{
meta_plugin_manager_confirm_display_change (plugin_mgr);
}
MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
MetaPluginClass *klass;
MetaPlugin *plugin;
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
@@ -109,10 +101,6 @@ meta_plugin_manager_new (MetaScreen *screen)
if (klass->start)
klass->start (plugin);
monitors = meta_monitor_manager_get ();
g_signal_connect (monitors, "confirm-display-change",
G_CALLBACK (on_confirm_display_change), plugin_mgr);
return plugin_mgr;
}
@@ -332,15 +320,3 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
else
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
}
void
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->confirm_display_change)
return klass->confirm_display_change (plugin);
else
return meta_plugin_complete_display_change (plugin, TRUE);
}

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,7 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include "meta-texture-tower.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
@@ -63,6 +64,7 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
Pixmap pixmap;
CoglTexturePixmapX11 *texture;
CoglTexture *mask_texture;
@@ -72,6 +74,8 @@ struct _MetaShapedTexturePrivate
cairo_region_t *clip_region;
guint tex_width, tex_height;
guint create_mipmaps : 1;
};
static void
@@ -98,8 +102,10 @@ 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
@@ -108,6 +114,10 @@ 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);
@@ -123,6 +133,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
CoglTexture *paint_tex;
guint tex_width, tex_height;
ClutterActorBox alloc;
@@ -137,6 +148,29 @@ 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;
@@ -178,10 +212,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
}
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);
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
{
CoglColor color;
@@ -342,6 +373,28 @@ 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)
@@ -381,6 +434,8 @@ 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);
}
@@ -459,6 +514,10 @@ 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));
}
/**

View File

@@ -0,0 +1,624 @@
/* -*- 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];
}

View File

@@ -0,0 +1,69 @@
/* -*- 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__ */

View File

@@ -69,6 +69,9 @@ struct _MetaWindowActorPrivate
Damage damage;
guint8 opacity;
guint8 shadow_opacity;
gchar * desc;
/* A region that matches the shape of the window, including frame bounds */
cairo_region_t *shape_region;
@@ -127,6 +130,8 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
guint no_more_x_calls : 1;
guint unredirected : 1;
/* This is used to detect fullscreen windows that need to be unredirected */
@@ -318,6 +323,9 @@ window_decorated_notify (MetaWindow *mw,
priv->damage = None;
}
g_free (priv->desc);
priv->desc = NULL;
priv->xwindow = new_xwindow;
/*
@@ -369,10 +377,10 @@ meta_window_actor_constructed (GObject *object)
*/
g_object_ref (priv->actor);
g_signal_connect_object (window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
g_signal_connect_object (window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0);
g_signal_connect (window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self);
g_signal_connect (window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self);
}
else
{
@@ -449,6 +457,7 @@ meta_window_actor_finalize (GObject *object)
MetaWindowActorPrivate *priv = self->priv;
g_list_free_full (priv->frames, (GDestroyNotify) frame_data_free);
g_free (priv->desc);
G_OBJECT_CLASS (meta_window_actor_parent_class)->finalize (object);
}
@@ -843,6 +852,25 @@ meta_window_actor_is_override_redirect (MetaWindowActor *self)
return meta_window_is_override_redirect (self->priv->window);
}
const char *meta_window_actor_get_description (MetaWindowActor *self)
{
/*
* For windows managed by the WM, we just defer to the WM for the window
* description. For override-redirect windows, we create the description
* ourselves, but only on demand.
*/
if (self->priv->window)
return meta_window_get_description (self->priv->window);
if (G_UNLIKELY (self->priv->desc == NULL))
{
self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
(guint) self->priv->xwindow);
}
return self->priv->desc;
}
/**
* meta_window_actor_get_workspace:
* @self: #MetaWindowActor
@@ -1312,6 +1340,14 @@ meta_window_actor_destroy (MetaWindowActor *self)
priv->needs_destroy = TRUE;
/*
* Once the window destruction is initiated we can no longer perform any
* furter X-based operations. For example, if we have a Map effect running,
* we cannot query the window geometry once the effect completes. So, flag
* this.
*/
priv->no_more_x_calls = TRUE;
if (!meta_window_actor_effect_in_progress (self))
clutter_actor_destroy (CLUTTER_ACTOR (self));
}
@@ -1712,8 +1748,8 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
* meta_window_actor_reset_visible_regions:
* @self: a #MetaWindowActor
*
* Unsets the regions set by meta_window_actor_set_visible_region() and
* meta_window_actor_set_visible_region_beneath()
* Unsets the regions set by meta_window_actor_reset_visible_region() and
* meta_window_actor_reset_visible_region_beneath()
*/
void
meta_window_actor_reset_visible_regions (MetaWindowActor *self)
@@ -1782,6 +1818,10 @@ 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);

View File

@@ -91,9 +91,8 @@ meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *visible_region;
ClutterActor *stage;
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect;
GList *children, *l;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
@@ -124,6 +123,13 @@ meta_window_group_paint (ClutterActor *actor)
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
children = clutter_actor_get_children (actor);
children = g_list_reverse (children);
/* Get the clipped redraw bounds from Clutter so that we can avoid
* painting shadows on windows that don't need to be painted in this
* frame. In the case of a multihead setup with mismatched monitor
@@ -145,18 +151,12 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
}
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
for (l = children; l; l = l->next)
{
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
continue;
if (info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
if (l->data == info->unredirected_window)
continue;
/* If an actor has effects applied, then that can change the area
@@ -175,12 +175,12 @@ meta_window_group_paint (ClutterActor *actor)
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (child))
if (clutter_actor_has_effects (l->data))
continue;
if (META_IS_WINDOW_ACTOR (child))
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
MetaWindowActor *window_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
@@ -204,12 +204,13 @@ meta_window_group_paint (ClutterActor *actor)
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
else if (META_IS_BACKGROUND_ACTOR (l->data) ||
META_IS_BACKGROUND_GROUP (l->data))
{
ClutterActor *background_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (child, &x, &y))
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
continue;
x += paint_x_offset;
@@ -217,10 +218,10 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_translate (visible_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
if (META_IS_BACKGROUND_GROUP (background_actor))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
else
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
cairo_region_translate (visible_region, x, y);
}
}
@@ -232,20 +233,21 @@ meta_window_group_paint (ClutterActor *actor)
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
for (l = children; l; l = l->next)
{
if (META_IS_WINDOW_ACTOR (child))
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
MetaWindowActor *window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (child))
else if (META_IS_BACKGROUND_ACTOR (l->data))
{
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, NULL);
}
}
g_list_free (children);
}
static gboolean

View File

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

View File

@@ -460,8 +460,7 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp);
guint deviceid);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */

View File

@@ -254,7 +254,7 @@ meta_display_class_init (MetaDisplayClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
/**
* MetaDisplay::modifiers-accelerator-activated:
@@ -1467,17 +1467,6 @@ meta_display_get_current_time (MetaDisplay *display)
return display->current_time;
}
static Bool
find_timestamp_predicate (Display *xdisplay,
XEvent *ev,
XPointer arg)
{
MetaDisplay *display = (MetaDisplay *) arg;
return (ev->type == PropertyNotify &&
ev->xproperty.atom == display->atom__MUTTER_TIMESTAMP_PING);
}
/* Get a timestamp, even if it means a roundtrip */
guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
@@ -1489,13 +1478,17 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
XEvent property_event;
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_TIMESTAMP_PING,
XA_STRING, 8, PropModeAppend, NULL, 0);
XIfEvent (display->xdisplay,
&property_event,
find_timestamp_predicate,
(XPointer) display);
/* Using the property XA_PRIMARY because it's safe; nothing
* would use it as a property. The type doesn't matter.
*/
XChangeProperty (display->xdisplay,
display->timestamp_pinging_window,
XA_PRIMARY, XA_STRING, 8,
PropModeAppend, NULL, 0);
XWindowEvent (display->xdisplay,
display->timestamp_pinging_window,
PropertyChangeMask,
&property_event);
timestamp = property_event.xproperty.time;
}
@@ -1981,16 +1974,21 @@ request_xserver_input_focus_change (MetaDisplay *display,
*/
meta_display_grab (display);
serial = XNextRequest (display->xdisplay);
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
serial = XNextRequest (display->xdisplay);
{
unsigned long data[1] = { 0 };
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_FOCUS_SET,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
}
meta_display_ungrab (display);
@@ -2111,7 +2109,7 @@ handle_window_focus_event (MetaDisplay *display,
else
g_return_if_reached ();
if (display->server_focus_serial > display->focus_serial)
if (display->server_focus_serial >= display->focus_serial)
{
update_focus_window (display,
focus_window,
@@ -2146,8 +2144,6 @@ event_callback (XEvent *event,
gboolean bypass_compositor;
gboolean filter_out_event;
XIEvent *input_event;
MetaMonitorManager *monitor;
MetaScreen *screen;
display = data;
@@ -2159,14 +2155,6 @@ 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;
@@ -2185,13 +2173,6 @@ 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);
@@ -2511,12 +2492,30 @@ event_callback (XEvent *event,
/* This is from our synchronous grab since
* it has no modifiers and was on the client window
*/
int mode;
/* When clicking a different app in click-to-focus
* in application-based mode, and the different
* app is not a dock or desktop, eat the focus click.
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
meta_prefs_get_application_based () &&
!window->has_focus &&
window->type != META_WINDOW_DOCK &&
window->type != META_WINDOW_DESKTOP &&
(display->focus_window == NULL ||
!meta_window_same_application (window,
display->focus_window)))
mode = XIAsyncDevice; /* eat focus click */
else
mode = XIReplayDevice; /* give event back */
meta_verbose ("Allowing events time %u\n",
meta_verbose ("Allowing events mode %s time %u\n",
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
(unsigned int)device_event->time);
XIAllowEvents (display->xdisplay, device_event->deviceid,
XIReplayDevice, device_event->time);
mode, device_event->time);
}
if (begin_move && window->has_move_func)
@@ -2839,10 +2838,32 @@ event_callback (XEvent *event,
meta_stack_tracker_configure_event (screen->stack_tracker,
&event->xconfigure);
}
if (window && window->override_redirect)
meta_window_configure_notify (window, &event->xconfigure);
else
/* Handle screen resize */
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.window);
if (screen != NULL)
{
#ifdef HAVE_RANDR
/* do the resize the official way */
XRRUpdateConfiguration (event);
#else
/* poke around in Xlib */
screen->xscreen->width = event->xconfigure.width;
screen->xscreen->height = event->xconfigure.height;
#endif
meta_screen_resize (screen,
event->xconfigure.width,
event->xconfigure.height);
}
}
break;
case ConfigureRequest:
/* This comment and code is found in both twm and fvwm */
@@ -3037,6 +3058,27 @@ event_callback (XEvent *event,
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
}
}
else if (event->xclient.message_type ==
display->atom__MUTTER_RELOAD_THEME_MESSAGE)
{
meta_verbose ("Received reload theme request\n");
meta_ui_set_current_theme (meta_prefs_get_theme (),
TRUE);
meta_display_retheme_all ();
}
else if (event->xclient.message_type ==
display->atom__MUTTER_SET_KEYBINDINGS_MESSAGE)
{
meta_verbose ("Received set keybindings request = %d\n",
(int) event->xclient.data.l[0]);
meta_set_keybindings_disabled (!event->xclient.data.l[0]);
}
else if (event->xclient.message_type ==
display->atom__MUTTER_TOGGLE_VERBOSE)
{
meta_verbose ("Received toggle verbose message\n");
meta_set_verbose (!meta_is_verbose ());
}
else if (event->xclient.message_type ==
display->atom_WM_PROTOCOLS)
{
@@ -3746,12 +3788,6 @@ meta_spew_event (MetaDisplay *display,
if (event->type == (display->damage_event_base + XDamageNotify))
return;
if (event->type == (display->xsync_event_base + XSyncAlarmNotify))
return;
if (event->type == PropertyNotify && event->xproperty.atom == display->atom__NET_WM_USER_TIME)
return;
input_event = get_input_event (display, event);
if (input_event)
@@ -5866,11 +5902,10 @@ meta_display_overlay_key_activate (MetaDisplay *display)
void
meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid,
guint timestamp)
guint deviceid)
{
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
0, action, deviceid, timestamp);
0, action, deviceid);
}
gboolean

View File

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

View File

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

View File

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

View File

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

View File

@@ -514,14 +514,14 @@ meta_run (void)
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
/* Try to find some theme that'll work if the theme preference
* doesn't exist. First try Simple (the default theme) then just
* try anything in the themes directory.
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Simple");
meta_ui_set_current_theme ("Simple", FALSE);
if (!meta_ui_have_a_theme ())
{
@@ -539,7 +539,7 @@ meta_run (void)
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
(!meta_ui_have_a_theme ()))
{
meta_ui_set_current_theme (dir_entry);
meta_ui_set_current_theme (dir_entry, FALSE);
}
g_dir_close (themes_dir);
@@ -598,7 +598,7 @@ prefs_changed_callback (MetaPreference pref,
{
case META_PREF_THEME:
case META_PREF_DRAGGABLE_BORDER_WIDTH:
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
meta_display_retheme_all ();
break;

View File

@@ -1,34 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_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

View File

@@ -1,275 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
/**
* SECTION:cursor-tracker
* @title: MetaCursorTracker
* @short_description: Mutter cursor tracking helper
*/
#include <config.h>
#include <meta/main.h>
#include <meta/util.h>
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <clutter/clutter.h>
#include <X11/extensions/Xfixes.h>
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#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);
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -45,10 +45,13 @@
#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>
@@ -73,9 +76,6 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
void *user_data);
#endif
static void on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen);
enum
{
PROP_N_WORKSPACES = 1,
@@ -350,93 +350,250 @@ set_wm_icon_size_hint (MetaScreen *screen)
#undef N_VALS
}
/* The list of monitors reported by the windowing system might include
* mirrored monitors with identical bounds. Since mirrored monitors
* shouldn't be treated as separate monitors for most purposes, we
* filter them out here. (We ignore the possibility of partially
* overlapping monitors because they are rare and it's hard to come
* up with any sensible interpretation.)
*/
static void
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
filter_mirrored_monitors (MetaScreen *screen)
{
XineramaScreenInfo *infos;
int n_infos, i, j;
int i, j;
if (screen->has_xinerama_indices)
return;
/* Currently always true and simplifies things */
g_assert (screen->primary_monitor_index == 0);
screen->has_xinerama_indices = TRUE;
if (!XineramaIsActive (screen->display->xdisplay))
return;
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
if (n_infos <= 0 || infos == NULL)
for (i = 1; i < screen->n_monitor_infos; i++)
{
meta_XFree (infos);
return;
}
/* In case we've filtered previous monitors */
screen->monitor_infos[i].number = i;
for (i = 0; i < screen->n_monitor_infos; ++i)
{
for (j = 0; j < n_infos; ++j)
for (j = 0; j < i; j++)
{
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
screen->monitor_infos[i].rect.y == infos[j].y_org &&
screen->monitor_infos[i].rect.width == infos[j].width &&
screen->monitor_infos[i].rect.height == infos[j].height)
screen->monitor_infos[i].xinerama_index = j;
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
&screen->monitor_infos[j].rect))
{
memmove (&screen->monitor_infos[i],
&screen->monitor_infos[i + 1],
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
screen->n_monitor_infos--;
i--;
continue;
}
}
}
meta_XFree (infos);
}
int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
}
int
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index)
#ifdef HAVE_RANDR
static MetaMonitorInfo *
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
{
MetaMonitorInfo *info;
int i;
meta_screen_ensure_xinerama_indices (screen);
for (i = 0; i < screen->n_monitor_infos; i++)
if (screen->monitor_infos[i].xinerama_index == index)
return i;
return -1;
{
info = &screen->monitor_infos[i];
if (x == info->rect.x &&
y == info->rect.y &&
w == info->rect.width &&
h == info->rect.height)
return info;
}
return NULL;
}
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
* outputs the "main". This is the one we consider "owning" the windows, so if
* the mirroring is changed to a dual monitor setup then the windows are moved to the
* crtc that now has that main output. If one of the outputs is the primary that is
* always the main, otherwise we just use the first.
*/
static XID
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
{
XRROutputInfo *output;
RROutput primary_output;
int i;
XID res;
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
res = None;
for (i = 0; i < crtc->noutput; i++)
{
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
if (output->connection != RR_Disconnected &&
(res == None || crtc->outputs[i] == primary_output))
res = crtc->outputs[i];
XRRFreeOutputInfo (output);
}
return res;
}
#endif
static void
reload_monitor_infos (MetaScreen *screen)
{
GList *tmp;
MetaMonitorManager *manager;
MetaDisplay *display;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
{
GList *tmp;
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
}
display = screen->display;
/* Any previous screen->monitor_infos is freed by the caller */
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
screen->has_xinerama_indices = FALSE;
/* Xinerama doesn't have a concept of primary monitor, however XRandR
* does. However, the XRandR xinerama compat code always sorts the
* primary output first, so we rely on that here. We could use the
* native XRandR calls instead of xinerama, but that would be
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
* that is defined in terms of xinerama monitor indexes.
* So, since we don't need anything in xrandr except the primary
* we can keep using xinerama and use the first monitor as the
* primary.
*/
screen->primary_monitor_index = 0;
screen->display->monitor_cache_invalidated = TRUE;
manager = meta_monitor_manager_get ();
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
{
meta_topic (META_DEBUG_XINERAMA,
"Pretending a single monitor has two Xinerama screens\n");
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
(unsigned*)&screen->n_monitor_infos);
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
screen->n_monitor_infos = 2;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
screen->monitor_infos[1].number = 1;
screen->monitor_infos[1].rect = screen->rect;
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
}
if (screen->n_monitor_infos == 0 &&
XineramaIsActive (display->xdisplay))
{
XineramaScreenInfo *infos;
int n_infos;
int i;
n_infos = 0;
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
meta_topic (META_DEBUG_XINERAMA,
"Found %d Xinerama screens on display %s\n",
n_infos, display->name);
if (n_infos > 0)
{
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
screen->n_monitor_infos = n_infos;
i = 0;
while (i < n_infos)
{
screen->monitor_infos[i].number = infos[i].screen_number;
screen->monitor_infos[i].rect.x = infos[i].x_org;
screen->monitor_infos[i].rect.y = infos[i].y_org;
screen->monitor_infos[i].rect.width = infos[i].width;
screen->monitor_infos[i].rect.height = infos[i].height;
screen->monitor_infos[i].in_fullscreen = -1;
meta_topic (META_DEBUG_XINERAMA,
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
}
meta_XFree (infos);
#ifdef HAVE_RANDR
{
XRRScreenResources *resources;
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
if (resources)
{
for (i = 0; i < resources->ncrtc; i++)
{
XRRCrtcInfo *crtc;
MetaMonitorInfo *info;
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
if (info)
info->output = find_main_output_for_crtc (screen, resources, crtc);
XRRFreeCrtcInfo (crtc);
}
XRRFreeScreenResources (resources);
}
}
#endif
}
else if (screen->n_monitor_infos > 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama extension or Xinerama inactive on display %s\n",
display->name);
}
/* If no Xinerama, fill in the single screen info so
* we can use the field unconditionally
*/
if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama screens, using default screen info\n");
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
screen->n_monitor_infos = 1;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].in_fullscreen = -1;
}
filter_mirrored_monitors (screen);
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
g_assert (screen->n_monitor_infos > 0);
g_assert (screen->monitor_infos != NULL);
}
/* The guard window allows us to leave minimized windows mapped so
@@ -511,7 +668,6 @@ meta_screen_new (MetaDisplay *display,
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@@ -670,17 +826,8 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), screen);
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
@@ -705,9 +852,12 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
reload_monitor_infos (screen);
meta_cursor_tracker_get_for_screen (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
/* Handle creating a no_focus_window for this screen */
@@ -791,7 +941,7 @@ meta_screen_new (MetaDisplay *display,
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
@@ -1463,18 +1613,29 @@ void
meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor)
{
Cursor xcursor;
if (cursor == screen->current_cursor)
return;
screen->current_cursor = cursor;
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
xcursor = meta_display_create_x_cursor (screen->display, cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
screen->current_cursor);
Cursor xcursor;
xcursor = meta_display_create_x_cursor (screen->display,
screen->current_cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
}
void
@@ -2055,65 +2216,6 @@ meta_screen_get_current_monitor_info (MetaScreen *screen)
return &screen->monitor_infos[monitor_index];
}
const MetaMonitorInfo*
meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
int x,
int y)
{
int monitor_index;
monitor_index = meta_screen_get_current_monitor_for_pos (screen, x, y);
return &screen->monitor_infos[monitor_index];
}
/**
* meta_screen_get_current_monitor_for_pos:
* @screen: a #MetaScreen
* @x: The x coordinate
* @y: The y coordinate
*
* Gets the index of the monitor that contains the passed coordinates.
*
* Return value: a monitor index
*/
int
meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
int x,
int y)
{
if (screen->n_monitor_infos == 1)
return 0;
else if (screen->display->monitor_cache_invalidated)
{
int i;
MetaRectangle pointer_position;
pointer_position.x = x;
pointer_position.y = y;
pointer_position.width = pointer_position.height = 1;
screen->display->monitor_cache_invalidated = FALSE;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
}
return screen->last_monitor_index;
}
/**
* meta_screen_get_current_monitor:
* @screen: a #MetaScreen
@@ -2139,7 +2241,11 @@ meta_screen_get_current_monitor (MetaScreen *screen)
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int i;
MetaRectangle pointer_position;
screen->display->monitor_cache_invalidated = FALSE;
XIQueryPointer (screen->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
@@ -2154,7 +2260,24 @@ meta_screen_get_current_monitor (MetaScreen *screen)
&group);
free (buttons.mask);
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
pointer_position.x = root_x_return;
pointer_position.y = root_y_return;
pointer_position.width = pointer_position.height = 1;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
}
return screen->last_monitor_index;
@@ -2836,15 +2959,19 @@ meta_screen_resize_func (MetaScreen *screen,
meta_window_recalc_features (window);
}
static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
void
meta_screen_resize (MetaScreen *screen,
int width,
int height)
{
GSList *tmp, *windows;
GSList *windows, *tmp;
MetaMonitorInfo *old_monitor_infos;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->rect.width = width;
screen->rect.height = height;
/* Save the old monitor infos, so they stay valid during the update */
old_monitor_infos = screen->monitor_infos;
reload_monitor_infos (screen);
set_desktop_geometry_hint (screen);
@@ -2856,8 +2983,8 @@ on_monitors_changed (MetaMonitorManager *manager,
changes.x = 0;
changes.y = 0;
changes.width = screen->rect.width;
changes.height = screen->rect.height;
changes.width = width;
changes.height = height;
XConfigureWindow(screen->display->xdisplay,
screen->guard_window,
@@ -2867,15 +2994,14 @@ on_monitors_changed (MetaMonitorManager *manager,
if (screen->display->compositor)
meta_compositor_sync_screen_size (screen->display->compositor,
screen,
screen->rect.width, screen->rect.height);
screen, width, height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
/* Fix up monitor for all windows on this screen */
windows = meta_display_list_windows (screen->display,
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
META_LIST_DEFAULT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
@@ -2884,6 +3010,7 @@ on_monitors_changed (MetaMonitorManager *manager,
meta_window_update_for_monitors_changed (window);
}
g_free (old_monitor_infos);
g_slist_free (windows);
meta_screen_queue_check_fullscreen (screen);
@@ -3679,17 +3806,3 @@ meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
/* We use -1 as a flag to mean "not known yet" for notification purposes */
return screen->monitor_infos[monitor].in_fullscreen == TRUE;
}
gboolean
meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent)
{
/* 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;
}

View File

@@ -332,8 +332,6 @@ topic_name (MetaDebugTopic topic)
return "COMPOSITOR";
case META_DEBUG_EDGE_RESISTANCE:
return "EDGE_RESISTANCE";
case META_DEBUG_DBUS:
return "DBUS";
case META_DEBUG_VERBOSE:
return "VERBOSE";
}
@@ -639,13 +637,8 @@ meta_show_dialog (const char *type,
append_argument (args, "zenity");
append_argument (args, type);
if (display)
{
append_argument (args, "--display");
append_argument (args, display);
}
append_argument (args, "--display");
append_argument (args, display);
append_argument (args, "--class");
append_argument (args, "mutter-dialog");
append_argument (args, "--title");

View File

@@ -165,7 +165,7 @@ struct _MetaWindow
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
* origin is on. */
gint fullscreen_monitors[4];
long fullscreen_monitors[4];
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
@@ -394,9 +394,6 @@ struct _MetaWindow
*/
MetaRectangle rect;
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size

View File

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

View File

@@ -145,8 +145,6 @@ static void meta_window_move_between_rects (MetaWindow *window,
static void unmaximize_window_before_freeing (MetaWindow *window);
static void unminimize_window_and_all_transient_parents (MetaWindow *window);
static void meta_window_update_monitor (MetaWindow *window);
/* Idle handlers for the three queues (run with meta_later_add()). The
* "data" parameter in each case will be a GINT_TO_POINTER of the
* index into the queue arrays to use.
@@ -2108,14 +2106,10 @@ set_net_wm_state (MetaWindow *window)
if (window->fullscreen)
{
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
data[0] = window->fullscreen_monitors[0];
data[1] = window->fullscreen_monitors[1];
data[2] = window->fullscreen_monitors[2];
data[3] = window->fullscreen_monitors[3];
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
@@ -4773,12 +4767,6 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
if (window->type == META_WINDOW_DESKTOP)
return;
if (window->override_redirect)
{
meta_window_update_monitor (window);
return;
}
old = window->monitor;
/* Start on primary */
@@ -4789,8 +4777,7 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
if (info->output_id != 0 &&
info->output_id == old->output_id)
if (info->output == old->output)
{
new = info;
break;
@@ -5826,18 +5813,7 @@ meta_window_get_outer_rect (const MetaWindow *window,
rect->height -= borders.invisible.top + borders.invisible.bottom;
}
else
{
*rect = window->rect;
if (window->has_custom_frame_extents)
{
GtkBorder *extents = &window->custom_frame_extents;
rect->x += extents->left;
rect->y += extents->top;
rect->width -= extents->left + extents->right;
rect->height -= extents->top + extents->bottom;
}
}
*rect = window->rect;
}
const char*
@@ -7135,14 +7111,10 @@ meta_window_client_message (MetaWindow *window,
meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
window->desc);
top = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[0]);
bottom = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[1]);
left = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[2]);
right = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[3]);
top = event->xclient.data.l[0];
bottom = event->xclient.data.l[1];
left = event->xclient.data.l[2];
right = event->xclient.data.l[3];
/* source_indication = event->xclient.data.l[4]; */
meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
@@ -8271,6 +8243,9 @@ recalc_window_features (MetaWindow *window)
if (window->type == META_WINDOW_TOOLBAR)
window->decorated = FALSE;
if (meta_window_is_attached_dialog (window))
window->border_only = TRUE;
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK ||
window->override_redirect)
@@ -8941,7 +8916,7 @@ update_move (MetaWindow *window,
* refers to the monitor which contains the largest part of the window,
* the latter to the one where the pointer is located.
*/
monitor = meta_screen_get_current_monitor_info_for_pos (window->screen, x, y);
monitor = meta_screen_get_current_monitor_info (window->screen);
meta_window_get_work_area_for_monitor (window,
monitor->number,
&work_area);
@@ -11003,7 +10978,7 @@ meta_window_get_frame_type (MetaWindow *window)
/* can't add border if undecorated */
return META_FRAME_TYPE_LAST;
}
else if (window->border_only ||
else if ((window->border_only && base_type != META_FRAME_TYPE_ATTACHED) ||
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)) ||
(window->hide_titlebar_when_maximized && META_WINDOW_TILED_SIDE_BY_SIDE (window)))
{

View File

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

View File

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

View File

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

View File

@@ -66,6 +66,9 @@ 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,

View File

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

View File

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

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

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

View File

@@ -78,9 +78,6 @@ MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
int meta_screen_get_n_monitors (MetaScreen *screen);
int meta_screen_get_primary_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
int x,
int y);
void meta_screen_get_monitor_geometry (MetaScreen *screen,
int monitor,
MetaRectangle *geometry);

View File

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

View File

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

View File

@@ -100,8 +100,7 @@ typedef enum
META_DEBUG_RESIZING = 1 << 18,
META_DEBUG_SHAPES = 1 << 19,
META_DEBUG_COMPOSITOR = 1 << 20,
META_DEBUG_EDGE_RESISTANCE = 1 << 21,
META_DEBUG_DBUS = 1 << 22
META_DEBUG_EDGE_RESISTANCE = 1 << 21
} MetaDebugTopic;
void meta_topic_real (MetaDebugTopic topic,

BIN
src/stock_delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
src/stock_maximize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

BIN
src/stock_minimize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

8
src/tools/.cvsignore Normal file
View File

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

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

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

View File

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

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

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

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

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

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

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

View File

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

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

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

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

File diff suppressed because it is too large Load Diff

View File

@@ -5063,14 +5063,16 @@ meta_theme_get_current (void)
}
void
meta_theme_set_current (const char *name)
meta_theme_set_current (const char *name,
gboolean force_reload)
{
MetaTheme *new_theme;
GError *err;
meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
if (meta_current_theme &&
if (!force_reload &&
meta_current_theme &&
strcmp (name, meta_current_theme->name) == 0)
return;

View File

@@ -4,6 +4,7 @@
/*
* Copyright (C) 2002 Havoc Pennington
* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -30,10 +31,13 @@
#include "core.h"
#include "theme-private.h"
#include "inlinepixbufs.h"
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
static void meta_stock_icons_init (void);
static void meta_ui_accelerator_parse (const char *accel,
guint *keysym,
guint *keycode,
@@ -59,10 +63,7 @@ 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);
meta_stock_icons_init ();
}
Display*
@@ -774,9 +775,10 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
}
void
meta_ui_set_current_theme (const char *name)
meta_ui_set_current_theme (const char *name,
gboolean force_reload)
{
meta_theme_set_current (name);
meta_theme_set_current (name, force_reload);
meta_invalidate_default_icons ();
}
@@ -996,6 +998,48 @@ meta_ui_window_is_widget (MetaUI *ui,
return FALSE;
}
/* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> */
typedef struct
{
char *stock_id;
const guint8 *icon_data;
} MetaStockIcon;
static void
meta_stock_icons_init (void)
{
GtkIconFactory *factory;
int i;
MetaStockIcon items[] =
{
{ METACITY_STOCK_DELETE, stock_delete_data },
{ METACITY_STOCK_MINIMIZE, stock_minimize_data },
{ METACITY_STOCK_MAXIMIZE, stock_maximize_data }
};
factory = gtk_icon_factory_new ();
gtk_icon_factory_add_default (factory);
for (i = 0; i < (gint) G_N_ELEMENTS (items); i++)
{
GtkIconSet *icon_set;
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new_from_inline (-1, items[i].icon_data,
FALSE,
NULL);
icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
g_object_unref (G_OBJECT (pixbuf));
}
g_object_unref (G_OBJECT (factory));
}
int
meta_ui_get_drag_threshold (MetaUI *ui)
{

View File

@@ -154,7 +154,8 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
void meta_ui_set_current_theme (const char *name);
void meta_ui_set_current_theme (const char *name,
gboolean force_reload);
gboolean meta_ui_have_a_theme (void);
/* Not a real key symbol but means "key above the tab key"; this is

7
src/wm-tester/.cvsignore Normal file
View File

@@ -0,0 +1,7 @@
Makefile
Makefile.in
focus-window
test-gravity
test-resizing
wm-tester
test-size-hints

33
src/wm-tester/Makefile.am Normal file
View File

@@ -0,0 +1,33 @@
INCLUDES=@MUTTER_CFLAGS@
wm_tester_SOURCES= \
main.c
test_gravity_SOURCES= \
test-gravity.c
focus_window_SOURCES= \
focus-window.c
test_resizing_SOURCES= \
test-resizing.c
test_size_hints_SOURCES= \
test-size-hints.c
test_attached_SOURCES= \
test-attached.c
test_focus_SOURCES= \
test-focus.c
noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window test-size-hints test-attached test-focus
wm_tester_LDADD= @MUTTER_LIBS@
test_gravity_LDADD= @MUTTER_LIBS@
test_resizing_LDADD= @MUTTER_LIBS@
test_size_hints_LDADD= @MUTTER_LIBS@
focus_window_LDADD= @MUTTER_LIBS@
test_attached_LDADD= @MUTTER_LIBS@
test_focus_LDADD= @MUTTER_LIBS@

View File

@@ -0,0 +1,37 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
Display *d;
Window w;
const char *w_str;
char *end;
if (argc != 2)
{
fprintf (stderr, "Usage: focus-window WINDOWID\n");
exit (1);
}
d = XOpenDisplay (NULL);
w_str = argv[1];
end = NULL;
w = strtoul (w_str, &end, 16);
if (end == w_str)
{
fprintf (stderr, "Usage: focus-window WINDOWID\n");
exit (1);
}
printf ("Setting input focus to 0x%lx\n", w);
XSetInputFocus (d, w, RevertToPointerRoot, CurrentTime);
XFlush (d);
return 0;
}

245
src/wm-tester/main.c Normal file
View File

@@ -0,0 +1,245 @@
/* WM tester main() */
/*
* Copyright (C) 2001 Havoc Pennington
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <gtk/gtk.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void set_up_the_evil (void);
static void set_up_icon_windows (void);
static void
usage (void)
{
g_print ("wm-tester [--evil] [--icon-windows]\n");
exit (0);
}
int
main (int argc, char **argv)
{
int i;
gboolean do_evil;
gboolean do_icon_windows;
gtk_init (&argc, &argv);
do_evil = FALSE;
do_icon_windows = FALSE;
i = 1;
while (i < argc)
{
const char *arg = argv[i];
if (strcmp (arg, "--help") == 0 ||
strcmp (arg, "-h") == 0 ||
strcmp (arg, "-?") == 0)
usage ();
else if (strcmp (arg, "--evil") == 0)
do_evil = TRUE;
else if (strcmp (arg, "--icon-windows") == 0)
do_icon_windows = TRUE;
else
usage ();
++i;
}
/* Be sure some option was provided */
if (! (do_evil || do_icon_windows))
return 1;
if (do_evil)
set_up_the_evil ();
if (do_icon_windows)
set_up_icon_windows ();
gtk_main ();
return 0;
}
static GSList *evil_windows = NULL;
static gint
evil_timeout (gpointer data)
{
int i;
int n_windows;
int len;
int create_count;
int destroy_count;
len = g_slist_length (evil_windows);
if (len > 35)
{
create_count = 2;
destroy_count = 5;
}
else
{
create_count = 5;
destroy_count = 5;
}
/* Create some windows */
n_windows = g_random_int_range (0, create_count);
i = 0;
while (i < n_windows)
{
GtkWidget *w;
GtkWidget *c;
int t;
GtkWidget *parent;
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_move (GTK_WINDOW (w),
g_random_int_range (0,
gdk_screen_width ()),
g_random_int_range (0,
gdk_screen_height ()));
parent = NULL;
/* set transient for random window (may create all kinds of weird cycles) */
if (len > 0)
{
t = g_random_int_range (- (len / 3), len);
if (t >= 0)
{
parent = g_slist_nth_data (evil_windows, t);
if (parent != NULL)
gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (parent));
}
}
if (parent != NULL)
c = gtk_button_new_with_label ("Evil Transient!");
else
c = gtk_button_new_with_label ("Evil Window!");
gtk_container_add (GTK_CONTAINER (w), c);
gtk_widget_show_all (w);
evil_windows = g_slist_prepend (evil_windows, w);
++i;
}
/* Destroy some windows */
if (len > destroy_count)
{
n_windows = g_random_int_range (0, destroy_count);
i = 0;
while (i < n_windows)
{
GtkWidget *w;
w = g_slist_nth_data (evil_windows,
g_random_int_range (0, len));
if (w)
{
--len;
evil_windows = g_slist_remove (evil_windows, w);
gtk_widget_destroy (w);
}
++i;
}
}
return TRUE;
}
static void
set_up_the_evil (void)
{
g_timeout_add (400, evil_timeout, NULL);
}
static void
set_up_icon_windows (void)
{
int i;
int n_windows;
/* Create some windows */
n_windows = 9;
i = 0;
while (i < n_windows)
{
GtkWidget *w;
GtkWidget *c;
GList *icons;
GdkPixbuf *pix;
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
c = gtk_button_new_with_label ("Icon window");
gtk_container_add (GTK_CONTAINER (w), c);
icons = NULL;
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_LARGE_TOOLBAR,
NULL);
icons = g_list_append (icons, pix);
if (i % 2)
{
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_DIALOG,
NULL);
icons = g_list_append (icons, pix);
}
if (i % 3)
{
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_MENU,
NULL);
icons = g_list_append (icons, pix);
}
gtk_window_set_icon_list (GTK_WINDOW (w), icons);
g_list_foreach (icons, (GFunc) g_object_unref, NULL);
g_list_free (icons);
gtk_widget_show_all (w);
++i;
}
}

View File

@@ -0,0 +1,100 @@
#include <gtk/gtk.h>
enum {
DESTROY_PARENT,
DETACH,
ATTACH_1,
ATTACH_2
};
GtkWidget *window1, *window2;
static void
dialog_response (GtkDialog *dialog, int response, gpointer user_data)
{
if (response == DESTROY_PARENT)
{
GtkWidget *window = GTK_WIDGET (gtk_window_get_transient_for (GTK_WINDOW (dialog)));
if (window == window1)
{
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
window1 = NULL;
}
else
{
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
window2 = NULL;
}
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
gtk_widget_destroy (window);
}
else if (response == DETACH)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL);
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
}
else if (response == ATTACH_1)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window1));
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
}
else if (response == ATTACH_2)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window2));
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
}
else if (response == GTK_RESPONSE_CLOSE)
gtk_main_quit ();
}
int
main (int argc, char **argv)
{
GtkWidget *dialog;
gtk_init (&argc, &argv);
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window1), "Parent 1");
gtk_widget_show (window1);
window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window2), "Parent 2");
gtk_widget_show (window2);
dialog = gtk_dialog_new_with_buttons ("Child",
NULL,
GTK_DIALOG_MODAL,
"Destroy Parent",
DESTROY_PARENT,
"Detach",
DETACH,
"Attach to 1",
ATTACH_1,
"Attach to 2",
ATTACH_2,
GTK_STOCK_QUIT,
GTK_RESPONSE_CLOSE,
NULL);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DETACH, FALSE);
g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), NULL);
gtk_widget_show (dialog);
gtk_main ();
return 0;
}

362
src/wm-tester/test-focus.c Normal file
View File

@@ -0,0 +1,362 @@
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
GtkWidget *main_window;
GtkWidget *noinput_window, *passive_window, *local_window;
GtkWidget *global_window, *lame_window, *grabby_window, *dying_window;
static void
clear_on_destroy (GtkWidget *widget, gpointer user_data)
{
GtkWidget **widget_pointer = user_data;
*widget_pointer = NULL;
}
static void
disable_take_focus (GtkWidget *window)
{
GdkDisplay *display;
GdkWindow *gdkwindow;
Atom *protocols, wm_take_focus;
int n_protocols, i;
gtk_widget_realize (window);
gdkwindow = gtk_widget_get_window (window);
display = gdk_window_get_display (gdkwindow);
wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
XGetWMProtocols (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (gdkwindow),
&protocols, &n_protocols);
for (i = 0; i < n_protocols; i++)
{
if (protocols[i] == wm_take_focus)
{
protocols[i] = protocols[n_protocols - 1];
n_protocols--;
break;
}
}
XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (gdkwindow),
protocols, n_protocols);
XFree (protocols);
}
static void
clear_input_hint (GtkWidget *window)
{
/* This needs to be called after gtk_widget_show, otherwise
* GTK+ will overwrite it. */
GdkWindow *gdkwindow = gtk_widget_get_window (window);
XWMHints *wm_hints;
wm_hints = XGetWMHints (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
GDK_WINDOW_XID (gdkwindow));
wm_hints->flags |= InputHint;
wm_hints->input = False;
XSetWMHints (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
GDK_WINDOW_XID (gdkwindow),
wm_hints);
XFree (wm_hints);
}
static void
active_notify (GObject *obj,
GParamSpec *pspec,
gpointer user_data)
{
GtkLabel *label = user_data;
if (gtk_window_is_active (GTK_WINDOW (obj)))
gtk_label_set_text (label, "Focused");
else
gtk_label_set_text (label, "Not focused");
}
static void
make_focused_label (GtkWidget *toplevel,
GtkWidget *parent)
{
GtkWidget *label;
label = gtk_label_new ("");
gtk_widget_show (label);
gtk_container_add (GTK_CONTAINER (parent), label);
g_signal_connect (toplevel, "notify::is-active",
G_CALLBACK (active_notify), label);
active_notify (G_OBJECT (toplevel), NULL, label);
}
static void
setup_test_dialog (GtkWidget *toplevel)
{
make_focused_label (toplevel, toplevel);
gtk_widget_set_size_request (toplevel, 200, 200);
}
static void
noinput_clicked (GtkButton *button, gpointer user_data)
{
if (noinput_window)
gtk_window_present_with_time (GTK_WINDOW (noinput_window), gtk_get_current_event_time ());
else
{
noinput_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "No Input",
"accept-focus", FALSE,
NULL);
setup_test_dialog (noinput_window);
g_signal_connect (noinput_window, "destroy",
G_CALLBACK (clear_on_destroy), &noinput_window);
disable_take_focus (noinput_window);
gtk_widget_show (noinput_window);
}
}
static void
passive_clicked (GtkButton *button, gpointer user_data)
{
if (passive_window)
gtk_window_present_with_time (GTK_WINDOW (passive_window), gtk_get_current_event_time ());
else
{
passive_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Passive Input",
"accept-focus", TRUE,
NULL);
setup_test_dialog (passive_window);
g_signal_connect (passive_window, "destroy",
G_CALLBACK (clear_on_destroy), &passive_window);
disable_take_focus (passive_window);
gtk_widget_show (passive_window);
}
}
static void
local_clicked (GtkButton *button, gpointer user_data)
{
if (local_window)
gtk_window_present_with_time (GTK_WINDOW (local_window), gtk_get_current_event_time ());
else
{
local_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Locally Active Input",
"accept-focus", TRUE,
NULL);
setup_test_dialog (local_window);
g_signal_connect (local_window, "destroy",
G_CALLBACK (clear_on_destroy), &local_window);
gtk_widget_show (local_window);
}
}
static void
global_clicked (GtkButton *button, gpointer user_data)
{
if (global_window)
gtk_window_present_with_time (GTK_WINDOW (global_window), gtk_get_current_event_time ());
else
{
/* gtk will only process WM_TAKE_FOCUS messages if accept-focus
* is TRUE. So we set that property and then manually clear the
* Input WMHint.
*/
global_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Globally Active Input",
"accept-focus", TRUE,
NULL);
setup_test_dialog (global_window);
g_signal_connect (global_window, "destroy",
G_CALLBACK (clear_on_destroy), &global_window);
gtk_widget_show (global_window);
clear_input_hint (global_window);
}
}
static void
lame_clicked (GtkButton *button, gpointer user_data)
{
if (lame_window)
gtk_window_present_with_time (GTK_WINDOW (lame_window), gtk_get_current_event_time ());
else
{
lame_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Lame Globally Active Input",
"accept-focus", FALSE,
NULL);
setup_test_dialog (lame_window);
g_signal_connect (lame_window, "destroy",
G_CALLBACK (clear_on_destroy), &lame_window);
gtk_widget_show (lame_window);
}
}
static void
grabby_active_changed (GObject *object, GParamSpec *param, gpointer user_data)
{
if (gtk_window_is_active (GTK_WINDOW (grabby_window)))
{
GdkWindow *gdkwindow = gtk_widget_get_window (grabby_window);
guint32 now = gdk_x11_get_server_time (gdkwindow);
gtk_window_present_with_time (GTK_WINDOW (main_window), now - 1);
XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_window_get_display (gdkwindow)),
GDK_WINDOW_XID (gdkwindow),
RevertToParent,
now);
}
}
static void
grabby_clicked (GtkButton *button, gpointer user_data)
{
if (grabby_window)
gtk_window_present_with_time (GTK_WINDOW (grabby_window), gtk_get_current_event_time ());
else
{
grabby_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Focus-grabbing Window",
"accept-focus", TRUE,
/* Because mutter maps windows
* asynchronously, our trick won't
* work if we try to do it when the
* window is first mapped.
*/
"focus-on-map", FALSE,
NULL);
setup_test_dialog (grabby_window);
g_signal_connect (grabby_window, "destroy",
G_CALLBACK (clear_on_destroy), &grabby_window);
g_signal_connect (grabby_window, "notify::is-active",
G_CALLBACK (grabby_active_changed), NULL);
gtk_widget_show (grabby_window);
}
}
static void
dying_clicked (GtkButton *button, gpointer user_data)
{
if (dying_window)
{
gtk_window_present_with_time (GTK_WINDOW (dying_window), gtk_get_current_event_time ());
gtk_widget_destroy (dying_window);
}
else
{
GtkWidget *label;
dying_window = g_object_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"title", "Dying Window",
"accept-focus", TRUE,
/* As with grabby window */
"focus-on-map", FALSE,
NULL);
setup_test_dialog (dying_window);
g_signal_connect (dying_window, "destroy",
G_CALLBACK (clear_on_destroy), &dying_window);
label = gtk_label_new ("Click button again to test");
gtk_container_add (GTK_CONTAINER (dying_window), label);
gtk_widget_set_size_request (dying_window, 200, 200);
gtk_widget_show_all (dying_window);
}
}
static void
main_window_destroyed (GtkWidget *widget, gpointer user_data)
{
gtk_main_quit ();
}
int
main (int argc, char **argv)
{
GtkWidget *vbox, *button;
gtk_init (&argc, &argv);
main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (main_window), "Focus Tester");
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_box_set_homogeneous (GTK_BOX (vbox), 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_container_add (GTK_CONTAINER (main_window), vbox);
make_focused_label (main_window, vbox);
/* ICCCM "No Input" mode; Input hint False, WM_TAKE_FOCUS absent */
button = gtk_button_new_with_label ("No Input Window");
g_signal_connect (button, "clicked", G_CALLBACK (noinput_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* ICCCM "Passive" mode; Input hint True, WM_TAKE_FOCUS absent */
button = gtk_button_new_with_label ("Passive Input Window");
g_signal_connect (button, "clicked", G_CALLBACK (passive_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* ICCCM "Locally Active" mode; Input hint True, WM_TAKE_FOCUS present.
* This is the behavior of GtkWindows with accept_focus==TRUE.
*/
button = gtk_button_new_with_label ("Locally Active Window");
g_signal_connect (button, "clicked", G_CALLBACK (local_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* ICCCM "Globally Active" mode; Input hint False, WM_TAKE_FOCUS present,
* and the window responds to WM_TAKE_FOCUS by calling XSetInputFocus.
*/
button = gtk_button_new_with_label ("Globally Active Window");
g_signal_connect (button, "clicked", G_CALLBACK (global_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* "Lame" Globally Active mode; like "Globally Active", except that
* the window does not respond to WM_TAKE_FOCUS. This is the
* behavior of GtkWindows with accept_focus==FALSE.
*/
button = gtk_button_new_with_label ("Globally Lame Window");
g_signal_connect (button, "clicked", G_CALLBACK (lame_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* "Grabby" window; when you activate the window, it asks the wm to
* focus the main window, but then forcibly grabs focus back with
* a newer timestamp, causing the wm to be temporarily confused
* about what window is focused and triggering the "Earlier attempt
* to focus ... failed" codepath.
*/
button = gtk_button_new_with_label ("Grabby Window");
g_signal_connect (button, "clicked", G_CALLBACK (grabby_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
/* "Dying" window; we create the window on the first click, then
* activate it and destroy it on the second click, causing mutter to
* do an XSetInputFocus but not receive the corresponding FocusIn.
*/
button = gtk_button_new_with_label ("Dying Window");
g_signal_connect (button, "clicked", G_CALLBACK (dying_clicked), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
gtk_widget_show_all (main_window);
g_signal_connect (main_window, "destroy",
G_CALLBACK (main_window_destroyed), NULL);
gtk_main ();
return 0;
}

View File

@@ -0,0 +1,308 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <string.h>
static int gravities[10] = {
NorthWestGravity,
NorthGravity,
NorthEastGravity,
WestGravity,
CenterGravity,
EastGravity,
SouthWestGravity,
SouthGravity,
SouthEastGravity,
StaticGravity
};
typedef struct
{
int x, y, width, height;
} Rectangle;
static Window windows[10];
static int doubled[10] = { 0, };
static Rectangle window_rects[10];
#define WINDOW_WIDTH 100
#define WINDOW_HEIGHT 100
static int x_offset[3] = { 0, - WINDOW_WIDTH/2, -WINDOW_WIDTH };
static int y_offset[3] = { 0, - WINDOW_HEIGHT/2, -WINDOW_HEIGHT };
static double screen_x_fraction[3] = { 0, 0.5, 1.0 };
static double screen_y_fraction[3] = { 0, 0.5, 1.0 };
static int screen_width;
static int screen_height;
static const char*
window_gravity_to_string (int gravity)
{
switch (gravity)
{
case NorthWestGravity:
return "NorthWestGravity";
case NorthGravity:
return "NorthGravity";
case NorthEastGravity:
return "NorthEastGravity";
case WestGravity:
return "WestGravity";
case CenterGravity:
return "CenterGravity";
case EastGravity:
return "EastGravity";
case SouthWestGravity:
return "SouthWestGravity";
case SouthGravity:
return "SouthGravity";
case SouthEastGravity:
return "SouthEastGravity";
case StaticGravity:
return "StaticGravity";
default:
return "NorthWestGravity";
}
}
static void
calculate_position (int i, int doubled, int *x, int *y)
{
if (i == 9)
{
*x = 150;
*y = 150;
}
else
{
int xoff = x_offset[i % 3];
int yoff = y_offset[i / 3];
if (doubled)
{
xoff *= 2;
yoff *= 2;
}
*x = screen_x_fraction[i % 3] * screen_width + xoff;
*y = screen_y_fraction[i / 3] * screen_height + yoff;
}
}
static int
find_window (Window window)
{
int i;
for (i=0; i<10; i++)
{
if (windows[i] == window)
return i;
}
return -1;
}
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
#define MWM_HINTS_INPUT_MODE (1L << 2)
#define MWM_HINTS_STATUS (1L << 3)
int main (int argc, char **argv)
{
Display *d;
Window w;
XSizeHints hints;
int i;
int screen;
XEvent ev;
int noframes;
if (argc > 1 && strcmp (argv[1], "--noframes") == 0)
noframes = 1;
else
noframes = 0;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
screen_width = DisplayWidth (d, screen);
screen_height = DisplayHeight (d, screen);
for (i=0; i<10; i++)
{
int x, y;
calculate_position (i, doubled[i], &x, &y);
w = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
WhitePixel (d, screen), WhitePixel (d, screen));
windows[i] = w;
window_rects[i].x = x;
window_rects[i].y = y;
window_rects[i].width = WINDOW_WIDTH;
window_rects[i].height = WINDOW_HEIGHT;
XSelectInput (d, w, ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity;
hints.min_width = WINDOW_WIDTH / 2;
hints.min_height = WINDOW_HEIGHT / 2;
#if 1
/* we constrain max size below the "doubled" size so that
* the WM will have to deal with constraints
* at the same time it's dealing with configure request
*/
hints.max_width = WINDOW_WIDTH * 2 - WINDOW_WIDTH / 2;
hints.max_height = WINDOW_HEIGHT * 2 - WINDOW_HEIGHT / 2;
#else
hints.max_width = WINDOW_WIDTH * 2 + WINDOW_WIDTH / 2;
hints.max_height = WINDOW_HEIGHT * 2 + WINDOW_HEIGHT / 2;
#endif
hints.win_gravity = gravities[i];
XSetWMNormalHints (d, w, &hints);
XStoreName (d, w, window_gravity_to_string (hints.win_gravity));
if (noframes)
{
MotifWmHints mwm;
Atom mwm_atom;
mwm.decorations = 0;
mwm.flags = MWM_HINTS_DECORATIONS;
mwm_atom = XInternAtom (d, "_MOTIF_WM_HINTS", False);
XChangeProperty (d, w, mwm_atom, mwm_atom,
32, PropModeReplace,
(unsigned char *)&mwm,
sizeof (MotifWmHints)/sizeof (long));
}
XMapWindow (d, w);
}
while (1)
{
XNextEvent (d, &ev);
if (ev.xany.type == ConfigureNotify)
{
i = find_window (ev.xconfigure.window);
if (i >= 0)
{
Window ignored;
window_rects[i].width = ev.xconfigure.width;
window_rects[i].height = ev.xconfigure.height;
XClearArea (d, windows[i], 0, 0,
ev.xconfigure.width,
ev.xconfigure.height,
True);
if (!ev.xconfigure.send_event)
XTranslateCoordinates (d, windows[i], DefaultRootWindow (d),
0, 0,
&window_rects[i].x, &window_rects[i].y,
&ignored);
else
{
window_rects[i].x = ev.xconfigure.x;
window_rects[i].y = ev.xconfigure.y;
}
}
}
else if (ev.xany.type == Expose)
{
i = find_window (ev.xexpose.window);
if (i >= 0)
{
GC gc;
XGCValues values;
char buf[256];
values.foreground = BlackPixel (d, screen);
gc = XCreateGC (d, windows[i],
GCForeground, &values);
sprintf (buf,
"%d,%d",
window_rects[i].x,
window_rects[i].y);
XDrawString (d, windows[i], gc, 10, 15,
buf, strlen (buf));
sprintf (buf,
"%dx%d",
window_rects[i].width,
window_rects[i].height);
XDrawString (d, windows[i], gc, 10, 35,
buf, strlen (buf));
XFreeGC (d, gc);
}
}
else if (ev.xany.type == ButtonPress)
{
i = find_window (ev.xbutton.window);
if (i >= 0)
{
/* Button 1 = move, 2 = resize, 3 = both at once */
if (ev.xbutton.button == Button1)
{
int x, y;
calculate_position (i, doubled[i], &x, &y);
XMoveWindow (d, windows[i], x, y);
}
else if (ev.xbutton.button == Button2)
{
if (doubled[i])
XResizeWindow (d, windows[i], WINDOW_WIDTH, WINDOW_HEIGHT);
else
XResizeWindow (d, windows[i], WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
doubled[i] = !doubled[i];
}
else if (ev.xbutton.button == Button3)
{
int x, y;
calculate_position (i, !doubled[i], &x, &y);
if (doubled[i])
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
else
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
doubled[i] = !doubled[i];
}
}
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

View File

@@ -0,0 +1,257 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <glib.h>
static void
calc_rects (XRectangle *rects, int width, int height)
{
int w = (width - 21) / 3;
int h = (height - 21) / 3;
int i;
i = 0;
while (i < 9)
{
rects[i].width = w;
rects[i].height = h;
++i;
}
/* NW */
rects[0].x = 0;
rects[0].y = 0;
/* N */
rects[1].x = width / 2 - w / 2;
rects[1].y = 0;
/* NE */
rects[2].x = width - w;
rects[2].y = 0;
/* E */
rects[3].x = width - w;
rects[3].y = height / 2 - h / 2;
/* SE */
rects[4].x = width - w;
rects[4].y = height - h;
/* S */
rects[5].x = width / 2 - w / 2;
rects[5].y = height - h;
/* SW */
rects[6].x = 0;
rects[6].y = height - h;
/* W */
rects[7].x = 0;
rects[7].y = height / 2 - h / 2;
/* Center */
rects[8].x = width / 2 - w / 2;
rects[8].y = height / 2 - h / 2;
}
static Bool
all_events (Display *display,
XEvent *event,
XPointer arg)
{
return True;
}
static void
get_size (Display *d, Drawable draw,
int *xp, int *yp, int *widthp, int *heightp)
{
int x, y;
unsigned int width=0, height=0, border=0, depth=0;
Window root;
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
if (xp)
*xp = x;
if (yp)
*yp = y;
if (widthp)
*widthp = width;
if (heightp)
*heightp = height;
}
int
main (int argc, char **argv)
{
Display *d;
Window w, cw;
XSizeHints hints;
int screen;
XEvent ev;
int x, y, width, height;
Pixmap pix;
GC gc;
XGCValues gc_vals;
XSetWindowAttributes set_attrs;
XWindowChanges changes;
XRectangle rects[9];
gboolean redraw_pending;
unsigned int mask;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
/* Print some debug spew to show how StaticGravity works */
w = XCreateSimpleWindow (d, RootWindow (d, screen),
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
cw = XCreateSimpleWindow (d, w,
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.win_gravity = StaticGravity;
XChangeWindowAttributes (d, cw,
CWWinGravity,
&set_attrs);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
changes.x = 10;
changes.y = 10;
changes.width = 110;
changes.height = 110;
/* last mask wins */
mask = CWX | CWY;
mask = CWWidth | CWHeight;
mask = CWX | CWY | CWWidth | CWHeight;
XConfigureWindow (d, w, mask, &changes);
XSync (d, False);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
XDestroyWindow (d, w);
/* The window that gets displayed */
x = 20;
y = 20;
width = 100;
height = 100;
calc_rects (rects, width, height);
w = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, width, height, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.bit_gravity = StaticGravity;
XChangeWindowAttributes (d, w,
CWBitGravity,
&set_attrs);
XSelectInput (d, w,
ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = PMinSize;
hints.min_width = 100;
hints.min_height = 100;
XSetWMNormalHints (d, w, &hints);
XMapWindow (d, w);
redraw_pending = FALSE;
while (1)
{
XNextEvent (d, &ev);
switch (ev.xany.type)
{
case ButtonPress:
if (ev.xbutton.button == 3)
{
g_print ("Exiting on button 3 press\n");
exit (0);
}
break;
case ConfigureNotify:
x = ev.xconfigure.x;
y = ev.xconfigure.y;
width = ev.xconfigure.width;
height = ev.xconfigure.height;
redraw_pending = TRUE;
break;
case Expose:
redraw_pending = TRUE;
break;
default:
break;
}
/* Primitive event compression */
if (XCheckIfEvent (d, &ev, all_events, NULL))
{
XPutBackEvent (d, &ev);
}
else if (redraw_pending)
{
calc_rects (rects, width, height);
pix = XCreatePixmap (d, w, width, height,
DefaultDepth (d, screen));
gc_vals.foreground = WhitePixel (d, screen);
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
XFillRectangle (d, pix, gc, 0, 0, width, height);
/* Draw rectangles at each gravity point */
gc_vals.foreground = BlackPixel (d, screen);
XChangeGC (d, gc, GCForeground, &gc_vals);
XFillRectangles (d, pix, gc, rects, G_N_ELEMENTS (rects));
XCopyArea (d, pix, w, gc, 0, 0, width, height, 0, 0);
XFreePixmap (d, pix);
XFreeGC (d, gc);
redraw_pending = FALSE;
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

View File

@@ -0,0 +1,136 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <glib.h>
static Bool
all_events (Display *display,
XEvent *event,
XPointer arg)
{
return True;
}
#if 0
static void
get_size (Display *d, Drawable draw,
int *xp, int *yp, int *widthp, int *heightp)
{
int x, y;
unsigned int width, height, border, depth;
Window root;
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
if (xp)
*xp = x;
if (yp)
*yp = y;
if (widthp)
*widthp = width;
if (*heightp)
*heightp = height;
}
#endif
int
main (int argc, char **argv)
{
Display *d;
Window zero_min_size;
XSizeHints hints;
int screen;
XEvent ev;
int x, y, width, height;
Pixmap pix;
GC gc;
XGCValues gc_vals;
gboolean redraw_pending;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
x = 0;
y = 0;
width = 100;
height = 100;
zero_min_size = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, width, height, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
XSelectInput (d, zero_min_size,
ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = PMinSize;
hints.min_width = 0;
hints.min_height = 0;
XSetWMNormalHints (d, zero_min_size, &hints);
XMapWindow (d, zero_min_size);
redraw_pending = FALSE;
while (1)
{
XNextEvent (d, &ev);
switch (ev.xany.type)
{
case ButtonPress:
if (ev.xbutton.button == 1)
{
g_print ("Exiting on button 1 press\n");
exit (0);
}
break;
case ConfigureNotify:
x = ev.xconfigure.x;
y = ev.xconfigure.y;
width = ev.xconfigure.width;
height = ev.xconfigure.height;
redraw_pending = TRUE;
break;
case Expose:
redraw_pending = TRUE;
break;
default:
break;
}
/* Primitive event compression */
if (XCheckIfEvent (d, &ev, all_events, NULL))
{
XPutBackEvent (d, &ev);
}
else if (redraw_pending)
{
pix = XCreatePixmap (d, zero_min_size, width, height,
DefaultDepth (d, screen));
gc_vals.foreground = WhitePixel (d, screen);
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
XFillRectangle (d, pix, gc, 0, 0, width, height);
XCopyArea (d, pix, zero_min_size, gc, 0, 0, width, height, 0, 0);
XFreePixmap (d, pix);
XFreeGC (d, gc);
redraw_pending = FALSE;
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

View File

@@ -1,290 +0,0 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Mutter.DisplayConfig:
@short_description: display configuration interface
This interface is used by mutter and gnome-settings-daemon
to apply multiple monitor configuration.
-->
<interface name="org.gnome.Mutter.DisplayConfig">
<!--
GetResources:
@serial: configuration serial
@crtcs: available CRTCs
@outputs: available outputs
@modes: available modes
@max_screen_width:
@max_screen_height:
Retrieves the current layout of the hardware.
@serial is an unique identifier representing the current state
of the screen. It must be passed back to ApplyConfiguration()
and will be increased for every configuration change (so that
mutter can detect that the new configuration is based on old
state).
A CRTC (CRT controller) is a logical monitor, ie a portion
of the compositor coordinate space. It might correspond
to multiple monitors, when in clone mode, but not that
it is possible to implement clone mode also by setting different
CRTCs to the same coordinates.
The number of CRTCs represent the maximum number of monitors
that can be set to expand and it is a HW constraint; if more
monitors are connected, then necessarily some will clone. This
is complementary to the concept of the encoder (not exposed in
the API), which groups outputs that necessarily will show the
same image (again a HW constraint).
A CRTC is represented by a DBus structure with the following
layout:
* u ID: the ID in the API of this CRTC
* x winsys_id: the low-level ID of this CRTC (which might
be a XID, a KMS handle or something entirely
different)
* i x, y, width, height: the geometry of this CRTC
(might be invalid if the CRTC is not in
use)
* i current_mode: the current mode of the CRTC, or -1 if this
CRTC is not used
Note: the size of the mode will always correspond
to the width and height of the CRTC
* u current_transform: the current transform (espressed according
to the wayland protocol)
* au transforms: all possible transforms
* a{sv} properties: other high-level properties that affect this
CRTC; they are not necessarily reflected in
the hardware.
No property is specified in this version of the API.
Note: all geometry information refers to the untransformed
display.
An output represents a physical screen, connected somewhere to
the computer. Floating connectors are not exposed in the API.
An output is a DBus struct with the following fields:
* u ID: the ID in the API
* x winsys_id: the low-level ID of this output (XID or KMS handle)
* i current_crtc: the CRTC that is currently driving this output,
or -1 if the output is disabled
* au possible_crtcs: all CRTCs that can control this output
* s name: the name of the connector to which the output is attached
(like VGA1 or HDMI)
* au modes: valid modes for this output
* au clones: valid clones for this output, ie other outputs that
can be assigned the same CRTC as this one; if you
want to mirror two outputs that don't have each other
in the clone list, you must configure two different
CRTCs for the same geometry
* a{sv} properties: other high-level properties that affect this
output; they are not necessarily reflected in
the hardware.
Known properties:
- "vendor" (s): (readonly) the human readable name
of the manufacturer
- "product" (s): (readonly) the human readable name
of the display model
- "serial" (s): (readonly) the serial number of this
particular hardware part
- "display-name" (s): (readonly) a human readable name
of this output, to be shown in the UI
- "backlight" (i): (readonly, use the specific interface)
the backlight value as a percentage
(-1 if not supported)
- "primary" (b): whether this output is primary
or not
- "presentation" (b): whether this output is
for presentation only
Note: properties might be ignored if not consistenly
applied to all outputs in the same clone group. In
general, it's expected that presentation or primary
outputs will not be cloned.
A mode represents a set of parameters that are applied to
each output, such as resolution and refresh rate. It is a separate
object so that it can be referenced by CRTCs and outputs.
Multiple outputs in the same CRTCs must all have the same mode.
A mode is exposed as:
* u ID: the ID in the API
* x winsys_id: the low-level ID of this mode
* u width, height: the resolution
* d frequency: refresh rate
Output and modes are read-only objects (except for output properties),
they can change only in accordance to HW changes (such as hotplugging
a monitor), while CRTCs can be changed with ApplyConfiguration().
XXX: actually, if you insist enough, you can add new modes
through xrandr command line or the KMS API, overriding what the
kernel driver and the EDID say.
Usually, it only matters with old cards with broken drivers, or
old monitors with broken EDIDs, but it happens more often with
projectors (if for example the kernel driver doesn't add the
640x480 - 800x600 - 1024x768 default modes). Probably something
that we need to handle in mutter anyway.
-->
<method name="GetResources">
<arg name="serial" direction="out" type="u" />
<arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
<arg name="outputs" direction="out" type="a(uxiausauaua{sv})" />
<arg name="modes" direction="out" type="a(uxuud)" />
<arg name="max_screen_width" direction="out" type="i" />
<arg name="max_screen_height" direction="out" type="i" />
</method>
<!--
ApplyConfiguration:
@serial: configuration serial
@persistent: whether this configuration should be saved on disk
@crtcs: new data for CRTCs
@outputs: new data for outputs
Applies the requested configuration changes.
@serial must match the serial from the last GetResources() call,
or org.freedesktop.DBus.AccessDenied will be generated.
If @persistent is true, mutter will attempt to replicate this
configuration the next time this HW layout appears.
@crtcs represents the new logical configuration, as a list
of structures containing:
- u ID: the API ID from the corresponding GetResources() call
- i new_mode: the API ID of the new mode to configure the CRTC
with, or -1 if the CRTC should be disabled
- i x, y: the new coordinates of the top left corner
the geometry will be completed with the size information
from @new_mode
- u transform: the desired transform
- au outputs: the API ID of outputs that should be assigned to
this CRTC
- a{sv} properties: properties whose value should be changed
Note: CRTCs not referenced in the array will be disabled.
@outputs represent the output property changes as:
- u ID: the API ID of the output to change
- a{sv} properties: properties whose value should be changed
Note: both for CRTCs and outputs, properties not included in
the dictionary will not be changed.
Note: unrecognized properties will have no effect, but if the
configuration change succeeds the property will be reported
by the next GetResources() call, and if @persistent is true,
it will also be saved to disk.
If the configuration is invalid according to the previous
GetResources() call, for example because a CRTC references
an output it cannot drive, or not all outputs support the
chosen mode, the error org.freedesktop.DBus.InvalidArgs will
be generated.
If the configuration cannot be applied for any other reason
(eg. the screen size would exceed texture limits), the error
org.freedesktop.DBus.Error.LimitsExceeded will be generated.
-->
<method name="ApplyConfiguration">
<arg name="serial" direction="in" type="u" />
<arg name="persistent" direction="in" type="b" />
<arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
<arg name="outputs" direction="in" type="a(ua{sv})" />
</method>
<!--
ChangeBacklight:
@serial: configuration serial
@output: the API id of the output
@value: the new backlight value
Changes the backlight of @output to @value, which is
expressed as a percentage and rounded to the HW limits.
-->
<method name="ChangeBacklight">
<arg name="serial" direction="in" type="u" />
<arg name="output" direction="in" type="u" />
<arg name="value" direction="in" type="i" />
</method>
<!--
GetCrtcGamma:
@serial: configuration serial
@crtc: API id of the crtc
@red: red gamma ramp
@green: green gamma ramp
@blue: blue gamma ramp
Requests the current gamma ramps of @crtc.
-->
<method name="GetCrtcGamma">
<arg name="serial" direction="in" type="u" />
<arg name="crtc" direction="in" type="u" />
<arg name="red" direction="out" type="aq" />
<arg name="green" direction="out" type="aq" />
<arg name="blue" direction="out" type="aq" />
</method>
<!--
SetCrtcGamma:
@serial: configuration serial
@crtc: API id of the crtc
@red: red gamma ramp
@green: green gamma ramp
@blue: blue gamma ramp
Changes the gamma ramps of @crtc.
-->
<method name="SetCrtcGamma">
<arg name="serial" direction="in" type="u" />
<arg name="crtc" direction="in" type="u" />
<arg name="red" direction="in" type="aq" />
<arg name="green" direction="in" type="aq" />
<arg name="blue" direction="in" type="aq" />
</method>
<!--
PowerSaveMode:
Contains the current power saving mode for the screen, and
allows changing it.
Possible values:
- 0: on
- 1: standby
- 2: suspend
- 3: off
- -1: unknown (unsupported)
A client should not attempt to change the powersave mode
from -1 (unknown) to any other value, and viceversa.
Note that the actual effects of the different values
depend on the hardware and the kernel driver in use, and
it's perfectly possible that all values different than on
have the same effect.
Also, setting the PowerSaveMode to 3 (off) may or may
not have the same effect as disabling all outputs by
setting no CRTC on them with ApplyConfiguration(), and
may or may not cause a configuration change.
Also note that this property might become out of date
if changed through different means (for example using the
XRandR interface directly).
-->
<property name="PowerSaveMode" type="i" access="readwrite" />
<!--
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>