Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
8b80a70efc | |||
63ad42e1f6 | |||
6b3be51ca8 | |||
46d57bf0ac | |||
8dd7102909 | |||
7a57e59fcc | |||
6772758a64 | |||
08ba9c689e | |||
bdb2dac244 | |||
dd9b1ce440 | |||
878f0e6443 | |||
fc1f78e8cc | |||
25aa942a0e | |||
56e74b1ea8 | |||
7d3204b196 | |||
d7ff632c67 | |||
6d3e64226d | |||
2e7b9e0dfe | |||
08d81b6f7f | |||
e01077914d | |||
d7cf6bed63 | |||
d071ba8446 | |||
4d08e89c16 | |||
21d8c4b032 | |||
c98686da92 | |||
a19eda5ae7 | |||
0a9bbe0109 | |||
a8eb42e43c | |||
9d0c9f1f42 | |||
9fa0743394 | |||
bb79a20fac |
48
NEWS
48
NEWS
@ -1,28 +1,44 @@
|
||||
3.15.2
|
||||
3.14.4
|
||||
======
|
||||
* Don't enable hiDPI on monitors with broken EDID [Bastien; #734839]
|
||||
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
|
||||
* Fix "flicker" during startup transition [Ray; #740377]
|
||||
* Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890]
|
||||
* Fix flash on unredirection [Chris; #743858]
|
||||
* Fix incompatibility with GLES2 GLSL [Alban; #745442]
|
||||
* Add function to refresh all background instances [Rui; #739178]
|
||||
* Fix geometry of shaded windows [Florian; #746145]
|
||||
* Misc. bug fixes [Florian, Rui; #698995, #743217, #743254]
|
||||
|
||||
Contributors:
|
||||
Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
|
||||
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
|
||||
Alban Browaeys, Rui Matos, Florian Müllner, Chris Wilson
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb]
|
||||
Matej Urbančič [sl], Muhammet Kara [tr], Samir Ribic [bs]
|
||||
|
||||
3.15.1
|
||||
3.14.3
|
||||
======
|
||||
* Use GResources for theme loading [Cosimo; #736936]
|
||||
* Fix headerbar drag getting stuck on xwayland [Carlos; #738411]
|
||||
* Fix wayland hiDPI regressions [Adel; #739161]
|
||||
* Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888,
|
||||
#738890]
|
||||
* Fix crash when trying to unredirect a destroyed window [Florian; #740133]
|
||||
* Fix "flicker" during startup transition [Ray; #740377]
|
||||
* Don't leave left-over frames queued [Owen; #738686]
|
||||
* Set CRTC configuration even if it might be redundant [Rui; #740838]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode, Owen W. Taylor
|
||||
|
||||
3.14.2
|
||||
======
|
||||
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
|
||||
* Misc. fixes [Rui, Jonathon, Jasper; #738630]
|
||||
|
||||
Contributors:
|
||||
Jonathon Jongsma, Rui Matos, Jasper St. Pierre
|
||||
|
||||
3.14.1.5
|
||||
========
|
||||
* Fix wayland hiDPI regressions [Adel; #739161]
|
||||
|
||||
Contributors:
|
||||
Adel Gadllah, Florian Müllner, Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Dušan Kazik [sk]
|
||||
|
||||
3.14.1
|
||||
======
|
||||
|
@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [15])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
m4_define([mutter_minor_version], [14])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -72,7 +72,7 @@ CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gio-unix-2.0 >= 2.25.10
|
||||
gio-unix-2.0 >= 2.35.1
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
@ -200,7 +200,7 @@ AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput gudev-1.0 gbm >= 10.3], [have_native_backend=yes], [have_native_backend=no])
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput gbm >= 10.3], [have_native_backend=yes], [have_native_backend=no])
|
||||
if test $have_native_backend = yes; then
|
||||
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
|
||||
fi
|
||||
|
@ -111,15 +111,6 @@ IGNORE_HFILES= \
|
||||
xprops.h \
|
||||
$(NULL)
|
||||
|
||||
if !HAVE_NATIVE_BACKEND
|
||||
IGNORE_HFILES+= \
|
||||
meta-backend-native.h \
|
||||
meta-cursor-renderer-native.h \
|
||||
meta-idle-monitor-native.h \
|
||||
meta-monitor-manager-kms.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if !HAVE_WAYLAND
|
||||
IGNORE_HFILES += \
|
||||
meta-surface-actor-wayland.h \
|
||||
|
@ -259,6 +259,8 @@ Overview of Theme Format Version 1
|
||||
<!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
|
||||
<color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
|
||||
</gradient>
|
||||
<!-- image has an optional colorize="#color" attribute to give the
|
||||
image a certain color -->
|
||||
<image filename="foo.png" alpha="0.7"
|
||||
x="10" y="30" width="width / 3" height="height / 4"/>
|
||||
<gtk_arrow state="normal" shadow="in" arrow="up"
|
||||
|
273
po/nb.po
273
po/nb.po
@ -4,10 +4,10 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter 3.15.x\n"
|
||||
"Project-Id-Version: mutter 3.13.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-11-15 18:32+0100\n"
|
||||
"PO-Revision-Date: 2014-11-15 18:34+0100\n"
|
||||
"POT-Creation-Date: 2014-09-06 14:13+0200\n"
|
||||
"PO-Revision-Date: 2014-08-23 13:37+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
|
||||
"Language: \n"
|
||||
@ -351,7 +351,7 @@ msgid ""
|
||||
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
|
||||
"the focus will not be changed immediately when entering a window, but only "
|
||||
"after the pointer stops moving."
|
||||
msgstr "Hvis denne settes til «true» og fokusmodus er enten «sloppy» eller «mouse» så vil fokus ikke endres med en gang markøren kommer inn i et vindu, men i stedet når markørens bevegelse stopper."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
|
||||
msgid "Draggable border width"
|
||||
@ -385,7 +385,7 @@ msgstr "Plasser nye vinduer i senter"
|
||||
msgid ""
|
||||
"When true, the new windows will always be put in the center of the active "
|
||||
"screen of the monitor."
|
||||
msgstr "Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt område på skjermen."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
|
||||
msgid "Select window from tab popup"
|
||||
@ -423,29 +423,29 @@ msgstr "Bytt til VT 6"
|
||||
msgid "Switch to VT 7"
|
||||
msgstr "Bytt til VT 7"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:350
|
||||
#: ../src/backends/meta-monitor-manager.c:412
|
||||
msgid "Built-in display"
|
||||
msgstr "Innebygget skjerm"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:375
|
||||
#: ../src/backends/meta-monitor-manager.c:437
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjent"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:377
|
||||
#: ../src/backends/meta-monitor-manager.c:439
|
||||
msgid "Unknown Display"
|
||||
msgstr "Ukjent skjerm"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: ../src/backends/meta-monitor-manager.c:385
|
||||
#: ../src/backends/meta-monitor-manager.c:447
|
||||
#, c-format
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. 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:456
|
||||
#: ../src/compositor/compositor.c:443
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
@ -481,7 +481,7 @@ msgstr "_Vent"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Tvungen nedstenging"
|
||||
|
||||
#: ../src/core/display.c:550
|
||||
#: ../src/core/display.c:547
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
|
||||
@ -518,12 +518,12 @@ msgstr "Kjør som en wayland-kompositør"
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Kjør som en full skjermtjener, heller enn nøstet"
|
||||
|
||||
#: ../src/core/main.c:451
|
||||
#: ../src/core/main.c:459
|
||||
#, c-format
|
||||
msgid "Failed to scan themes directory: %s\n"
|
||||
msgstr "Feil under søk i temakatalog: %s\n"
|
||||
|
||||
#: ../src/core/main.c:467
|
||||
#: ../src/core/main.c:475
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
|
||||
@ -553,17 +553,17 @@ msgstr "Skriv versjonsnummer"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Mutter-tillegg som skal brukes"
|
||||
|
||||
#: ../src/core/prefs.c:2064
|
||||
#: ../src/core/prefs.c:2101
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Arbeidsområde %d"
|
||||
|
||||
#: ../src/core/screen.c:543
|
||||
#: ../src/core/screen.c:548
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Skjerm %d på display «%s» er ugyldig\n"
|
||||
|
||||
#: ../src/core/screen.c:559
|
||||
#: ../src/core/screen.c:564
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||
@ -572,7 +572,7 @@ msgstr ""
|
||||
"Skjerm %d på display «%s» har allerede en vindushåndterer; prøv å bruke "
|
||||
"flagget --replace for å erstatte aktiv vindushåndterer.\n"
|
||||
|
||||
#: ../src/core/screen.c:652
|
||||
#: ../src/core/screen.c:657
|
||||
#, c-format
|
||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||
msgstr "Skjerm %d på display «%s» har allerede en vinduhåndterer\n"
|
||||
@ -589,48 +589,48 @@ msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
|
||||
msgid "%d x %d"
|
||||
msgstr "%d x %d"
|
||||
|
||||
#: ../src/ui/theme.c:154
|
||||
#: ../src/ui/theme.c:233
|
||||
msgid "top"
|
||||
msgstr "topp"
|
||||
|
||||
#: ../src/ui/theme.c:156
|
||||
#: ../src/ui/theme.c:235
|
||||
msgid "bottom"
|
||||
msgstr "bunn"
|
||||
|
||||
#: ../src/ui/theme.c:158
|
||||
#: ../src/ui/theme.c:237
|
||||
msgid "left"
|
||||
msgstr "venstre"
|
||||
|
||||
#: ../src/ui/theme.c:160
|
||||
#: ../src/ui/theme.c:239
|
||||
msgid "right"
|
||||
msgstr "høyre"
|
||||
|
||||
#: ../src/ui/theme.c:188
|
||||
#: ../src/ui/theme.c:267
|
||||
#, c-format
|
||||
msgid "frame geometry does not specify \"%s\" dimension"
|
||||
msgstr "rammegeometrien spesifiserer ikke «%s»-dimensjon"
|
||||
|
||||
#: ../src/ui/theme.c:207
|
||||
#: ../src/ui/theme.c:286
|
||||
#, c-format
|
||||
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
|
||||
msgstr "rammegeometri spesifiserer ikke dimensjon «%s» for kant «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:244
|
||||
#: ../src/ui/theme.c:323
|
||||
#, c-format
|
||||
msgid "Button aspect ratio %g is not reasonable"
|
||||
msgstr "Aspektrate %g for knapp er ikke fornuftig"
|
||||
|
||||
#: ../src/ui/theme.c:256
|
||||
#: ../src/ui/theme.c:335
|
||||
#, c-format
|
||||
msgid "Frame geometry does not specify size of buttons"
|
||||
msgstr "Rammegeometrien spesifiserer ikke størrelse på knapper"
|
||||
|
||||
#: ../src/ui/theme.c:1024
|
||||
#: ../src/ui/theme.c:1061
|
||||
#, c-format
|
||||
msgid "Gradients should have at least two colors"
|
||||
msgstr "Gradienter må ha minst to farger"
|
||||
|
||||
#: ../src/ui/theme.c:1174
|
||||
#: ../src/ui/theme.c:1211
|
||||
#, c-format
|
||||
msgid ""
|
||||
"GTK custom color specification must have color name and fallback in "
|
||||
@ -639,7 +639,7 @@ msgstr ""
|
||||
"Egendefinert GTK-fargespesifikasjon må ha fargenavn og reserve i parantes, f."
|
||||
"eks gtk:custom(foo,bar); kunne ikke lese «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1190
|
||||
#: ../src/ui/theme.c:1227
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
|
||||
@ -648,7 +648,7 @@ msgstr ""
|
||||
"Ugyldig tegn «%c» i parameter color_name for gtk:custom, kun A-Za-z0-9-_ er "
|
||||
"gyldig"
|
||||
|
||||
#: ../src/ui/theme.c:1204
|
||||
#: ../src/ui/theme.c:1241
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
|
||||
@ -657,7 +657,7 @@ msgstr ""
|
||||
"Gtk:custom-format er «gtk:custom(color_name,fallback)», «%s» passer ikke i "
|
||||
"formatet"
|
||||
|
||||
#: ../src/ui/theme.c:1249
|
||||
#: ../src/ui/theme.c:1286
|
||||
#, c-format
|
||||
msgid ""
|
||||
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
|
||||
@ -666,7 +666,7 @@ msgstr ""
|
||||
"GTK-fargespesifikasjon må ha tilstand i klammer, f.eks. gtk:fg[NORMAL], hvor "
|
||||
"NORMAL er tilstanden; kunne ikke lese «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1263
|
||||
#: ../src/ui/theme.c:1300
|
||||
#, c-format
|
||||
msgid ""
|
||||
"GTK color specification must have a close bracket after the state, e.g. gtk:"
|
||||
@ -675,17 +675,17 @@ msgstr ""
|
||||
"GTK-fargespesifikasjon må ha en avsluttende klamme etter tilstanden, f.eks. "
|
||||
"gtk:fg[NORMAL], hvor NORMAL er tilstanden; kunne ikke lese «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1274
|
||||
#: ../src/ui/theme.c:1311
|
||||
#, c-format
|
||||
msgid "Did not understand state \"%s\" in color specification"
|
||||
msgstr "Forsto ikke tilstand «%s» i fargespesifikasjonen"
|
||||
|
||||
#: ../src/ui/theme.c:1287
|
||||
#: ../src/ui/theme.c:1324
|
||||
#, c-format
|
||||
msgid "Did not understand color component \"%s\" in color specification"
|
||||
msgstr "Forsto ikke fargekomponent «%s» i fargespesifikasjonen"
|
||||
|
||||
#: ../src/ui/theme.c:1315
|
||||
#: ../src/ui/theme.c:1352
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
|
||||
@ -694,56 +694,56 @@ msgstr ""
|
||||
"Blandingsformat er «blend/bg_color/fg_color/alpha», «%s» passer ikke i "
|
||||
"formatet"
|
||||
|
||||
#: ../src/ui/theme.c:1326
|
||||
#: ../src/ui/theme.c:1363
|
||||
#, c-format
|
||||
msgid "Could not parse alpha value \"%s\" in blended color"
|
||||
msgstr "Kunne ikke lese alpha-verdi «%s» i blandet farge"
|
||||
|
||||
#: ../src/ui/theme.c:1336
|
||||
#: ../src/ui/theme.c:1373
|
||||
#, c-format
|
||||
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
|
||||
msgstr "Alpha-verdi «%s» i blandet farge er ikke mellom 0.0 og 1.0"
|
||||
|
||||
#: ../src/ui/theme.c:1382
|
||||
#: ../src/ui/theme.c:1419
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
|
||||
msgstr ""
|
||||
"Skyggeformatet er «shade/base_color/factor», «%s» passer ikke i formatet"
|
||||
|
||||
#: ../src/ui/theme.c:1393
|
||||
#: ../src/ui/theme.c:1430
|
||||
#, c-format
|
||||
msgid "Could not parse shade factor \"%s\" in shaded color"
|
||||
msgstr "Kunne ikke lese skyggefaktor «%s» i skyggelagt farge"
|
||||
|
||||
#: ../src/ui/theme.c:1403
|
||||
#: ../src/ui/theme.c:1440
|
||||
#, c-format
|
||||
msgid "Shade factor \"%s\" in shaded color is negative"
|
||||
msgstr "Skyggefaktor «%s» i skyggelagt farge er negativ"
|
||||
|
||||
#: ../src/ui/theme.c:1432
|
||||
#: ../src/ui/theme.c:1469
|
||||
#, c-format
|
||||
msgid "Could not parse color \"%s\""
|
||||
msgstr "Kunne ikke lese farge «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1741
|
||||
#: ../src/ui/theme.c:1778
|
||||
#, c-format
|
||||
msgid "Coordinate expression contains character '%s' which is not allowed"
|
||||
msgstr "Koordinatuttrykk inneholder tegn «%s» som ikke er tillatt"
|
||||
|
||||
#: ../src/ui/theme.c:1768
|
||||
#: ../src/ui/theme.c:1805
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Coordinate expression contains floating point number '%s' which could not be "
|
||||
"parsed"
|
||||
msgstr "Koordinatuttrykk inneholder flyttall «%s» som ikke kunne tolkes"
|
||||
|
||||
#: ../src/ui/theme.c:1782
|
||||
#: ../src/ui/theme.c:1819
|
||||
#, c-format
|
||||
msgid "Coordinate expression contains integer '%s' which could not be parsed"
|
||||
msgstr "Koordinatuttrykk inneholder heltall «%s» som ikke kunne tolkes"
|
||||
|
||||
#: ../src/ui/theme.c:1903
|
||||
#: ../src/ui/theme.c:1940
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Coordinate expression contained unknown operator at the start of this text: "
|
||||
@ -752,39 +752,39 @@ msgstr ""
|
||||
"Koordinatuttrykket inneholdt en ukjent operator ved begynnelsen av denne "
|
||||
"teksten: «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1960
|
||||
#: ../src/ui/theme.c:1997
|
||||
#, c-format
|
||||
msgid "Coordinate expression was empty or not understood"
|
||||
msgstr "Koordinatuttrykket var tomt eller ble ikke forstått"
|
||||
|
||||
#: ../src/ui/theme.c:2073 ../src/ui/theme.c:2083 ../src/ui/theme.c:2117
|
||||
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
|
||||
#, c-format
|
||||
msgid "Coordinate expression results in division by zero"
|
||||
msgstr "Koordinatuttrykket resulterer i divisjon med null"
|
||||
|
||||
#: ../src/ui/theme.c:2125
|
||||
#: ../src/ui/theme.c:2162
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Coordinate expression tries to use mod operator on a floating-point number"
|
||||
msgstr "Koordinatuttrykket prøver å bruke mod-operator på et flyttall"
|
||||
|
||||
#: ../src/ui/theme.c:2181
|
||||
#: ../src/ui/theme.c:2218
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Coordinate expression has an operator \"%s\" where an operand was expected"
|
||||
msgstr "Koordinatuttrykket har en operator «%s» hvor en operand var ventet"
|
||||
|
||||
#: ../src/ui/theme.c:2190
|
||||
#: ../src/ui/theme.c:2227
|
||||
#, c-format
|
||||
msgid "Coordinate expression had an operand where an operator was expected"
|
||||
msgstr "Koordinatuttrykket hadde en operand hvor en operator var ventet"
|
||||
|
||||
#: ../src/ui/theme.c:2198
|
||||
#: ../src/ui/theme.c:2235
|
||||
#, c-format
|
||||
msgid "Coordinate expression ended with an operator instead of an operand"
|
||||
msgstr "Koordinatuttrykket sluttet med en operator i stedet for en operand"
|
||||
|
||||
#: ../src/ui/theme.c:2208
|
||||
#: ../src/ui/theme.c:2245
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
|
||||
@ -793,38 +793,38 @@ msgstr ""
|
||||
"Koordinatuttrykket har en operator «%c» etter en operator «%c» og ingen "
|
||||
"operand mellom dem."
|
||||
|
||||
#: ../src/ui/theme.c:2359 ../src/ui/theme.c:2404
|
||||
#: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441
|
||||
#, c-format
|
||||
msgid "Coordinate expression had unknown variable or constant \"%s\""
|
||||
msgstr "Koordinatuttrykket haddeen ukjent variabel eller konstant «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:2458
|
||||
#: ../src/ui/theme.c:2495
|
||||
#, c-format
|
||||
msgid "Coordinate expression parser overflowed its buffer."
|
||||
msgstr "Tolkeren for koordinatuttrykk oversteg buffergrensen."
|
||||
|
||||
#: ../src/ui/theme.c:2487
|
||||
#: ../src/ui/theme.c:2524
|
||||
#, c-format
|
||||
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
|
||||
msgstr "Koordinatuttrykket hadde en parantes slutt uten parantes start"
|
||||
|
||||
#: ../src/ui/theme.c:2551
|
||||
#: ../src/ui/theme.c:2588
|
||||
#, c-format
|
||||
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
|
||||
msgstr "Koordinatuttrykket hadde en åpen parantes uten en avsluttende parantes"
|
||||
|
||||
#: ../src/ui/theme.c:2562
|
||||
#: ../src/ui/theme.c:2599
|
||||
#, c-format
|
||||
msgid "Coordinate expression doesn't seem to have any operators or operands"
|
||||
msgstr ""
|
||||
"Koordinatuttrykket ser ikke ut til å ha noen operatorer eller operander"
|
||||
|
||||
#: ../src/ui/theme.c:2775 ../src/ui/theme.c:2795 ../src/ui/theme.c:2815
|
||||
#: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
|
||||
#, c-format
|
||||
msgid "Theme contained an expression that resulted in an error: %s\n"
|
||||
msgstr "Tema inneholdt et uttrykk som resulterte i en feil: %s\n"
|
||||
|
||||
#: ../src/ui/theme.c:4055
|
||||
#: ../src/ui/theme.c:4455
|
||||
#, c-format
|
||||
msgid ""
|
||||
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
|
||||
@ -833,25 +833,25 @@ msgstr ""
|
||||
"<button function=«%s» state=«%s» draw_ops=«ett-eller-annet»/> må "
|
||||
"spesifiseres for denne rammestilen"
|
||||
|
||||
#: ../src/ui/theme.c:4570 ../src/ui/theme.c:4595
|
||||
#: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
||||
msgstr ""
|
||||
"Mangler <frame state=«%s» resize=«%s» focus=«%s» stil=«ett-eller-annet»/>"
|
||||
|
||||
#: ../src/ui/theme.c:4641
|
||||
#: ../src/ui/theme.c:5041
|
||||
#, c-format
|
||||
msgid "Failed to load theme \"%s\": %s\n"
|
||||
msgstr "Klarte ikke å laste tema «%s»: %s\n"
|
||||
|
||||
#: ../src/ui/theme.c:4777 ../src/ui/theme.c:4784 ../src/ui/theme.c:4791
|
||||
#: ../src/ui/theme.c:4798 ../src/ui/theme.c:4805
|
||||
#: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191
|
||||
#: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205
|
||||
#, c-format
|
||||
msgid "No <%s> set for theme \"%s\""
|
||||
msgstr "<%s> er ikke satt for tema «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:4813
|
||||
#: ../src/ui/theme.c:5213
|
||||
#, c-format
|
||||
msgid ""
|
||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
||||
@ -860,14 +860,14 @@ msgstr ""
|
||||
"Ingen rammestil satt for vindutype «%s» i tema «%s», legg til et <window "
|
||||
"type=«%s» style_set=«ett-eller-annet»/>-element"
|
||||
|
||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5282 ../src/ui/theme.c:5345
|
||||
#: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
|
||||
#, c-format
|
||||
msgid ""
|
||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
||||
msgstr ""
|
||||
"Brukerdefinerte konstanter må begynne med stor bokstav; «%s» gjør ikke det"
|
||||
|
||||
#: ../src/ui/theme.c:5228 ../src/ui/theme.c:5290 ../src/ui/theme.c:5353
|
||||
#: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
|
||||
#, c-format
|
||||
msgid "Constant \"%s\" has already been defined"
|
||||
msgstr "Konstant «%s» er allerede definert"
|
||||
@ -930,13 +930,13 @@ msgstr "Bolske verdier må være «sann» eller «usann» ikke «%s»"
|
||||
msgid "Angle must be between 0.0 and 360.0, was %g\n"
|
||||
msgstr "Vinkelen må være mellom 0.0 og 360.0, var %g\n"
|
||||
|
||||
#: ../src/ui/theme-parser.c:797
|
||||
#: ../src/ui/theme-parser.c:800
|
||||
#, c-format
|
||||
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
|
||||
msgstr ""
|
||||
"Alpha må være mellom 0.0 (usynlig) og 1.0 (helt ugjennomsiktig), var %g\n"
|
||||
|
||||
#: ../src/ui/theme-parser.c:862
|
||||
#: ../src/ui/theme-parser.c:865
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
|
||||
@ -945,58 +945,58 @@ msgstr ""
|
||||
"Ugyldig skalering av tittel «%s» (må være en av xx-small,x-small,small,"
|
||||
"medium,large,x-large,xx-large)\n"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1018 ../src/ui/theme-parser.c:1081
|
||||
#: ../src/ui/theme-parser.c:1115 ../src/ui/theme-parser.c:1218
|
||||
#: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084
|
||||
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
|
||||
#, c-format
|
||||
msgid "<%s> name \"%s\" used a second time"
|
||||
msgstr "<%s> navn «%s» brukt på nytt"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1030 ../src/ui/theme-parser.c:1127
|
||||
#: ../src/ui/theme-parser.c:1230
|
||||
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
|
||||
#: ../src/ui/theme-parser.c:1233
|
||||
#, c-format
|
||||
msgid "<%s> parent \"%s\" has not been defined"
|
||||
msgstr "<%s> opphav «%s» er ikke definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1140
|
||||
#: ../src/ui/theme-parser.c:1143
|
||||
#, c-format
|
||||
msgid "<%s> geometry \"%s\" has not been defined"
|
||||
msgstr "<%s> geometri «%s» er ikke definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1153
|
||||
#: ../src/ui/theme-parser.c:1156
|
||||
#, c-format
|
||||
msgid "<%s> must specify either a geometry or a parent that has a geometry"
|
||||
msgstr "<%s> må spesifisere enten en geometri eller et opphav som har geometri"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1195
|
||||
#: ../src/ui/theme-parser.c:1198
|
||||
msgid "You must specify a background for an alpha value to be meaningful"
|
||||
msgstr "Du må oppgi en bakgrunn for at en alpha-verdi skal ha mening"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1263
|
||||
#: ../src/ui/theme-parser.c:1266
|
||||
#, c-format
|
||||
msgid "Unknown type \"%s\" on <%s> element"
|
||||
msgstr "Ukjent type «%s» på <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1274
|
||||
#: ../src/ui/theme-parser.c:1277
|
||||
#, c-format
|
||||
msgid "Unknown style_set \"%s\" on <%s> element"
|
||||
msgstr "Ukjent style_set «%s» på <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1282
|
||||
#: ../src/ui/theme-parser.c:1285
|
||||
#, c-format
|
||||
msgid "Window type \"%s\" has already been assigned a style set"
|
||||
msgstr "Vindutype «%s» er allerede tildelt et stilsett"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1312 ../src/ui/theme-parser.c:1376
|
||||
#: ../src/ui/theme-parser.c:1602 ../src/ui/theme-parser.c:2821
|
||||
#: ../src/ui/theme-parser.c:2867 ../src/ui/theme-parser.c:3017
|
||||
#: ../src/ui/theme-parser.c:3253 ../src/ui/theme-parser.c:3291
|
||||
#: ../src/ui/theme-parser.c:3329 ../src/ui/theme-parser.c:3367
|
||||
#: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379
|
||||
#: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840
|
||||
#: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036
|
||||
#: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310
|
||||
#: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386
|
||||
#, c-format
|
||||
msgid "Element <%s> is not allowed below <%s>"
|
||||
msgstr "Element <%s> er ikke tillatt under <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1426 ../src/ui/theme-parser.c:1440
|
||||
#: ../src/ui/theme-parser.c:1485
|
||||
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
|
||||
#: ../src/ui/theme-parser.c:1488
|
||||
msgid ""
|
||||
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
|
||||
"for buttons"
|
||||
@ -1004,123 +1004,123 @@ msgstr ""
|
||||
"Kan ikke spesifisere både «button_width»/«button_height» og «aspect_ratio» "
|
||||
"for knapper"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1449
|
||||
#: ../src/ui/theme-parser.c:1452
|
||||
#, c-format
|
||||
msgid "Distance \"%s\" is unknown"
|
||||
msgstr "Avstand «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1494
|
||||
#: ../src/ui/theme-parser.c:1497
|
||||
#, c-format
|
||||
msgid "Aspect ratio \"%s\" is unknown"
|
||||
msgstr "Aspektrate «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1556
|
||||
#: ../src/ui/theme-parser.c:1559
|
||||
#, c-format
|
||||
msgid "Border \"%s\" is unknown"
|
||||
msgstr "Grense «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1867
|
||||
#: ../src/ui/theme-parser.c:1870
|
||||
#, c-format
|
||||
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
|
||||
msgstr "Ingen «start_angle» eller «from»-attributt på element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1874
|
||||
#: ../src/ui/theme-parser.c:1877
|
||||
#, c-format
|
||||
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
|
||||
msgstr "Ingen «extent_angle» eller «to»-attributt <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2114
|
||||
#: ../src/ui/theme-parser.c:2117
|
||||
#, c-format
|
||||
msgid "Did not understand value \"%s\" for type of gradient"
|
||||
msgstr "Forsto ikke verdi «%s» for gradienttype"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2189 ../src/ui/theme-parser.c:2551
|
||||
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
|
||||
#, c-format
|
||||
msgid "Did not understand fill type \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke fyll-type «%s» for <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2343 ../src/ui/theme-parser.c:2426
|
||||
#: ../src/ui/theme-parser.c:2489
|
||||
#: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445
|
||||
#: ../src/ui/theme-parser.c:2508
|
||||
#, c-format
|
||||
msgid "Did not understand state \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke tilstand «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2353 ../src/ui/theme-parser.c:2436
|
||||
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
|
||||
#, c-format
|
||||
msgid "Did not understand shadow \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke skygge «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2363
|
||||
#: ../src/ui/theme-parser.c:2382
|
||||
#, c-format
|
||||
msgid "Did not understand arrow \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke pil «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2677 ../src/ui/theme-parser.c:2773
|
||||
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
|
||||
#, c-format
|
||||
msgid "No <draw_ops> called \"%s\" has been defined"
|
||||
msgstr "Ingen <draw_ops> kalt «%s» er definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2689 ../src/ui/theme-parser.c:2785
|
||||
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
|
||||
#, c-format
|
||||
msgid "Including draw_ops \"%s\" here would create a circular reference"
|
||||
msgstr "Hvis du tar med draw_ops «%s» her vil dette lage en sirkulær referanse"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2900
|
||||
#: ../src/ui/theme-parser.c:2919
|
||||
#, c-format
|
||||
msgid "Unknown position \"%s\" for frame piece"
|
||||
msgstr "Ukjent posisjon «%s» for rammesdel"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2908
|
||||
#: ../src/ui/theme-parser.c:2927
|
||||
#, c-format
|
||||
msgid "Frame style already has a piece at position %s"
|
||||
msgstr "Rammestil har allerede en del i posisjon %s"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2925 ../src/ui/theme-parser.c:3002
|
||||
#: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021
|
||||
#, c-format
|
||||
msgid "No <draw_ops> with the name \"%s\" has been defined"
|
||||
msgstr "Ingen <draw_ops> med navn «%s» er definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2955
|
||||
#: ../src/ui/theme-parser.c:2974
|
||||
#, c-format
|
||||
msgid "Unknown function \"%s\" for button"
|
||||
msgstr "Ukjent funksjon «%s» for knapp"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2965
|
||||
#: ../src/ui/theme-parser.c:2984
|
||||
#, c-format
|
||||
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
|
||||
msgstr "Knappefunksjon «%s» eksisterer ikke i denne versjonen (%d, trenger %d)"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2977
|
||||
#: ../src/ui/theme-parser.c:2996
|
||||
#, c-format
|
||||
msgid "Unknown state \"%s\" for button"
|
||||
msgstr "Ukjent tilstand «%s» for knapp"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2985
|
||||
#: ../src/ui/theme-parser.c:3004
|
||||
#, c-format
|
||||
msgid "Frame style already has a button for function %s state %s"
|
||||
msgstr "Rammestil har allerede en knapp for funksjon %s tilstand %s"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3056
|
||||
#: ../src/ui/theme-parser.c:3075
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid value for focus attribute"
|
||||
msgstr "«%s» er ikke en gyldig verdi for fokusattributt"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3065
|
||||
#: ../src/ui/theme-parser.c:3084
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid value for state attribute"
|
||||
msgstr "«%s» er ikke en gyldig verdi for tilstandsattributt"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3075
|
||||
#: ../src/ui/theme-parser.c:3094
|
||||
#, c-format
|
||||
msgid "A style called \"%s\" has not been defined"
|
||||
msgstr "En stil med navn «%s» er ikke definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3096 ../src/ui/theme-parser.c:3119
|
||||
#: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid value for resize attribute"
|
||||
msgstr "«%s» er ikke en gyldig verdi for attributt for endring av størrelse"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3130
|
||||
#: ../src/ui/theme-parser.c:3149
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
|
||||
@ -1129,27 +1129,27 @@ msgstr ""
|
||||
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert/"
|
||||
"skyggelagt tilstand"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3144
|
||||
#: ../src/ui/theme-parser.c:3163
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Should not have \"resize\" attribute on <%s> element for maximized states"
|
||||
msgstr ""
|
||||
"Skal ikke være noen «resize»-attributt på <%s>-element for maksimert tilstand"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3158 ../src/ui/theme-parser.c:3202
|
||||
#: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221
|
||||
#, c-format
|
||||
msgid "Style has already been specified for state %s resize %s focus %s"
|
||||
msgstr ""
|
||||
"Stil er allerede spesifisert for tilstand %s størrelsesendring %s fokus %s"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3169 ../src/ui/theme-parser.c:3180
|
||||
#: ../src/ui/theme-parser.c:3191 ../src/ui/theme-parser.c:3213
|
||||
#: ../src/ui/theme-parser.c:3224 ../src/ui/theme-parser.c:3235
|
||||
#: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199
|
||||
#: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232
|
||||
#: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254
|
||||
#, c-format
|
||||
msgid "Style has already been specified for state %s focus %s"
|
||||
msgstr "Stil er allerede spesifisert for tilstand %s fokus %s"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3274
|
||||
#: ../src/ui/theme-parser.c:3293
|
||||
msgid ""
|
||||
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
|
||||
"attribute and also a <draw_ops> element, or specified two elements)"
|
||||
@ -1158,7 +1158,7 @@ msgstr ""
|
||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller så "
|
||||
"spesifiserte det to elementer)"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3312
|
||||
#: ../src/ui/theme-parser.c:3331
|
||||
msgid ""
|
||||
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
|
||||
"attribute and also a <draw_ops> element, or specified two elements)"
|
||||
@ -1167,7 +1167,7 @@ msgstr ""
|
||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
|
||||
"spesifiserte to elementer)"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3350
|
||||
#: ../src/ui/theme-parser.c:3369
|
||||
msgid ""
|
||||
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
|
||||
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
|
||||
@ -1176,12 +1176,12 @@ msgstr ""
|
||||
"draw_ops-attributt i tillegg til et <draw_ops>-element, eller det "
|
||||
"spesifiserte to elementer)"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3414
|
||||
#: ../src/ui/theme-parser.c:3433
|
||||
#, c-format
|
||||
msgid "Bad version specification '%s'"
|
||||
msgstr "Ugyldig versjonspesifikasjon «%s»"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3487
|
||||
#: ../src/ui/theme-parser.c:3506
|
||||
msgid ""
|
||||
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
|
||||
"theme-2.xml"
|
||||
@ -1189,66 +1189,66 @@ msgstr ""
|
||||
"«version»-attributt kan ikke brukes i metacity-theme-1.xml eller metacity-"
|
||||
"theme-2.xml"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3510
|
||||
#: ../src/ui/theme-parser.c:3529
|
||||
#, c-format
|
||||
msgid "Theme requires version %s but latest supported theme version is %d.%d"
|
||||
msgstr "Tema krever versjon %s men siste støttede temaversjon er %d.%d"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3542
|
||||
#: ../src/ui/theme-parser.c:3561
|
||||
#, c-format
|
||||
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
|
||||
msgstr "Ytterste element i temaet må være <metacity_theme> ikke <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3562
|
||||
#: ../src/ui/theme-parser.c:3581
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Element <%s> is not allowed inside a name/author/date/description element"
|
||||
msgstr ""
|
||||
"Element <%s> er ikke tillatt inne i et name/author/date/description element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3567
|
||||
#: ../src/ui/theme-parser.c:3586
|
||||
#, c-format
|
||||
msgid "Element <%s> is not allowed inside a <constant> element"
|
||||
msgstr "Element <%s> er ikke tillatt inne i et <constand> element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3579
|
||||
#: ../src/ui/theme-parser.c:3598
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
|
||||
msgstr "Element <%s> er ikke tillatt inne i et avstand/kant/aspektrate-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3601
|
||||
#: ../src/ui/theme-parser.c:3620
|
||||
#, c-format
|
||||
msgid "Element <%s> is not allowed inside a draw operation element"
|
||||
msgstr "Element <%s> er ikke tillatt inne i et element for tegneoperasjon"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3611 ../src/ui/theme-parser.c:3641
|
||||
#: ../src/ui/theme-parser.c:3646 ../src/ui/theme-parser.c:3651
|
||||
#: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660
|
||||
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
|
||||
#, c-format
|
||||
msgid "Element <%s> is not allowed inside a <%s> element"
|
||||
msgstr "Element <%s> er ikke tillatt inne i et <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3879
|
||||
#: ../src/ui/theme-parser.c:3898
|
||||
msgid "No draw_ops provided for frame piece"
|
||||
msgstr "Ingen draw_ops tilbys for rammedelen"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3894
|
||||
#: ../src/ui/theme-parser.c:3913
|
||||
msgid "No draw_ops provided for button"
|
||||
msgstr "Ingen draw_ops tilbys for knappen"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3948
|
||||
#: ../src/ui/theme-parser.c:3967
|
||||
#, c-format
|
||||
msgid "No text is allowed inside element <%s>"
|
||||
msgstr "Ingen tekst er tillatt inne i element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:4006 ../src/ui/theme-parser.c:4018
|
||||
#: ../src/ui/theme-parser.c:4030 ../src/ui/theme-parser.c:4042
|
||||
#: ../src/ui/theme-parser.c:4054
|
||||
#: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037
|
||||
#: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061
|
||||
#: ../src/ui/theme-parser.c:4073
|
||||
#, c-format
|
||||
msgid "<%s> specified twice for this theme"
|
||||
msgstr "<%s> spesifisert to ganger for dette temaet"
|
||||
|
||||
#: ../src/ui/theme-parser.c:4316
|
||||
#: ../src/ui/theme-parser.c:4335
|
||||
#, c-format
|
||||
msgid "Failed to find a valid file for theme %s\n"
|
||||
msgstr "Fant ikke en gyldig fil for tema %s\n"
|
||||
@ -1261,7 +1261,10 @@ msgstr ""
|
||||
"Disse vinduene støtter ikke "lagre aktiv konfigurasjon"og vil "
|
||||
"måtte startes på nytt manuelt neste gang du logger inn."
|
||||
|
||||
#: ../src/x11/window-props.c:558
|
||||
#: ../src/x11/window-props.c:515
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (på %s)"
|
||||
|
||||
#~ msgid "background texture could not be created from file"
|
||||
#~ msgstr "bakgrunnstekstur kunne ikke lages fra fil"
|
||||
|
@ -41,9 +41,11 @@ endif
|
||||
# Some random test programs for bits of the code
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS+=testboxes testasyncgetprop
|
||||
noinst_PROGRAMS+=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
@ -6,7 +6,6 @@ lib_LTLIBRARIES = libmutter.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
EXTRA_DIST =
|
||||
NULL =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
@ -32,30 +31,26 @@ AM_CPPFLAGS = \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" \
|
||||
$(NULL)
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_display_config_built_sources) \
|
||||
$(dbus_login1_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
$(NULL)
|
||||
mutter-enum-types.c
|
||||
|
||||
if HAVE_WAYLAND
|
||||
mutter_built_sources += \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h \
|
||||
$(NULL)
|
||||
xdg-shell-server-protocol.h
|
||||
endif
|
||||
|
||||
wayland_protocols = \
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
wayland/protocol/xdg-shell.xml \
|
||||
$(NULL)
|
||||
wayland/protocol/xdg-shell.xml
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
backends/meta-backend.c \
|
||||
@ -167,6 +162,8 @@ libmutter_la_SOURCES = \
|
||||
meta/errors.h \
|
||||
core/frame.c \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/meta-gesture-tracker.c \
|
||||
core/meta-gesture-tracker-private.h \
|
||||
core/keybindings.c \
|
||||
@ -225,8 +222,7 @@ libmutter_la_SOURCES = \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
x11/mutter-Xatomtype.h \
|
||||
$(NULL)
|
||||
x11/mutter-Xatomtype.h
|
||||
|
||||
if HAVE_WAYLAND
|
||||
libmutter_la_SOURCES += \
|
||||
@ -259,8 +255,7 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h \
|
||||
$(NULL)
|
||||
wayland/window-wayland.h
|
||||
endif
|
||||
|
||||
if HAVE_NATIVE_BACKEND
|
||||
@ -276,11 +271,11 @@ libmutter_la_SOURCES += \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/native/dbus-utils.c \
|
||||
backends/native/dbus-utils.h \
|
||||
$(NULL)
|
||||
backends/native/dbus-utils.h
|
||||
endif
|
||||
|
||||
nodist_libmutter_la_SOURCES = $(mutter_built_sources)
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
|
||||
@ -295,6 +290,7 @@ libmutterinclude_headers = \
|
||||
meta/compositor.h \
|
||||
meta/display.h \
|
||||
meta/errors.h \
|
||||
meta/gradient.h \
|
||||
meta/group.h \
|
||||
meta/keybindings.h \
|
||||
meta/main.h \
|
||||
@ -315,8 +311,7 @@ libmutterinclude_headers = \
|
||||
meta/types.h \
|
||||
meta/util.h \
|
||||
meta/window.h \
|
||||
meta/workspace.h \
|
||||
$(NULL)
|
||||
meta/workspace.h
|
||||
|
||||
libmutterinclude_built_headers = \
|
||||
meta/meta-version.h
|
||||
@ -397,15 +392,14 @@ DISTCLEANFILES = \
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libmutter.pc
|
||||
|
||||
EXTRA_DIST += \
|
||||
$(wayland_protocols) \
|
||||
libmutter.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
org.freedesktop.login1.xml \
|
||||
EXTRA_DIST += \
|
||||
$(wayland_protocols) \
|
||||
libmutter.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
org.freedesktop.login1.xml \
|
||||
org.gnome.Mutter.DisplayConfig.xml \
|
||||
org.gnome.Mutter.IdleMonitor.xml \
|
||||
$(NULL)
|
||||
org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
BUILT_SOURCES = \
|
||||
$(mutter_built_sources) \
|
||||
|
@ -27,9 +27,7 @@
|
||||
* pointer abstraction"
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/util.h>
|
||||
@ -40,10 +38,11 @@
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "boxes-private.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -68,7 +67,6 @@ typedef struct {
|
||||
} MetaOutputConfig;
|
||||
|
||||
typedef struct {
|
||||
guint refcount;
|
||||
MetaOutputKey *keys;
|
||||
MetaOutputConfig *outputs;
|
||||
unsigned int n_outputs;
|
||||
@ -79,6 +77,7 @@ struct _MetaMonitorConfig {
|
||||
|
||||
GHashTable *configs;
|
||||
MetaConfiguration *current;
|
||||
gboolean current_is_stored;
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
@ -125,29 +124,11 @@ config_clear (MetaConfiguration *config)
|
||||
g_free (config->outputs);
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
config_ref (MetaConfiguration *config)
|
||||
{
|
||||
config->refcount++;
|
||||
return config;
|
||||
}
|
||||
|
||||
static void
|
||||
config_unref (MetaConfiguration *config)
|
||||
config_free (gpointer config)
|
||||
{
|
||||
if (--config->refcount == 0)
|
||||
{
|
||||
config_clear (config);
|
||||
g_slice_free (MetaConfiguration, config);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
config_new (void)
|
||||
{
|
||||
MetaConfiguration *config = g_slice_new0 (MetaConfiguration);
|
||||
config->refcount = 1;
|
||||
return config;
|
||||
config_clear (config);
|
||||
g_slice_free (MetaConfiguration, config);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
@ -239,7 +220,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
||||
const char *filename;
|
||||
char *path;
|
||||
|
||||
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
|
||||
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free);
|
||||
|
||||
filename = g_getenv ("MUTTER_MONITOR_FILENAME");
|
||||
if (filename == NULL)
|
||||
@ -849,45 +830,73 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
return stored;
|
||||
}
|
||||
|
||||
static void
|
||||
set_current (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
|
||||
self->previous = self->current;
|
||||
self->current = config_ref (config);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
apply_configuration (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config,
|
||||
MetaMonitorManager *manager)
|
||||
MetaMonitorManager *manager,
|
||||
gboolean stored)
|
||||
{
|
||||
GPtrArray *crtcs, *outputs;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
|
||||
outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
|
||||
|
||||
if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
|
||||
goto out;
|
||||
{
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
if (!stored)
|
||||
config_free (config);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta_monitor_manager_apply_configuration (manager,
|
||||
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
|
||||
(MetaOutputInfo**)outputs->pdata, outputs->len);
|
||||
|
||||
set_current (self, config);
|
||||
/* Stored (persistent) configurations override the previous one always.
|
||||
Also, we clear the previous configuration if the current one (which is
|
||||
about to become previous) is stored, or if the current one has
|
||||
different outputs.
|
||||
*/
|
||||
if (stored ||
|
||||
(self->current && self->current_is_stored))
|
||||
{
|
||||
if (self->previous)
|
||||
config_free (self->previous);
|
||||
self->previous = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Despite the name, config_equal() only checks the set of outputs,
|
||||
not their modes
|
||||
*/
|
||||
if (self->current && config_equal (self->current, config))
|
||||
{
|
||||
self->previous = self->current;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->current)
|
||||
config_free (self->current);
|
||||
self->previous = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
self->current = config;
|
||||
self->current_is_stored = stored;
|
||||
/* If true, we'll be overridden at the end of this call
|
||||
* inside turn_off_laptop_display / apply_configuration_with_lid */
|
||||
inside turn_off_laptop_display()
|
||||
*/
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
ret = TRUE;
|
||||
if (self->current == self->previous)
|
||||
self->previous = NULL;
|
||||
|
||||
out:
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -939,7 +948,7 @@ make_laptop_lid_config (MetaConfiguration *reference)
|
||||
|
||||
g_assert (multiple_outputs_are_enabled (reference));
|
||||
|
||||
new = config_new ();
|
||||
new = g_slice_new0 (MetaConfiguration);
|
||||
new->n_outputs = reference->n_outputs;
|
||||
new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
|
||||
new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
|
||||
@ -994,32 +1003,6 @@ make_laptop_lid_config (MetaConfiguration *reference)
|
||||
return new;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
apply_configuration_with_lid (MetaMonitorConfig *self,
|
||||
MetaConfiguration *config,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
multiple_outputs_are_enabled (config) &&
|
||||
laptop_display_is_on (config))
|
||||
{
|
||||
MetaConfiguration *laptop_lid_config = make_laptop_lid_config (config);
|
||||
if (apply_configuration (self, laptop_lid_config, manager))
|
||||
{
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
config_unref (laptop_lid_config);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
config_unref (laptop_lid_config);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
return apply_configuration (self, config, manager);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
MetaMonitorManager *manager)
|
||||
@ -1032,7 +1015,23 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
stored = meta_monitor_config_get_stored (self, outputs, n_outputs);
|
||||
|
||||
if (stored)
|
||||
return apply_configuration_with_lid (self, stored, manager);
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
multiple_outputs_are_enabled (stored) &&
|
||||
laptop_display_is_on (stored))
|
||||
{
|
||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
||||
manager, FALSE))
|
||||
{
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return apply_configuration (self, stored, manager, TRUE);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@ -1082,123 +1081,47 @@ find_primary_output (MetaOutput *outputs,
|
||||
return best;
|
||||
}
|
||||
|
||||
static void
|
||||
init_config_from_preferred_mode (MetaOutputConfig *config,
|
||||
MetaOutput *output)
|
||||
static MetaConfiguration *
|
||||
make_default_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height)
|
||||
{
|
||||
config->enabled = TRUE;
|
||||
config->rect.x = 0;
|
||||
config->rect.y = 0;
|
||||
config->rect.width = output->preferred_mode->width;
|
||||
config->rect.height = output->preferred_mode->height;
|
||||
config->refresh_rate = output->preferred_mode->refresh_rate;
|
||||
config->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
config->is_primary = FALSE;
|
||||
config->is_presentation = FALSE;
|
||||
}
|
||||
|
||||
/* This function handles configuring the outputs when the driver provides a
|
||||
* suggested layout position for each output. This is done in recent versions
|
||||
* of qxl and allows displays to be aligned on the guest in the same order as
|
||||
* they are aligned on the client.
|
||||
*/
|
||||
static gboolean
|
||||
make_suggested_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
unsigned int i;
|
||||
MetaOutput *primary;
|
||||
GList *region = NULL;
|
||||
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
|
||||
if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
|
||||
return FALSE;
|
||||
|
||||
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
|
||||
config->outputs[i].is_primary = is_primary;
|
||||
|
||||
config->outputs[i].rect.x = outputs[i].suggested_x;
|
||||
config->outputs[i].rect.y = outputs[i].suggested_y;
|
||||
|
||||
/* Reject the configuration if the suggested positions result in
|
||||
* overlapping displays */
|
||||
if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
|
||||
{
|
||||
g_warning ("Overlapping outputs, rejecting suggested configuration");
|
||||
g_list_free (region);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
region = g_list_prepend (region, &config->outputs[i].rect);
|
||||
}
|
||||
|
||||
g_list_free (region);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
make_linear_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
MetaOutput *primary;
|
||||
unsigned i;
|
||||
int x;
|
||||
|
||||
g_return_if_fail (config != NULL);
|
||||
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
x = primary->preferred_mode->width;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
|
||||
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
|
||||
config->outputs[i].is_primary = is_primary;
|
||||
|
||||
if (is_primary)
|
||||
{
|
||||
config->outputs[i].rect.x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
config->outputs[i].rect.x = x;
|
||||
x += config->outputs[i].rect.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for a configuration that includes one less screen, then add the new
|
||||
* one as a presentation screen in preferred mode.
|
||||
*
|
||||
* XXX: but presentation mode is not implemented in the control-center or in
|
||||
* mutter core, so let's do extended for now.
|
||||
*/
|
||||
static gboolean
|
||||
extend_stored_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height,
|
||||
MetaConfiguration *config)
|
||||
{
|
||||
int x, y;
|
||||
unsigned i, j;
|
||||
int x, y;
|
||||
MetaConfiguration *ret;
|
||||
MetaOutput *primary;
|
||||
|
||||
ret = g_slice_new (MetaConfiguration);
|
||||
make_config_key (ret, outputs, n_outputs, -1);
|
||||
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
|
||||
/* Special case the simple case: one output, primary at preferred mode,
|
||||
nothing else to do */
|
||||
if (n_outputs == 1)
|
||||
{
|
||||
ret->outputs[0].enabled = TRUE;
|
||||
ret->outputs[0].rect.x = 0;
|
||||
ret->outputs[0].rect.y = 0;
|
||||
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].is_primary = TRUE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If we reach this point, this is either the first time mutter runs
|
||||
on this system ever, or we just hotplugged a new screen.
|
||||
In the latter case, search for a configuration that includes one
|
||||
less screen, then add the new one as a presentation screen
|
||||
in preferred mode.
|
||||
|
||||
XXX: but presentation mode is not implemented in the control-center
|
||||
or in mutter core, so let's do extended for now.
|
||||
*/
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
@ -1216,80 +1139,69 @@ extend_stored_config (MetaMonitorConfig *self,
|
||||
{
|
||||
if (j < i)
|
||||
{
|
||||
g_assert (output_key_equal (&config->keys[j], &ref->keys[j]));
|
||||
config->outputs[j] = ref->outputs[j];
|
||||
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
|
||||
ret->outputs[j] = ref->outputs[j];
|
||||
x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width);
|
||||
y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height);
|
||||
}
|
||||
else if (j > i)
|
||||
{
|
||||
g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1]));
|
||||
config->outputs[j] = ref->outputs[j - 1];
|
||||
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
|
||||
ret->outputs[j] = ref->outputs[j - 1];
|
||||
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
|
||||
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
init_config_from_preferred_mode (&config->outputs[j], &outputs[0]);
|
||||
ret->outputs[j].enabled = TRUE;
|
||||
ret->outputs[j].rect.x = 0;
|
||||
ret->outputs[j].rect.y = 0;
|
||||
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
|
||||
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
|
||||
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].is_primary = FALSE;
|
||||
ret->outputs[j].is_presentation = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Place the new output at the right end of the screen, if it fits,
|
||||
otherwise below it, otherwise disable it (or apply_configuration will fail) */
|
||||
if (x + config->outputs[i].rect.width <= max_width)
|
||||
config->outputs[i].rect.x = x;
|
||||
else if (y + config->outputs[i].rect.height <= max_height)
|
||||
config->outputs[i].rect.y = y;
|
||||
if (x + ret->outputs[i].rect.width <= max_width)
|
||||
ret->outputs[i].rect.x = x;
|
||||
else if (y + ret->outputs[i].rect.height <= max_height)
|
||||
ret->outputs[i].rect.y = y;
|
||||
else
|
||||
config->outputs[i].enabled = FALSE;
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
/* No previous configuration found, try with a really default one, which
|
||||
is one primary that goes first and the rest to the right of it, extended.
|
||||
*/
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
static MetaConfiguration *
|
||||
make_default_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height,
|
||||
gboolean use_stored_config)
|
||||
{
|
||||
MetaConfiguration *ret = NULL;
|
||||
unsigned i;
|
||||
|
||||
ret = config_new ();
|
||||
make_config_key (ret, outputs, n_outputs, -1);
|
||||
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
|
||||
/* Special case the simple case: one output, primary at preferred mode,
|
||||
nothing else to do */
|
||||
if (n_outputs == 1)
|
||||
{
|
||||
init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
|
||||
ret->outputs[0].is_primary = TRUE;
|
||||
goto check_limits;
|
||||
}
|
||||
|
||||
if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
|
||||
goto check_limits;
|
||||
|
||||
if (use_stored_config &&
|
||||
extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
|
||||
goto check_limits;
|
||||
|
||||
make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
|
||||
|
||||
check_limits:
|
||||
/* Disable outputs that would go beyond framebuffer limits */
|
||||
x = primary->preferred_mode->width;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
|
||||
|| (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height))
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
MetaOutput *output = &outputs[i];
|
||||
|
||||
ret->outputs[i].enabled = TRUE;
|
||||
ret->outputs[i].rect.x = (output == primary) ? 0 : x;
|
||||
ret->outputs[i].rect.y = 0;
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = (output == primary);
|
||||
|
||||
/* Disable outputs that would go beyond framebuffer limits */
|
||||
if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
else if (output != primary)
|
||||
x += output->preferred_mode->width;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1301,7 +1213,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs)
|
||||
{
|
||||
MetaConfiguration *config;
|
||||
MetaConfiguration *ret;
|
||||
MetaOutput *primary;
|
||||
unsigned i;
|
||||
|
||||
@ -1312,29 +1224,34 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
|
||||
/* Oh no, we don't! Activate the primary one and disable everything else */
|
||||
|
||||
config = config_new ();
|
||||
make_config_key (config, outputs, n_outputs, -1);
|
||||
config->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
ret = g_slice_new (MetaConfiguration);
|
||||
make_config_key (ret, outputs, n_outputs, -1);
|
||||
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
MetaOutput *output = &outputs[i];
|
||||
|
||||
if (is_primary)
|
||||
if (output == primary)
|
||||
{
|
||||
init_config_from_preferred_mode (&config->outputs[i], &outputs[0]);
|
||||
config->outputs[i].is_primary = TRUE;
|
||||
ret->outputs[i].enabled = TRUE;
|
||||
ret->outputs[i].rect.x = 0;
|
||||
ret->outputs[i].rect.y = 0;
|
||||
ret->outputs[i].rect.width = output->preferred_mode->width;
|
||||
ret->outputs[i].rect.height = output->preferred_mode->height;
|
||||
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
config->outputs[i].enabled = FALSE;
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
apply_configuration (self, config, manager);
|
||||
config_unref (config);
|
||||
apply_configuration (self, ret, manager, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1345,9 +1262,8 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs;
|
||||
MetaConfiguration *default_config;
|
||||
unsigned n_outputs;
|
||||
gboolean ok = FALSE;
|
||||
gboolean ok;
|
||||
int max_width, max_height;
|
||||
gboolean use_stored_config;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
||||
@ -1358,21 +1274,23 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the device has hotplug_mode_update, it's possible that the
|
||||
* current display configuration does not match a stored configuration.
|
||||
* Since extend_existing_config() tries to build a configuration that is
|
||||
* based on a previously-stored configuration, it's quite likely that the
|
||||
* resulting config will fail. Even if it doesn't fail, it may result in
|
||||
* an unexpected configuration, so don't attempt to use a stored config
|
||||
* in this situation. */
|
||||
use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager);
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config);
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||
|
||||
if (default_config != NULL)
|
||||
{
|
||||
ok = apply_configuration_with_lid (self, default_config, manager);
|
||||
config_unref (default_config);
|
||||
if (self->lid_is_closed &&
|
||||
multiple_outputs_are_enabled (default_config) &&
|
||||
laptop_display_is_on (default_config))
|
||||
{
|
||||
ok = apply_configuration (self, make_laptop_lid_config (default_config),
|
||||
manager, FALSE);
|
||||
config_free (default_config);
|
||||
}
|
||||
else
|
||||
ok = apply_configuration (self, default_config, manager, FALSE);
|
||||
}
|
||||
else
|
||||
ok = FALSE;
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
@ -1409,7 +1327,7 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
|
||||
current = config_new ();
|
||||
current = g_slice_new (MetaConfiguration);
|
||||
current->n_outputs = n_outputs;
|
||||
current->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
current->keys = g_new0 (MetaOutputKey, n_outputs);
|
||||
@ -1422,11 +1340,15 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
|
||||
|
||||
if (self->current && config_equal_full (current, self->current))
|
||||
{
|
||||
config_unref (current);
|
||||
config_free (current);
|
||||
return;
|
||||
}
|
||||
|
||||
set_current (self, current);
|
||||
if (self->current && !self->current_is_stored)
|
||||
config_free (self->current);
|
||||
|
||||
self->current = current;
|
||||
self->current_is_stored = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1434,17 +1356,7 @@ meta_monitor_config_restore_previous (MetaMonitorConfig *self,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
if (self->previous)
|
||||
{
|
||||
/* The user chose to restore the previous configuration. In this
|
||||
* case, restore the previous configuration. */
|
||||
MetaConfiguration *prev_config = config_ref (self->previous);
|
||||
apply_configuration (self, prev_config, manager);
|
||||
config_unref (prev_config);
|
||||
|
||||
/* After this, self->previous contains the rejected configuration.
|
||||
* Since it was rejected, nuke it. */
|
||||
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
|
||||
}
|
||||
apply_configuration (self, self->previous, manager, FALSE);
|
||||
else
|
||||
{
|
||||
if (!meta_monitor_config_apply_stored (self, manager))
|
||||
@ -1462,8 +1374,7 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
return;
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
apply_configuration (self, new, manager);
|
||||
config_unref (new);
|
||||
apply_configuration (self, new, manager, FALSE);
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
}
|
||||
|
||||
@ -1622,7 +1533,16 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
void
|
||||
meta_monitor_config_make_persistent (MetaMonitorConfig *self)
|
||||
{
|
||||
g_hash_table_replace (self->configs, self->current, config_ref (self->current));
|
||||
if (self->current_is_stored)
|
||||
return;
|
||||
|
||||
self->current_is_stored = TRUE;
|
||||
g_hash_table_replace (self->configs, self->current, self->current);
|
||||
|
||||
if (self->previous)
|
||||
config_free (self->previous);
|
||||
self->previous = NULL;
|
||||
|
||||
meta_monitor_config_save (self);
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,14 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
read_current_config (MetaMonitorManager *manager)
|
||||
{
|
||||
manager->serial++;
|
||||
|
||||
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_logical_config:
|
||||
*
|
||||
@ -190,7 +198,7 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
|
||||
manager->config = meta_monitor_config_new ();
|
||||
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
read_current_config (manager);
|
||||
|
||||
if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
@ -203,7 +211,24 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
so this is not needed.
|
||||
*/
|
||||
if (META_IS_MONITOR_MANAGER_XRANDR (manager))
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
{
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
old_modes = manager->modes;
|
||||
n_old_modes = manager->n_modes;
|
||||
old_crtcs = manager->crtcs;
|
||||
|
||||
read_current_config (manager);
|
||||
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
}
|
||||
|
||||
make_logical_config (manager);
|
||||
initialize_dbus_interface (manager);
|
||||
@ -211,7 +236,7 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
manager->in_init = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs)
|
||||
{
|
||||
@ -234,7 +259,7 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
g_free (old_outputs);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
|
||||
int n_old_modes)
|
||||
{
|
||||
@ -1137,31 +1162,6 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
|
||||
*height = manager->max_screen_height;
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
|
||||
/* Some implementations of read_current use the existing information
|
||||
* we have available, so don't free the old configuration until after
|
||||
* read_current finishes. */
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
old_modes = manager->modes;
|
||||
n_old_modes = manager->n_modes;
|
||||
old_crtcs = manager->crtcs;
|
||||
|
||||
manager->serial++;
|
||||
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
|
||||
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
||||
{
|
||||
@ -1179,22 +1179,3 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
||||
g_free (old_monitor_infos);
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
|
||||
{
|
||||
gboolean applied_config = FALSE;
|
||||
|
||||
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
|
||||
* applying our stored configuration, because it's likely the user just resizing
|
||||
* the window.
|
||||
*/
|
||||
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
{
|
||||
if (meta_monitor_config_apply_stored (manager->config, manager))
|
||||
applied_config = TRUE;
|
||||
}
|
||||
|
||||
/* If we haven't applied any configuration, apply the default configuration. */
|
||||
if (!applied_config)
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
}
|
||||
|
@ -116,8 +116,6 @@ struct _MetaOutput
|
||||
|
||||
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
|
||||
gboolean hotplug_mode_update;
|
||||
gint suggested_x;
|
||||
gint suggested_y;
|
||||
};
|
||||
|
||||
struct _MetaCRTC
|
||||
@ -341,9 +339,11 @@ void meta_monitor_manager_confirm_configuration (MetaMonitorManag
|
||||
void meta_crtc_info_free (MetaCRTCInfo *info);
|
||||
void meta_output_info_free (MetaOutputInfo *info);
|
||||
|
||||
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs);
|
||||
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
|
||||
int n_old_modes);
|
||||
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
|
||||
void meta_monitor_manager_read_current_config (MetaMonitorManager *manager);
|
||||
void meta_monitor_manager_on_hotplug (MetaMonitorManager *manager);
|
||||
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
|
@ -130,8 +130,8 @@ take_device (Login1Session *session_proxy,
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GVariant *fd_variant = NULL;
|
||||
GUnixFDList *fd_list = NULL;
|
||||
int fd = -1;
|
||||
GUnixFDList *fd_list;
|
||||
|
||||
if (!login1_session_call_take_device_sync (session_proxy,
|
||||
dev_major,
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-monitor-manager-kms.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -41,8 +40,6 @@
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
@ -71,8 +68,6 @@ struct _MetaMonitorManagerKms
|
||||
unsigned int n_encoders;
|
||||
|
||||
drmModeEncoder *current_encoder;
|
||||
|
||||
GUdevClient *udev;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerKmsClass
|
||||
@ -415,8 +410,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
meta_output->suggested_x = -1;
|
||||
meta_output->suggested_y = -1;
|
||||
|
||||
switch (connector->subpixel)
|
||||
{
|
||||
@ -900,23 +893,6 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
|
||||
}
|
||||
|
||||
static void
|
||||
on_uevent (GUdevClient *client,
|
||||
const char *action,
|
||||
GUdevDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||
|
||||
if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
|
||||
return;
|
||||
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
|
||||
meta_monitor_manager_on_hotplug (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
||||
{
|
||||
@ -931,21 +907,6 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
||||
cogl_renderer = cogl_display_get_renderer (cogl_display);
|
||||
|
||||
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
|
||||
const char *subsystems[2] = { "drm", NULL };
|
||||
manager_kms->udev = g_udev_client_new (subsystems);
|
||||
g_signal_connect (manager_kms->udev, "uevent",
|
||||
G_CALLBACK (on_uevent), manager_kms);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_kms_dispose (GObject *object)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
|
||||
|
||||
g_clear_object (&manager_kms->udev);
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -964,7 +925,6 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_monitor_manager_kms_dispose;
|
||||
object_class->finalize = meta_monitor_manager_kms_finalize;
|
||||
|
||||
manager_class->read_current = meta_monitor_manager_kms_read_current;
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
|
@ -57,6 +57,7 @@ struct _MetaMonitorManagerXrandr
|
||||
|
||||
Display *xdisplay;
|
||||
XRRScreenResources *resources;
|
||||
int time;
|
||||
int rr_event_base;
|
||||
int rr_error_base;
|
||||
};
|
||||
@ -139,34 +140,6 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname,
|
||||
gint *value)
|
||||
{
|
||||
gboolean exists = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
|
||||
|
||||
if (exists && value != NULL)
|
||||
*value = ((int*)buffer)[0];
|
||||
|
||||
XFree (buffer);
|
||||
return exists;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
@ -384,28 +357,6 @@ output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
|
||||
}
|
||||
|
||||
static gint
|
||||
output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
gint val;
|
||||
if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
|
||||
return val;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gint
|
||||
output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
gint val;
|
||||
if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
|
||||
return val;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_xmode_name (XRRModeInfo *xmode)
|
||||
{
|
||||
@ -486,6 +437,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
return;
|
||||
|
||||
manager_xrandr->resources = resources;
|
||||
manager_xrandr->time = resources->configTimestamp;
|
||||
manager->n_outputs = resources->noutput;
|
||||
manager->n_crtcs = resources->ncrtc;
|
||||
manager->n_modes = resources->nmode;
|
||||
@ -593,8 +545,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
|
||||
meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output);
|
||||
meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
@ -821,7 +771,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
CurrentTime,
|
||||
manager_xrandr->time,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
@ -851,7 +801,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
CurrentTime,
|
||||
manager_xrandr->time,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
@ -888,26 +838,12 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
unsigned int j, n_outputs;
|
||||
int width, height;
|
||||
Status ok;
|
||||
unsigned long old_controlled_mask;
|
||||
unsigned long new_controlled_mask;
|
||||
|
||||
mode = crtc_info->mode;
|
||||
|
||||
n_outputs = crtc_info->outputs->len;
|
||||
outputs = g_new (XID, n_outputs);
|
||||
|
||||
old_controlled_mask = 0;
|
||||
for (j = 0; j < manager->n_outputs; j++)
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
output = &manager->outputs[j];
|
||||
|
||||
if (output->crtc == crtc)
|
||||
old_controlled_mask |= 1UL << j;
|
||||
}
|
||||
|
||||
new_controlled_mask = 0;
|
||||
for (j = 0; j < n_outputs; j++)
|
||||
{
|
||||
MetaOutput *output;
|
||||
@ -916,25 +852,14 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
new_controlled_mask |= 1UL << j;
|
||||
|
||||
outputs[j] = output->winsys_id;
|
||||
}
|
||||
|
||||
if (crtc->current_mode == mode &&
|
||||
crtc->rect.x == crtc_info->x &&
|
||||
crtc->rect.y == crtc_info->y &&
|
||||
crtc->transform == crtc_info->transform &&
|
||||
old_controlled_mask == new_controlled_mask)
|
||||
{
|
||||
/* No change */
|
||||
goto next;
|
||||
}
|
||||
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
CurrentTime,
|
||||
manager_xrandr->time,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
meta_monitor_transform_to_xrandr (crtc_info->transform),
|
||||
@ -1075,6 +1000,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
XRRFreeGamma (gamma);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
|
||||
{
|
||||
/* This will be a no-op if the change was from our side, as
|
||||
we already called it in the DBus method handler */
|
||||
meta_monitor_config_update_current (manager->config, manager);
|
||||
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
@ -1134,30 +1069,57 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
||||
XEvent *event)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
||||
gboolean hotplug;
|
||||
Time old_timestamp;
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
gboolean new_config;
|
||||
gboolean applied_config = FALSE;
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
return FALSE;
|
||||
|
||||
XRRUpdateConfiguration (event);
|
||||
|
||||
old_timestamp = manager_xrandr->resources->timestamp;
|
||||
/* Save the old structures, so they stay valid during the update */
|
||||
old_outputs = manager->outputs;
|
||||
n_old_outputs = manager->n_outputs;
|
||||
old_modes = manager->modes;
|
||||
n_old_modes = manager->n_modes;
|
||||
old_crtcs = manager->crtcs;
|
||||
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
manager->serial++;
|
||||
meta_monitor_manager_xrandr_read_current (manager);
|
||||
|
||||
hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp;
|
||||
if (hotplug)
|
||||
new_config = manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp;
|
||||
|
||||
/* If this is the X server telling us we set a new configuration,
|
||||
* we can simply short-cut to rebuilding our logical configuration.
|
||||
*/
|
||||
if (new_config)
|
||||
{
|
||||
/* This is a hotplug event, so go ahead and build a new configuration. */
|
||||
meta_monitor_manager_on_hotplug (manager);
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
|
||||
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
|
||||
* applying our stored configuration, because it's likely the user just resizing
|
||||
* the window.
|
||||
*/
|
||||
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
{
|
||||
/* If something else changed -- tell the world about it. */
|
||||
if (old_timestamp < manager_xrandr->resources->timestamp)
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
if (meta_monitor_config_apply_stored (manager->config, manager))
|
||||
applied_config = TRUE;
|
||||
}
|
||||
|
||||
/* If we haven't applied any configuration, apply the default configuration. */
|
||||
if (!applied_config)
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
|
||||
out:
|
||||
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
|
||||
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
|
||||
g_free (old_crtcs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -614,6 +614,7 @@ set_unredirected_window (MetaCompositor *compositor,
|
||||
meta_window_actor_set_unredirected (window_actor, FALSE);
|
||||
}
|
||||
|
||||
meta_shape_cow_for_window (compositor, window);
|
||||
compositor->unredirected_window = window;
|
||||
|
||||
if (compositor->unredirected_window != NULL)
|
||||
@ -621,8 +622,6 @@ set_unredirected_window (MetaCompositor *compositor,
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (compositor->unredirected_window));
|
||||
meta_window_actor_set_unredirected (window_actor, TRUE);
|
||||
}
|
||||
|
||||
meta_shape_cow_for_window (compositor, compositor->unredirected_window);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -115,7 +115,7 @@ typedef enum {
|
||||
#define FRAGMENT_SHADER_CODE \
|
||||
"float t = 2.0 * length(position);\n" \
|
||||
"t = min(t, 1.0);\n" \
|
||||
"float pixel_brightness = 1 - t * vignette_sharpness;\n" \
|
||||
"float pixel_brightness = 1.0 - t * vignette_sharpness;\n" \
|
||||
"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \
|
||||
|
||||
typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
|
||||
|
@ -53,7 +53,7 @@ struct _MetaBackgroundImageCacheClass
|
||||
struct _MetaBackgroundImage
|
||||
{
|
||||
GObject parent_instance;
|
||||
GFile *file;
|
||||
char *filename;
|
||||
MetaBackgroundImageCache *cache;
|
||||
gboolean in_cache;
|
||||
gboolean loaded;
|
||||
@ -70,7 +70,7 @@ G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJ
|
||||
static void
|
||||
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
|
||||
{
|
||||
cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
|
||||
cache->images = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -124,17 +124,9 @@ load_file (GTask *task,
|
||||
{
|
||||
GError *error = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
GFileInputStream *stream;
|
||||
|
||||
stream = g_file_read (image->file, NULL, &error);
|
||||
if (stream == NULL)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error);
|
||||
g_object_unref (stream);
|
||||
pixbuf = gdk_pixbuf_new_from_file (image->filename,
|
||||
&error);
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
@ -164,11 +156,9 @@ file_loaded (GObject *source_object,
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
char *uri = g_file_get_uri (image->file);
|
||||
g_warning ("Failed to load background '%s': %s",
|
||||
uri, error->message);
|
||||
image->filename, error->message);
|
||||
g_clear_error (&error);
|
||||
g_free (uri);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -205,7 +195,7 @@ out:
|
||||
/**
|
||||
* meta_background_image_cache_load:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @file: #GFile to load
|
||||
* @filename: filename to load
|
||||
*
|
||||
* Loads an image to use as a background, or returns a reference to an
|
||||
* image that is already in the process of loading or loaded. In either
|
||||
@ -219,23 +209,23 @@ out:
|
||||
*/
|
||||
MetaBackgroundImage *
|
||||
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
GFile *file)
|
||||
const char *filename)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, file);
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
if (image != NULL)
|
||||
return g_object_ref (image);
|
||||
|
||||
image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
|
||||
image->cache = cache;
|
||||
image->in_cache = TRUE;
|
||||
image->file = g_object_ref (file);
|
||||
g_hash_table_insert (cache->images, image->file, image);
|
||||
image->filename = g_strdup (filename);
|
||||
g_hash_table_insert (cache->images, image->filename, image);
|
||||
|
||||
task = g_task_new (image, NULL, file_loaded, NULL);
|
||||
|
||||
@ -248,25 +238,25 @@ meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
/**
|
||||
* meta_background_image_cache_purge:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @file: file to remove from the cache
|
||||
* @filename: filename to remove from the cache
|
||||
*
|
||||
* Remove an entry from the cache; this would be used if monitoring
|
||||
* showed that the file changed.
|
||||
*/
|
||||
void
|
||||
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
|
||||
GFile *file)
|
||||
const char *filename)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
|
||||
g_return_if_fail (file != NULL);
|
||||
g_return_if_fail (filename != NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, file);
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
if (image == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_remove (cache->images, image->file);
|
||||
g_hash_table_remove (cache->images, image->filename);
|
||||
image->in_cache = FALSE;
|
||||
}
|
||||
|
||||
@ -283,12 +273,12 @@ meta_background_image_finalize (GObject *object)
|
||||
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
|
||||
|
||||
if (image->in_cache)
|
||||
g_hash_table_remove (image->cache->images, image->file);
|
||||
g_hash_table_remove (image->cache->images, image->filename);
|
||||
|
||||
if (image->texture)
|
||||
cogl_object_unref (image->texture);
|
||||
if (image->file)
|
||||
g_object_unref (image->file);
|
||||
if (image->filename)
|
||||
g_free (image->filename);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -50,9 +50,9 @@ struct _MetaBackgroundPrivate
|
||||
ClutterColor color;
|
||||
ClutterColor second_color;
|
||||
|
||||
GFile *file1;
|
||||
char *filename1;
|
||||
MetaBackgroundImage *background_image1;
|
||||
GFile *file2;
|
||||
char *filename2;
|
||||
MetaBackgroundImage *background_image2;
|
||||
|
||||
CoglTexture *color_texture;
|
||||
@ -71,6 +71,8 @@ enum
|
||||
|
||||
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
|
||||
|
||||
static GSList *all_backgrounds = NULL;
|
||||
|
||||
static void
|
||||
free_fbos (MetaBackground *self)
|
||||
{
|
||||
@ -241,28 +243,16 @@ on_background_loaded (MetaBackgroundImage *image,
|
||||
mark_changed (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
file_equal0 (GFile *file1,
|
||||
GFile *file2)
|
||||
{
|
||||
if (file1 == file2)
|
||||
return TRUE;
|
||||
|
||||
if ((file1 == NULL) || (file2 == NULL))
|
||||
return FALSE;
|
||||
|
||||
return g_file_equal (file1, file2);
|
||||
}
|
||||
|
||||
static void
|
||||
set_file (MetaBackground *self,
|
||||
GFile **filep,
|
||||
MetaBackgroundImage **imagep,
|
||||
GFile *file)
|
||||
set_filename (MetaBackground *self,
|
||||
char **filenamep,
|
||||
MetaBackgroundImage **imagep,
|
||||
const char *filename)
|
||||
{
|
||||
if (!file_equal0 (*filep, file))
|
||||
if (g_strcmp0 (filename, *filenamep) != 0)
|
||||
{
|
||||
g_clear_object (filep);
|
||||
g_free (*filenamep);
|
||||
*filenamep = g_strdup (filename);
|
||||
|
||||
if (*imagep)
|
||||
{
|
||||
@ -273,12 +263,10 @@ set_file (MetaBackground *self,
|
||||
*imagep = NULL;
|
||||
}
|
||||
|
||||
if (file)
|
||||
if (filename)
|
||||
{
|
||||
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
|
||||
|
||||
*filep = g_object_ref (file);
|
||||
*imagep = meta_background_image_cache_load (cache, file);
|
||||
*imagep = meta_background_image_cache_load (cache, filename);
|
||||
g_signal_connect (*imagep, "loaded",
|
||||
G_CALLBACK (on_background_loaded), self);
|
||||
}
|
||||
@ -294,8 +282,8 @@ meta_background_dispose (GObject *object)
|
||||
free_color_texture (self);
|
||||
free_wallpaper_texture (self);
|
||||
|
||||
set_file (self, &priv->file1, &priv->background_image1, NULL);
|
||||
set_file (self, &priv->file2, &priv->background_image2, NULL);
|
||||
set_filename (self, &priv->filename1, &priv->background_image1, NULL);
|
||||
set_filename (self, &priv->filename2, &priv->background_image2, NULL);
|
||||
|
||||
set_screen (self, NULL);
|
||||
|
||||
@ -305,6 +293,8 @@ meta_background_dispose (GObject *object)
|
||||
static void
|
||||
meta_background_finalize (GObject *object)
|
||||
{
|
||||
all_backgrounds = g_slist_remove (all_backgrounds, object);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@ -347,6 +337,7 @@ meta_background_init (MetaBackground *self)
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_BACKGROUND,
|
||||
MetaBackgroundPrivate);
|
||||
all_backgrounds = g_slist_prepend (all_backgrounds, self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -881,19 +872,19 @@ meta_background_set_gradient (MetaBackground *self,
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_set_file (MetaBackground *self,
|
||||
GFile *file,
|
||||
GDesktopBackgroundStyle style)
|
||||
meta_background_set_filename (MetaBackground *self,
|
||||
const char *filename,
|
||||
GDesktopBackgroundStyle style)
|
||||
{
|
||||
g_return_if_fail (META_IS_BACKGROUND (self));
|
||||
|
||||
meta_background_set_blend (self, file, NULL, 0.0, style);
|
||||
meta_background_set_blend (self, filename, NULL, 0.0, style);
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_set_blend (MetaBackground *self,
|
||||
GFile *file1,
|
||||
GFile *file2,
|
||||
const char *filename1,
|
||||
const char *filename2,
|
||||
double blend_factor,
|
||||
GDesktopBackgroundStyle style)
|
||||
{
|
||||
@ -904,8 +895,8 @@ meta_background_set_blend (MetaBackground *self,
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
set_file (self, &priv->file1, &priv->background_image1, file1);
|
||||
set_file (self, &priv->file2, &priv->background_image2, file2);
|
||||
set_filename (self, &priv->filename1, &priv->background_image1, filename1);
|
||||
set_filename (self, &priv->filename2, &priv->background_image2, filename2);
|
||||
|
||||
priv->blend_factor = blend_factor;
|
||||
priv->style = style;
|
||||
@ -913,3 +904,12 @@ meta_background_set_blend (MetaBackground *self,
|
||||
free_wallpaper_texture (self);
|
||||
mark_changed (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_refresh_all (void)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = all_backgrounds; l; l = l->next)
|
||||
mark_changed (l->data);
|
||||
}
|
||||
|
@ -49,8 +49,6 @@ meta_surface_actor_pick (ClutterActor *actor,
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor))
|
||||
return;
|
||||
@ -94,11 +92,6 @@ meta_surface_actor_pick (ClutterActor *actor,
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -100,7 +100,7 @@ struct _MetaWindowActorPrivate
|
||||
guint disposed : 1;
|
||||
|
||||
/* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN
|
||||
* client message using the most recent frame in ->frames */
|
||||
* client message for one or more messages in ->frames */
|
||||
guint needs_frame_drawn : 1;
|
||||
guint repaint_scheduled : 1;
|
||||
|
||||
@ -118,10 +118,21 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
typedef struct _FrameData FrameData;
|
||||
|
||||
/* Each time the application updates the sync request counter to a new even value
|
||||
* value, we queue a frame into the windows list of frames. Once we're painting
|
||||
* an update "in response" to the window, we fill in frame_counter with the
|
||||
* Cogl counter for that frame, and send _NET_WM_FRAME_DRAWN at the end of the
|
||||
* frame. _NET_WM_FRAME_TIMINGS is sent when we get a frame_complete callback.
|
||||
*
|
||||
* As an exception, if a window is completely obscured, we try to throttle drawning
|
||||
* to a slower frame rate. In this case, frame_counter stays -1 until
|
||||
* send_frame_message_timeout() runs, at which point we send both the
|
||||
* _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages.
|
||||
*/
|
||||
struct _FrameData
|
||||
{
|
||||
int64_t frame_counter;
|
||||
guint64 sync_request_serial;
|
||||
int64_t frame_counter;
|
||||
gint64 frame_drawn_time;
|
||||
};
|
||||
|
||||
@ -655,6 +666,30 @@ clip_shadow_under_window (MetaWindowActor *self)
|
||||
return is_non_opaque (self) && priv->window->frame;
|
||||
}
|
||||
|
||||
static void
|
||||
assign_frame_counter_to_frames (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
GList *l;
|
||||
|
||||
/* If the window is obscured, then we're expecting to deal with sending
|
||||
* frame messages in a timeout, rather than in this paint cycle.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
for (l = priv->frames; l; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_counter == -1)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
||||
frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
@ -671,6 +706,8 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
g_source_remove (priv->send_frame_messages_timer);
|
||||
priv->send_frame_messages_timer = 0;
|
||||
|
||||
assign_frame_counter_to_frames (self);
|
||||
}
|
||||
|
||||
if (shadow != NULL)
|
||||
@ -873,16 +910,27 @@ send_frame_messages_timeout (gpointer data)
|
||||
{
|
||||
MetaWindowActor *self = (MetaWindowActor *) data;
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
FrameData *frame = g_slice_new0 (FrameData);
|
||||
GList *l;
|
||||
|
||||
frame->sync_request_serial = priv->window->sync_request_serial;
|
||||
for (l = priv->frames; l;)
|
||||
{
|
||||
GList *l_next = l->next;
|
||||
FrameData *frame = l->data;
|
||||
|
||||
do_send_frame_drawn (self, frame);
|
||||
do_send_frame_timings (self, frame, 0, 0);
|
||||
if (frame->frame_counter == -1)
|
||||
{
|
||||
do_send_frame_drawn (self, frame);
|
||||
do_send_frame_timings (self, frame, 0, 0);
|
||||
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
|
||||
l = l_next;
|
||||
}
|
||||
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
priv->send_frame_messages_timer = 0;
|
||||
frame_data_free (frame);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -891,6 +939,10 @@ static void
|
||||
queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
MetaDisplay *display = meta_window_get_display (priv->window);
|
||||
gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
|
||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||
@ -933,6 +985,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
return;
|
||||
|
||||
frame = g_slice_new0 (FrameData);
|
||||
frame->frame_counter = -1;
|
||||
|
||||
priv->needs_frame_drawn = TRUE;
|
||||
|
||||
@ -1905,24 +1958,12 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
|
||||
void
|
||||
meta_window_actor_pre_paint (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
GList *l;
|
||||
|
||||
if (meta_window_actor_is_destroyed (self))
|
||||
return;
|
||||
|
||||
meta_window_actor_handle_updates (self);
|
||||
|
||||
for (l = priv->frames; l != NULL; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_counter == 0)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (cogl_get_draw_framebuffer());
|
||||
frame->frame_counter = cogl_onscreen_get_frame_counter (onscreen);
|
||||
}
|
||||
}
|
||||
assign_frame_counter_to_frames (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1963,16 +2004,23 @@ meta_window_actor_post_paint (MetaWindowActor *self)
|
||||
if (meta_window_actor_is_destroyed (self))
|
||||
return;
|
||||
|
||||
/* This window had damage, but wasn't actually redrawn because
|
||||
* it is obscured. So we should wait until timer expiration
|
||||
* before sending _NET_WM_FRAME_* messages.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
return;
|
||||
|
||||
if (priv->needs_frame_drawn)
|
||||
/* If the window had damage, but wasn't actually redrawn because
|
||||
* it is obscured, we should wait until timer expiration before
|
||||
* sending _NET_WM_FRAME_* messages.
|
||||
*/
|
||||
if (priv->send_frame_messages_timer == 0 &&
|
||||
priv->needs_frame_drawn)
|
||||
{
|
||||
do_send_frame_drawn (self, priv->frames->data);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->frames; l; l = l->next)
|
||||
{
|
||||
FrameData *frame = l->data;
|
||||
|
||||
if (frame->frame_drawn_time == 0)
|
||||
do_send_frame_drawn (self, frame);
|
||||
}
|
||||
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
}
|
||||
|
||||
@ -2057,15 +2105,20 @@ meta_window_actor_frame_complete (MetaWindowActor *self,
|
||||
{
|
||||
GList *l_next = l->next;
|
||||
FrameData *frame = l->data;
|
||||
gint64 frame_counter = cogl_frame_info_get_frame_counter (frame_info);
|
||||
|
||||
if (frame->frame_counter == cogl_frame_info_get_frame_counter (frame_info))
|
||||
if (frame->frame_counter != -1 && frame->frame_counter <= frame_counter)
|
||||
{
|
||||
if (frame->frame_drawn_time != 0)
|
||||
{
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
send_frame_timings (self, frame, frame_info, presentation_time);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
if (G_UNLIKELY (frame->frame_drawn_time == 0))
|
||||
g_warning ("%s: Frame has assigned frame counter but no frame drawn time",
|
||||
priv->window->desc);
|
||||
if (G_UNLIKELY (frame->frame_counter < frame_counter))
|
||||
g_warning ("%s: frame_complete callback never occurred for frame %" G_GINT64_FORMAT,
|
||||
priv->window->desc, frame->frame_counter);
|
||||
|
||||
priv->frames = g_list_delete_link (priv->frames, l);
|
||||
send_frame_timings (self, frame, frame_info, presentation_time);
|
||||
frame_data_free (frame);
|
||||
}
|
||||
|
||||
l = l_next;
|
||||
|
@ -1017,7 +1017,6 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
double best_width, best_height;
|
||||
double alt_width, alt_height;
|
||||
MetaRectangle *start_rect;
|
||||
MetaRectangle client_rect;
|
||||
|
||||
if (priority > PRIORITY_ASPECT_RATIO)
|
||||
return TRUE;
|
||||
@ -1069,18 +1068,15 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
fudge = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
|
||||
|
||||
constraint_already_satisfied =
|
||||
client_rect.width - (client_rect.height * minr ) > -minr*fudge &&
|
||||
client_rect.width - (client_rect.height * maxr ) < maxr*fudge;
|
||||
info->current.width - (info->current.height * minr ) > -minr*fudge &&
|
||||
info->current.width - (info->current.height * maxr ) < maxr*fudge;
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
new_width = client_rect.width;
|
||||
new_height = client_rect.height;
|
||||
new_width = info->current.width;
|
||||
new_height = info->current.height;
|
||||
|
||||
switch (info->resize_gravity)
|
||||
{
|
||||
@ -1127,14 +1123,6 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
client_rect.width = new_width;
|
||||
client_rect.height = new_height;
|
||||
meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
|
||||
new_width = client_rect.width;
|
||||
new_height = client_rect.height;
|
||||
}
|
||||
|
||||
/* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
|
||||
* See bug 448183
|
||||
*/
|
||||
|
@ -1214,7 +1214,7 @@ meta_grab_op_is_moving (MetaGrabOp op)
|
||||
if (!grab_op_is_window (op))
|
||||
return FALSE;
|
||||
|
||||
return (op & META_GRAB_OP_WINDOW_DIR_MASK) == 0;
|
||||
return !meta_grab_op_is_resizing (op);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1953,11 +1953,6 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
|
||||
display->screen, grab_window, grab_op);
|
||||
|
||||
/* We need to reset this early, since the
|
||||
* meta_window_grab_op_ended callback relies on this being
|
||||
* up to date. */
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
|
||||
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
|
||||
{
|
||||
/* Clear out the edge cache */
|
||||
@ -1990,6 +1985,7 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
}
|
||||
|
||||
display->event_route = META_EVENT_ROUTE_NORMAL;
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
|
@ -151,6 +151,23 @@ sequence_is_pointer_emulated (MetaDisplay *display,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_display_update_pointer_emulating_sequence (MetaDisplay *display,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN &&
|
||||
!display->pointer_emulating_sequence &&
|
||||
sequence_is_pointer_emulated (display, event))
|
||||
display->pointer_emulating_sequence = sequence;
|
||||
else if (event->type == CLUTTER_TOUCH_END &&
|
||||
display->pointer_emulating_sequence == sequence)
|
||||
display->pointer_emulating_sequence = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_display_handle_event (MetaDisplay *display,
|
||||
const ClutterEvent *event)
|
||||
@ -159,15 +176,8 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
gboolean bypass_clutter = FALSE;
|
||||
G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
|
||||
MetaGestureTracker *tracker;
|
||||
ClutterEventSequence *sequence;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
/* Set the pointer emulating sequence on touch begin, if eligible */
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN &&
|
||||
!display->pointer_emulating_sequence &&
|
||||
sequence_is_pointer_emulated (display, event))
|
||||
display->pointer_emulating_sequence = sequence;
|
||||
meta_display_update_pointer_emulating_sequence (display, event);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
MetaWaylandCompositor *compositor = NULL;
|
||||
@ -304,11 +314,6 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Unset the pointer emulating sequence after its end event is processed */
|
||||
if (event->type == CLUTTER_TOUCH_END &&
|
||||
display->pointer_emulating_sequence == sequence)
|
||||
display->pointer_emulating_sequence = NULL;
|
||||
|
||||
display->current_time = CurrentTime;
|
||||
return bypass_clutter;
|
||||
}
|
||||
|
@ -1660,14 +1660,13 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
|
||||
grab_keyboard (window, timestamp, XIGrabModeSync);
|
||||
}
|
||||
|
||||
|
@ -779,7 +779,8 @@ meta_window_place (MetaWindow *window,
|
||||
|
||||
if (w != window &&
|
||||
meta_window_showing_on_its_workspace (w) &&
|
||||
meta_window_located_on_workspace (w, window->workspace))
|
||||
(window->on_all_workspaces ||
|
||||
meta_window_located_on_workspace (w, window->workspace)))
|
||||
windows = g_list_prepend (windows, w);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
@ -3213,9 +3213,7 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
/* Window's size hints may have changed while maximized, making
|
||||
* saved_rect invalid. #329152
|
||||
*/
|
||||
meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect);
|
||||
ensure_size_hints_satisfied (&target_rect, &window->size_hints);
|
||||
meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
|
||||
|
||||
/* Need to update window->has_resize_func before we move_resize()
|
||||
*/
|
||||
@ -5853,7 +5851,7 @@ update_resize (MetaWindow *window,
|
||||
int new_w, new_h;
|
||||
int gravity;
|
||||
MetaRectangle old;
|
||||
double remaining = 0;
|
||||
double remaining;
|
||||
MetaMaximizeFlags new_unmaximize;
|
||||
|
||||
window->display->grab_latest_motion_x = x;
|
||||
@ -6112,8 +6110,10 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (event->button.button == 1 ||
|
||||
event->button.button == (unsigned int) meta_prefs_get_mouse_button_resize ())
|
||||
end_grab_op (window, event);
|
||||
|
||||
{
|
||||
end_grab_op (window, event);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
|
@ -173,6 +173,7 @@ void meta_display_unmanage_screen (MetaDisplay *display,
|
||||
void meta_display_clear_mouse_mode (MetaDisplay *display);
|
||||
|
||||
void meta_display_freeze_keyboard (MetaDisplay *display,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
void meta_display_ungrab_keyboard (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
|
71
src/meta/gradient.h
Normal file
71
src/meta/gradient.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter gradient rendering */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in
|
||||
* WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef META_GRADIENT_H
|
||||
#define META_GRADIENT_H
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
/**
|
||||
* MetaGradientType:
|
||||
* @META_GRADIENT_VERTICAL: Vertical gradient
|
||||
* @META_GRADIENT_HORIZONTAL: Horizontal gradient
|
||||
* @META_GRADIENT_DIAGONAL: Diagonal gradient
|
||||
* @META_GRADIENT_LAST: Marks the end of the #MetaGradientType enumeration
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_GRADIENT_VERTICAL,
|
||||
META_GRADIENT_HORIZONTAL,
|
||||
META_GRADIENT_DIAGONAL,
|
||||
META_GRADIENT_LAST
|
||||
} MetaGradientType;
|
||||
|
||||
GdkPixbuf* meta_gradient_create_simple (int width,
|
||||
int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to,
|
||||
MetaGradientType style);
|
||||
GdkPixbuf* meta_gradient_create_multi (int width,
|
||||
int height,
|
||||
const GdkRGBA *colors,
|
||||
int n_colors,
|
||||
MetaGradientType style);
|
||||
GdkPixbuf* meta_gradient_create_interwoven (int width,
|
||||
int height,
|
||||
const GdkRGBA colors1[2],
|
||||
int thickness1,
|
||||
const GdkRGBA colors2[2],
|
||||
int thickness2);
|
||||
|
||||
|
||||
/* Generate an alpha gradient and multiply it with the existing alpha
|
||||
* channel of the given pixbuf
|
||||
*/
|
||||
void meta_gradient_add_alpha (GdkPixbuf *pixbuf,
|
||||
const guchar *alphas,
|
||||
int n_alphas,
|
||||
MetaGradientType type);
|
||||
|
||||
|
||||
#endif
|
@ -69,8 +69,8 @@ MetaBackgroundImageCache *meta_background_image_cache_get_default (void);
|
||||
GType meta_background_image_cache_get_type (void);
|
||||
|
||||
MetaBackgroundImage *meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
GFile *file);
|
||||
const char *filename);
|
||||
void meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
|
||||
GFile *file);
|
||||
const char *filename);
|
||||
|
||||
#endif /* __META_BACKGROUND_IMAGE_H__ */
|
||||
|
@ -57,6 +57,8 @@ struct _MetaBackground
|
||||
MetaBackgroundPrivate *priv;
|
||||
};
|
||||
|
||||
void meta_background_refresh_all (void);
|
||||
|
||||
GType meta_background_get_type (void);
|
||||
|
||||
MetaBackground *meta_background_new (MetaScreen *screen);
|
||||
@ -67,12 +69,12 @@ void meta_background_set_gradient (MetaBackground *self,
|
||||
GDesktopBackgroundShading shading_direction,
|
||||
ClutterColor *color,
|
||||
ClutterColor *second_color);
|
||||
void meta_background_set_file (MetaBackground *self,
|
||||
GFile *file,
|
||||
void meta_background_set_filename (MetaBackground *self,
|
||||
const char *filename,
|
||||
GDesktopBackgroundStyle style);
|
||||
void meta_background_set_blend (MetaBackground *self,
|
||||
GFile *file1,
|
||||
GFile *file2,
|
||||
const char *filename1,
|
||||
const char *filename2,
|
||||
double blend_factor,
|
||||
GDesktopBackgroundStyle style);
|
||||
|
||||
|
902
src/ui/gradient.c
Normal file
902
src/ui/gradient.c
Normal file
@ -0,0 +1,902 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington, 99% copied from wrlib in
|
||||
* WindowMaker, Copyright (C) 1997-2000 Dan Pascu and Alfredo Kojima
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/**
|
||||
* SECTION:gradient
|
||||
* @title: Gradients
|
||||
* @short_description: Metacity gradient rendering
|
||||
*/
|
||||
|
||||
#include <meta/gradient.h>
|
||||
#include <meta/util.h>
|
||||
#include <string.h>
|
||||
|
||||
/* This is all Alfredo's and Dan's usual very nice WindowMaker code,
|
||||
* slightly GTK-ized
|
||||
*/
|
||||
static GdkPixbuf* meta_gradient_create_horizontal (int width,
|
||||
int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to);
|
||||
static GdkPixbuf* meta_gradient_create_vertical (int width,
|
||||
int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to);
|
||||
static GdkPixbuf* meta_gradient_create_diagonal (int width,
|
||||
int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to);
|
||||
static GdkPixbuf* meta_gradient_create_multi_horizontal (int width,
|
||||
int height,
|
||||
const GdkRGBA *colors,
|
||||
int count);
|
||||
static GdkPixbuf* meta_gradient_create_multi_vertical (int width,
|
||||
int height,
|
||||
const GdkRGBA *colors,
|
||||
int count);
|
||||
static GdkPixbuf* meta_gradient_create_multi_diagonal (int width,
|
||||
int height,
|
||||
const GdkRGBA *colors,
|
||||
int count);
|
||||
|
||||
|
||||
/* Used as the destroy notification function for gdk_pixbuf_new() */
|
||||
static void
|
||||
free_buffer (guchar *pixels, gpointer data)
|
||||
{
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
blank_pixbuf (int width, int height)
|
||||
{
|
||||
guchar *buf;
|
||||
int rowstride;
|
||||
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
|
||||
/* Always align rows to 32-bit boundaries */
|
||||
rowstride = 4 * ((4 * width + 4) / 4);
|
||||
|
||||
buf = g_try_malloc (height * rowstride);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
|
||||
TRUE, 8,
|
||||
width, height, rowstride,
|
||||
free_buffer, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_gradient_create_simple:
|
||||
* @width: Width in pixels
|
||||
* @height: Height in pixels
|
||||
* @from: Starting color
|
||||
* @to: Ending color
|
||||
* @style: Gradient style
|
||||
*
|
||||
* Returns: (transfer full): A new linear gradient
|
||||
*/
|
||||
GdkPixbuf*
|
||||
meta_gradient_create_simple (int width,
|
||||
int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to,
|
||||
MetaGradientType style)
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case META_GRADIENT_HORIZONTAL:
|
||||
return meta_gradient_create_horizontal (width, height,
|
||||
from, to);
|
||||
case META_GRADIENT_VERTICAL:
|
||||
return meta_gradient_create_vertical (width, height,
|
||||
from, to);
|
||||
|
||||
case META_GRADIENT_DIAGONAL:
|
||||
return meta_gradient_create_diagonal (width, height,
|
||||
from, to);
|
||||
case META_GRADIENT_LAST:
|
||||
break;
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_gradient_create_multi:
|
||||
* @width: Width in pixels
|
||||
* @height: Height in pixels
|
||||
* @colors: (array length=n_colors): Array of colors
|
||||
* @n_colors: Number of colors
|
||||
* @style: Gradient style
|
||||
*
|
||||
* Returns: (transfer full): A new multi-step linear gradient
|
||||
*/
|
||||
GdkPixbuf*
|
||||
meta_gradient_create_multi (int width,
|
||||
int height,
|
||||
const GdkRGBA *colors,
|
||||
int n_colors,
|
||||
MetaGradientType style)
|
||||
{
|
||||
|
||||
if (n_colors > 2)
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case META_GRADIENT_HORIZONTAL:
|
||||
return meta_gradient_create_multi_horizontal (width, height, colors, n_colors);
|
||||
case META_GRADIENT_VERTICAL:
|
||||
return meta_gradient_create_multi_vertical (width, height, colors, n_colors);
|
||||
case META_GRADIENT_DIAGONAL:
|
||||
return meta_gradient_create_multi_diagonal (width, height, colors, n_colors);
|
||||
case META_GRADIENT_LAST:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (n_colors > 1)
|
||||
{
|
||||
return meta_gradient_create_simple (width, height, &colors[0], &colors[1],
|
||||
style);
|
||||
}
|
||||
else if (n_colors > 0)
|
||||
{
|
||||
return meta_gradient_create_simple (width, height, &colors[0], &colors[0],
|
||||
style);
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_gradient_create_interwoven: (skip)
|
||||
* @width: Width in pixels
|
||||
* @height: Height in pixels
|
||||
* @colors1: Array of colors
|
||||
* @thickness1: Thickness
|
||||
* @colors2: Array of colors
|
||||
* @thickness2: Thickness
|
||||
*
|
||||
* Interwoven essentially means we have two vertical gradients,
|
||||
* cut into horizontal strips of the given thickness, and then the strips
|
||||
* are alternated. I'm not sure what it's good for, just copied since
|
||||
* WindowMaker had it.
|
||||
*/
|
||||
GdkPixbuf*
|
||||
meta_gradient_create_interwoven (int width,
|
||||
int height,
|
||||
const GdkRGBA colors1[2],
|
||||
int thickness1,
|
||||
const GdkRGBA colors2[2],
|
||||
int thickness2)
|
||||
{
|
||||
|
||||
int i, j, k, l, ll;
|
||||
long r1, g1, b1, a1, dr1, dg1, db1, da1;
|
||||
long r2, g2, b2, a2, dr2, dg2, db2, da2;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int rowstride;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
r1 = (long)(colors1[0].red*0xffffff);
|
||||
g1 = (long)(colors1[0].green*0xffffff);
|
||||
b1 = (long)(colors1[0].blue*0xffffff);
|
||||
a1 = (long)(colors1[0].alpha*0xffffff);
|
||||
|
||||
r2 = (long)(colors2[0].red*0xffffff);
|
||||
g2 = (long)(colors2[0].green*0xffffff);
|
||||
b2 = (long)(colors2[0].blue*0xffffff);
|
||||
a2 = (long)(colors2[0].alpha*0xffffff);
|
||||
|
||||
dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
|
||||
dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
|
||||
db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
|
||||
da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height;
|
||||
|
||||
dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
|
||||
dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
|
||||
db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
|
||||
da2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height;
|
||||
|
||||
for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
|
||||
{
|
||||
ptr = pixels + i * rowstride;
|
||||
|
||||
if (k == 0)
|
||||
{
|
||||
ptr[0] = (unsigned char) (r1>>16);
|
||||
ptr[1] = (unsigned char) (g1>>16);
|
||||
ptr[2] = (unsigned char) (b1>>16);
|
||||
ptr[3] = (unsigned char) (a1>>16);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr[0] = (unsigned char) (r2>>16);
|
||||
ptr[1] = (unsigned char) (g2>>16);
|
||||
ptr[2] = (unsigned char) (b2>>16);
|
||||
ptr[3] = (unsigned char) (a2>>16);
|
||||
}
|
||||
|
||||
for (j=1; j <= width/2; j *= 2)
|
||||
memcpy (&(ptr[j*4]), ptr, j*4);
|
||||
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
|
||||
|
||||
if (++l == ll)
|
||||
{
|
||||
if (k == 0)
|
||||
{
|
||||
k = 1;
|
||||
ll = thickness2;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 0;
|
||||
ll = thickness1;
|
||||
}
|
||||
l = 0;
|
||||
}
|
||||
r1+=dr1;
|
||||
g1+=dg1;
|
||||
b1+=db1;
|
||||
a1+=da1;
|
||||
|
||||
r2+=dr2;
|
||||
g2+=dg2;
|
||||
b2+=db2;
|
||||
a2+=da2;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* meta_gradient_create_horizontal--
|
||||
* Renders a horizontal linear gradient of the specified size in the
|
||||
* GdkPixbuf format with a border of the specified type.
|
||||
*
|
||||
* Returns:
|
||||
* A 24bit GdkPixbuf with the gradient (no alpha channel).
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_horizontal (int width, int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to)
|
||||
{
|
||||
int i;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int r0, g0, b0, a0;
|
||||
int rf, gf, bf, af;
|
||||
int rowstride;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
ptr = pixels;
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
r0 = (guchar) (from->red * 0xff);
|
||||
g0 = (guchar) (from->green * 0xff);
|
||||
b0 = (guchar) (from->blue * 0xff);
|
||||
a0 = (guchar) (from->alpha * 0xff);
|
||||
rf = (guchar) (to->red * 0xff);
|
||||
gf = (guchar) (to->green * 0xff);
|
||||
bf = (guchar) (to->blue * 0xff);
|
||||
af = (guchar) (to->alpha * 0xff);
|
||||
|
||||
r = r0 << 16;
|
||||
g = g0 << 16;
|
||||
b = b0 << 16;
|
||||
a = a0 << 16;
|
||||
|
||||
dr = ((rf-r0)<<16)/(int)width;
|
||||
dg = ((gf-g0)<<16)/(int)width;
|
||||
db = ((bf-b0)<<16)/(int)width;
|
||||
da = ((af-a0)<<16)/(int)width;
|
||||
/* render the first line */
|
||||
for (i=0; i<width; i++)
|
||||
{
|
||||
*(ptr++) = (unsigned char)(r>>16);
|
||||
*(ptr++) = (unsigned char)(g>>16);
|
||||
*(ptr++) = (unsigned char)(b>>16);
|
||||
*(ptr++) = (unsigned char)(a>>16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
}
|
||||
|
||||
/* copy the first line to the other lines */
|
||||
for (i=1; i<height; i++)
|
||||
{
|
||||
memcpy (&(pixels[i*rowstride]), pixels, rowstride);
|
||||
}
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* meta_gradient_create_vertical--
|
||||
* Renders a vertical linear gradient of the specified size in the
|
||||
* GdkPixbuf format with a border of the specified type.
|
||||
*
|
||||
* Returns:
|
||||
* A 24bit GdkPixbuf with the gradient (no alpha channel).
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_vertical (int width, int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to)
|
||||
{
|
||||
int i, j;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
int r0, g0, b0, a0;
|
||||
int rf, gf, bf, af;
|
||||
int rowstride;
|
||||
unsigned char *pixels;
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
r0 = (guchar) (from->red * 0xff);
|
||||
g0 = (guchar) (from->green * 0xff);
|
||||
b0 = (guchar) (from->blue * 0xff);
|
||||
a0 = (guchar) (from->alpha * 0xff);
|
||||
rf = (guchar) (to->red * 0xff);
|
||||
gf = (guchar) (to->green * 0xff);
|
||||
bf = (guchar) (to->blue * 0xff);
|
||||
af = (guchar) (to->alpha * 0xff);
|
||||
|
||||
r = r0<<16;
|
||||
g = g0<<16;
|
||||
b = b0<<16;
|
||||
a = a0<<16;
|
||||
|
||||
dr = ((rf-r0)<<16)/(int)height;
|
||||
dg = ((gf-g0)<<16)/(int)height;
|
||||
db = ((bf-b0)<<16)/(int)height;
|
||||
da = ((af-a0)<<16)/(int)height;
|
||||
|
||||
for (i=0; i<height; i++)
|
||||
{
|
||||
ptr = pixels + i * rowstride;
|
||||
|
||||
ptr[0] = (unsigned char)(r>>16);
|
||||
ptr[1] = (unsigned char)(g>>16);
|
||||
ptr[2] = (unsigned char)(b>>16);
|
||||
ptr[3] = (unsigned char)(a>>16);
|
||||
|
||||
for (j=1; j <= width/2; j *= 2)
|
||||
memcpy (&(ptr[j*4]), ptr, j*4);
|
||||
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
|
||||
|
||||
r+=dr;
|
||||
g+=dg;
|
||||
b+=db;
|
||||
a+=da;
|
||||
}
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* meta_gradient_create_diagonal--
|
||||
* Renders a diagonal linear gradient of the specified size in the
|
||||
* GdkPixbuf format with a border of the specified type.
|
||||
*
|
||||
* Returns:
|
||||
* A 24bit GdkPixbuf with the gradient (no alpha channel).
|
||||
*
|
||||
* Side effects:
|
||||
* None
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_diagonal (int width, int height,
|
||||
const GdkRGBA *from,
|
||||
const GdkRGBA *to)
|
||||
{
|
||||
GdkPixbuf *pixbuf, *tmp;
|
||||
int j;
|
||||
float a, offset;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int rowstride;
|
||||
|
||||
if (width == 1)
|
||||
return meta_gradient_create_vertical (width, height, from, to);
|
||||
else if (height == 1)
|
||||
return meta_gradient_create_horizontal (width, height, from, to);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
tmp = meta_gradient_create_horizontal (2*width-1, 1, from, to);
|
||||
if (!tmp)
|
||||
{
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = gdk_pixbuf_get_pixels (tmp);
|
||||
|
||||
a = ((float)(width - 1))/((float)(height - 1));
|
||||
width = width * 4;
|
||||
|
||||
/* copy the first line to the other lines with corresponding offset */
|
||||
for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
|
||||
{
|
||||
memcpy (&(pixels[j]), &ptr[4*(int)offset], width);
|
||||
offset += a;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (tmp));
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_multi_horizontal (int width, int height,
|
||||
const GdkRGBA *colors,
|
||||
int count)
|
||||
{
|
||||
int i, j, k;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int width2;
|
||||
int rowstride;
|
||||
|
||||
g_return_val_if_fail (count > 2, NULL);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
ptr = pixels;
|
||||
|
||||
if (count > width)
|
||||
count = width;
|
||||
|
||||
if (count > 1)
|
||||
width2 = width/(count-1);
|
||||
else
|
||||
width2 = width;
|
||||
|
||||
k = 0;
|
||||
|
||||
r = (long)(colors[0].red * 0xffffff);
|
||||
g = (long)(colors[0].green * 0xffffff);
|
||||
b = (long)(colors[0].blue * 0xffffff);
|
||||
a = (long)(colors[0].alpha * 0xffffff);
|
||||
|
||||
/* render the first line */
|
||||
for (i=1; i<count; i++)
|
||||
{
|
||||
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
|
||||
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
|
||||
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
|
||||
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)width2;
|
||||
for (j=0; j<width2; j++)
|
||||
{
|
||||
*ptr++ = (unsigned char)(r>>16);
|
||||
*ptr++ = (unsigned char)(g>>16);
|
||||
*ptr++ = (unsigned char)(b>>16);
|
||||
*ptr++ = (unsigned char)(a>>16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
k++;
|
||||
}
|
||||
r = (long)(colors[i].red * 0xffffff);
|
||||
g = (long)(colors[i].green * 0xffffff);
|
||||
b = (long)(colors[i].blue * 0xffffff);
|
||||
a = (long)(colors[i].alpha * 0xffffff);
|
||||
}
|
||||
for (j=k; j<width; j++)
|
||||
{
|
||||
*ptr++ = (unsigned char)(r>>16);
|
||||
*ptr++ = (unsigned char)(g>>16);
|
||||
*ptr++ = (unsigned char)(b>>16);
|
||||
*ptr++ = (unsigned char)(a>>16);
|
||||
}
|
||||
|
||||
/* copy the first line to the other lines */
|
||||
for (i=1; i<height; i++)
|
||||
{
|
||||
memcpy (&(pixels[i*rowstride]), pixels, rowstride);
|
||||
}
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_multi_vertical (int width, int height,
|
||||
const GdkRGBA *colors,
|
||||
int count)
|
||||
{
|
||||
int i, j, k;
|
||||
long r, g, b, a, dr, dg, db, da;
|
||||
GdkPixbuf *pixbuf;
|
||||
unsigned char *ptr, *tmp, *pixels;
|
||||
int height2;
|
||||
int x;
|
||||
int rowstride;
|
||||
|
||||
g_return_val_if_fail (count > 2, NULL);
|
||||
|
||||
pixbuf = blank_pixbuf (width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
ptr = pixels;
|
||||
|
||||
if (count > height)
|
||||
count = height;
|
||||
|
||||
if (count > 1)
|
||||
height2 = height/(count-1);
|
||||
else
|
||||
height2 = height;
|
||||
|
||||
k = 0;
|
||||
|
||||
r = (long)(colors[0].red * 0xffffff);
|
||||
g = (long)(colors[0].green * 0xffffff);
|
||||
b = (long)(colors[0].blue * 0xffffff);
|
||||
a = (long)(colors[0].alpha * 0xffffff);
|
||||
|
||||
for (i=1; i<count; i++)
|
||||
{
|
||||
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
|
||||
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
|
||||
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
|
||||
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)height2;
|
||||
|
||||
for (j=0; j<height2; j++)
|
||||
{
|
||||
ptr[0] = (unsigned char)(r>>16);
|
||||
ptr[1] = (unsigned char)(g>>16);
|
||||
ptr[2] = (unsigned char)(b>>16);
|
||||
ptr[3] = (unsigned char)(a>>16);
|
||||
|
||||
for (x=1; x <= width/2; x *= 2)
|
||||
memcpy (&(ptr[x*4]), ptr, x*4);
|
||||
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
|
||||
|
||||
ptr += rowstride;
|
||||
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
a += da;
|
||||
k++;
|
||||
}
|
||||
r = (long)(colors[i].red * 0xffffff);
|
||||
g = (long)(colors[i].green * 0xffffff);
|
||||
b = (long)(colors[i].blue * 0xffffff);
|
||||
a = (long)(colors[i].alpha * 0xffffff);
|
||||
}
|
||||
|
||||
if (k<height)
|
||||
{
|
||||
tmp = ptr;
|
||||
|
||||
ptr[0] = (unsigned char) (r>>16);
|
||||
ptr[1] = (unsigned char) (g>>16);
|
||||
ptr[2] = (unsigned char) (b>>16);
|
||||
ptr[3] = (unsigned char) (a>>16);
|
||||
|
||||
for (x=1; x <= width/2; x *= 2)
|
||||
memcpy (&(ptr[x*4]), ptr, x*4);
|
||||
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
|
||||
|
||||
ptr += rowstride;
|
||||
|
||||
for (j=k+1; j<height; j++)
|
||||
{
|
||||
memcpy (ptr, tmp, rowstride);
|
||||
ptr += rowstride;
|
||||
}
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
|
||||
static GdkPixbuf*
|
||||
meta_gradient_create_multi_diagonal (int width, int height,
|
||||
const GdkRGBA *colors,
|
||||
int count)
|
||||
{
|
||||
GdkPixbuf *pixbuf, *tmp;
|
||||
float a, offset;
|
||||
int j;
|
||||
unsigned char *ptr;
|
||||
unsigned char *pixels;
|
||||
int rowstride;
|
||||
|
||||
g_return_val_if_fail (count > 2, NULL);
|
||||
|
||||
if (width == 1)
|
||||
return meta_gradient_create_multi_vertical (width, height, colors, count);
|
||||
else if (height == 1)
|
||||
return meta_gradient_create_multi_horizontal (width, height, colors, count);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
|
||||
width, height);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
if (count > width)
|
||||
count = width;
|
||||
if (count > height)
|
||||
count = height;
|
||||
|
||||
if (count > 2)
|
||||
tmp = meta_gradient_create_multi_horizontal (2*width-1, 1, colors, count);
|
||||
else
|
||||
/* wrlib multiplies these colors by 256 before passing them in, but
|
||||
* I think it's a bug in wrlib, so changed here. I could be wrong
|
||||
* though, if we notice two-color multi diagonals not working.
|
||||
*/
|
||||
tmp = meta_gradient_create_horizontal (2*width-1, 1,
|
||||
&colors[0], &colors[1]);
|
||||
|
||||
if (!tmp)
|
||||
{
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
return NULL;
|
||||
}
|
||||
ptr = gdk_pixbuf_get_pixels (tmp);
|
||||
|
||||
a = ((float)(width - 1))/((float)(height - 1));
|
||||
width = width * 3;
|
||||
|
||||
/* copy the first line to the other lines with corresponding offset */
|
||||
for (j=0, offset=0; j<rowstride*height; j += rowstride)
|
||||
{
|
||||
memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
|
||||
offset += a;
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (tmp));
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
simple_multiply_alpha (GdkPixbuf *pixbuf,
|
||||
guchar alpha)
|
||||
{
|
||||
guchar *pixels;
|
||||
int rowstride;
|
||||
int height;
|
||||
int row;
|
||||
|
||||
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
|
||||
|
||||
if (alpha == 255)
|
||||
return;
|
||||
|
||||
g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
row = 0;
|
||||
while (row < height)
|
||||
{
|
||||
guchar *p;
|
||||
guchar *end;
|
||||
|
||||
p = pixels + row * rowstride;
|
||||
end = p + rowstride;
|
||||
|
||||
while (p != end)
|
||||
{
|
||||
p += 3; /* skip RGB */
|
||||
|
||||
/* multiply the two alpha channels. not sure this is right.
|
||||
* but some end cases are that if the pixbuf contains 255,
|
||||
* then it should be modified to contain "alpha"; if the
|
||||
* pixbuf contains 0, it should remain 0.
|
||||
*/
|
||||
/* ((*p / 255.0) * (alpha / 255.0)) * 255; */
|
||||
*p = (guchar) (((int) *p * (int) alpha) / (int) 255);
|
||||
|
||||
++p; /* skip A */
|
||||
}
|
||||
|
||||
++row;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gradient_add_alpha_horizontal (GdkPixbuf *pixbuf,
|
||||
const unsigned char *alphas,
|
||||
int n_alphas)
|
||||
{
|
||||
int i, j;
|
||||
long a, da;
|
||||
unsigned char *p;
|
||||
unsigned char *pixels;
|
||||
int width2;
|
||||
int rowstride;
|
||||
int width, height;
|
||||
unsigned char *gradient;
|
||||
unsigned char *gradient_p;
|
||||
unsigned char *gradient_end;
|
||||
|
||||
g_return_if_fail (n_alphas > 0);
|
||||
|
||||
if (n_alphas == 1)
|
||||
{
|
||||
/* Optimize this */
|
||||
simple_multiply_alpha (pixbuf, alphas[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
|
||||
gradient = g_new (unsigned char, width);
|
||||
gradient_end = gradient + width;
|
||||
|
||||
if (n_alphas > width)
|
||||
n_alphas = width;
|
||||
|
||||
if (n_alphas > 1)
|
||||
width2 = width / (n_alphas - 1);
|
||||
else
|
||||
width2 = width;
|
||||
|
||||
a = alphas[0] << 8;
|
||||
gradient_p = gradient;
|
||||
|
||||
/* render the gradient into an array */
|
||||
for (i = 1; i < n_alphas; i++)
|
||||
{
|
||||
da = (((int)(alphas[i] - (int) alphas[i-1])) << 8) / (int) width2;
|
||||
|
||||
for (j = 0; j < width2; j++)
|
||||
{
|
||||
*gradient_p++ = (a >> 8);
|
||||
|
||||
a += da;
|
||||
}
|
||||
|
||||
a = alphas[i] << 8;
|
||||
}
|
||||
|
||||
/* get leftover pixels */
|
||||
while (gradient_p != gradient_end)
|
||||
{
|
||||
*gradient_p++ = a >> 8;
|
||||
}
|
||||
|
||||
/* Now for each line of the pixbuf, fill in with the gradient */
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
|
||||
p = pixels;
|
||||
i = 0;
|
||||
while (i < height)
|
||||
{
|
||||
unsigned char *row_end = p + rowstride;
|
||||
gradient_p = gradient;
|
||||
|
||||
p += 3;
|
||||
while (gradient_p != gradient_end)
|
||||
{
|
||||
/* multiply the two alpha channels. not sure this is right.
|
||||
* but some end cases are that if the pixbuf contains 255,
|
||||
* then it should be modified to contain "alpha"; if the
|
||||
* pixbuf contains 0, it should remain 0.
|
||||
*/
|
||||
/* ((*p / 255.0) * (alpha / 255.0)) * 255; */
|
||||
*p = (guchar) (((int) *p * (int) *gradient_p) / (int) 255);
|
||||
|
||||
p += 4;
|
||||
++gradient_p;
|
||||
}
|
||||
|
||||
p = row_end;
|
||||
++i;
|
||||
}
|
||||
|
||||
g_free (gradient);
|
||||
}
|
||||
|
||||
void
|
||||
meta_gradient_add_alpha (GdkPixbuf *pixbuf,
|
||||
const guchar *alphas,
|
||||
int n_alphas,
|
||||
MetaGradientType type)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
|
||||
g_return_if_fail (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
g_return_if_fail (n_alphas > 0);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case META_GRADIENT_HORIZONTAL:
|
||||
meta_gradient_add_alpha_horizontal (pixbuf, alphas, n_alphas);
|
||||
break;
|
||||
|
||||
case META_GRADIENT_VERTICAL:
|
||||
g_printerr ("metacity: vertical alpha channel gradient not implemented yet\n");
|
||||
break;
|
||||
|
||||
case META_GRADIENT_DIAGONAL:
|
||||
g_printerr ("metacity: diagonal alpha channel gradient not implemented yet\n");
|
||||
break;
|
||||
|
||||
case META_GRADIENT_LAST:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
315
src/ui/testgradient.c
Normal file
315
src/ui/testgradient.c
Normal file
@ -0,0 +1,315 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter gradient test program */
|
||||
|
||||
/*
|
||||
* 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <meta/gradient.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef void (* RenderGradientFunc) (cairo_t *cr,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void
|
||||
draw_checkerboard (cairo_t *cr,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
gint i, j, xcount, ycount;
|
||||
GdkRGBA color1, color2;
|
||||
|
||||
#define CHECK_SIZE 10
|
||||
#define SPACING 2
|
||||
|
||||
color1.red = 30000. / 65535.;
|
||||
color1.green = 30000. / 65535.;
|
||||
color1.blue = 30000. / 65535.;
|
||||
color1.alpha = 1.0;
|
||||
|
||||
color2.red = 50000. / 65535.;
|
||||
color2.green = 50000. / 65535.;
|
||||
color2.blue = 50000. / 65535.;
|
||||
color2.alpha = 1.0;
|
||||
|
||||
xcount = 0;
|
||||
i = SPACING;
|
||||
while (i < width)
|
||||
{
|
||||
j = SPACING;
|
||||
ycount = xcount % 2; /* start with even/odd depending on row */
|
||||
while (j < height)
|
||||
{
|
||||
if (ycount % 2)
|
||||
gdk_cairo_set_source_rgba (cr, &color1);
|
||||
else
|
||||
gdk_cairo_set_source_rgba (cr, &color2);
|
||||
|
||||
/* If we're outside event->area, this will do nothing.
|
||||
* It might be mildly more efficient if we handled
|
||||
* the clipping ourselves, but again we're feeling lazy.
|
||||
*/
|
||||
cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
|
||||
cairo_fill (cr);
|
||||
|
||||
j += CHECK_SIZE + SPACING;
|
||||
++ycount;
|
||||
}
|
||||
|
||||
i += CHECK_SIZE + SPACING;
|
||||
++xcount;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_simple (cairo_t *cr,
|
||||
int width, int height,
|
||||
MetaGradientType type,
|
||||
gboolean with_alpha)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkRGBA from, to;
|
||||
|
||||
gdk_rgba_parse (&from, "blue");
|
||||
gdk_rgba_parse (&to, "green");
|
||||
|
||||
pixbuf = meta_gradient_create_simple (width, height,
|
||||
&from, &to,
|
||||
type);
|
||||
|
||||
if (with_alpha)
|
||||
{
|
||||
const unsigned char alphas[] = { 0xff, 0xaa, 0x2f, 0x0, 0xcc, 0xff, 0xff };
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
GdkPixbuf *new_pixbuf;
|
||||
|
||||
new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
pixbuf = new_pixbuf;
|
||||
}
|
||||
|
||||
meta_gradient_add_alpha (pixbuf,
|
||||
alphas, G_N_ELEMENTS (alphas),
|
||||
META_GRADIENT_HORIZONTAL);
|
||||
|
||||
draw_checkerboard (cr , width, height);
|
||||
}
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
|
||||
static void
|
||||
render_vertical_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (cr, width, height, META_GRADIENT_VERTICAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
render_horizontal_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (cr, width, height, META_GRADIENT_HORIZONTAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
render_diagonal_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (cr, width, height, META_GRADIENT_DIAGONAL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
render_diagonal_alpha_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_simple (cr, width, height, META_GRADIENT_DIAGONAL, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
render_multi (cairo_t *cr,
|
||||
int width, int height,
|
||||
MetaGradientType type)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
#define N_COLORS 5
|
||||
GdkRGBA colors[N_COLORS];
|
||||
|
||||
gdk_rgba_parse (&colors[0], "red");
|
||||
gdk_rgba_parse (&colors[1], "blue");
|
||||
gdk_rgba_parse (&colors[2], "orange");
|
||||
gdk_rgba_parse (&colors[3], "pink");
|
||||
gdk_rgba_parse (&colors[4], "green");
|
||||
|
||||
pixbuf = meta_gradient_create_multi (width, height,
|
||||
colors, N_COLORS,
|
||||
type);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
#undef N_COLORS
|
||||
}
|
||||
|
||||
static void
|
||||
render_vertical_multi_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_multi (cr, width, height, META_GRADIENT_VERTICAL);
|
||||
}
|
||||
|
||||
static void
|
||||
render_horizontal_multi_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_multi (cr, width, height, META_GRADIENT_HORIZONTAL);
|
||||
}
|
||||
|
||||
static void
|
||||
render_diagonal_multi_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
render_multi (cr, width, height, META_GRADIENT_DIAGONAL);
|
||||
}
|
||||
|
||||
static void
|
||||
render_interwoven_func (cairo_t *cr,
|
||||
int width, int height)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
#define N_COLORS 4
|
||||
GdkRGBA colors[N_COLORS];
|
||||
|
||||
gdk_rgba_parse (&colors[0], "red");
|
||||
gdk_rgba_parse (&colors[1], "blue");
|
||||
gdk_rgba_parse (&colors[2], "pink");
|
||||
gdk_rgba_parse (&colors[3], "green");
|
||||
|
||||
pixbuf = meta_gradient_create_interwoven (width, height,
|
||||
colors, height / 10,
|
||||
colors + 2, height / 14);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
draw_callback (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer data)
|
||||
{
|
||||
RenderGradientFunc func = data;
|
||||
GtkStyleContext *style;
|
||||
GdkRGBA color;
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_save (style);
|
||||
gtk_style_context_set_state (style, gtk_widget_get_state_flags (widget));
|
||||
gtk_style_context_lookup_color (style, "foreground-color", &color);
|
||||
gtk_style_context_restore (style);
|
||||
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
(* func) (cr,
|
||||
gtk_widget_get_allocated_width (widget),
|
||||
gtk_widget_get_allocated_height (widget));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
create_gradient_window (const char *title,
|
||||
RenderGradientFunc func)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *drawing_area;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (window), title);
|
||||
|
||||
drawing_area = gtk_drawing_area_new ();
|
||||
|
||||
gtk_widget_set_size_request (drawing_area, 1, 1);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 175, 175);
|
||||
|
||||
g_signal_connect (G_OBJECT (drawing_area),
|
||||
"draw",
|
||||
G_CALLBACK (draw_callback),
|
||||
func);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), drawing_area);
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gradient_test (void)
|
||||
{
|
||||
create_gradient_window ("Simple vertical",
|
||||
render_vertical_func);
|
||||
|
||||
create_gradient_window ("Simple horizontal",
|
||||
render_horizontal_func);
|
||||
|
||||
create_gradient_window ("Simple diagonal",
|
||||
render_diagonal_func);
|
||||
|
||||
create_gradient_window ("Multi vertical",
|
||||
render_vertical_multi_func);
|
||||
|
||||
create_gradient_window ("Multi horizontal",
|
||||
render_horizontal_multi_func);
|
||||
|
||||
create_gradient_window ("Multi diagonal",
|
||||
render_diagonal_multi_func);
|
||||
|
||||
create_gradient_window ("Interwoven",
|
||||
render_interwoven_func);
|
||||
|
||||
create_gradient_window ("Simple diagonal with horizontal multi alpha",
|
||||
render_diagonal_alpha_func);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
meta_gradient_test ();
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -774,6 +774,9 @@ parse_alpha (const char *str,
|
||||
|
||||
n_alphas = i;
|
||||
|
||||
/* FIXME allow specifying horizontal/vertical/diagonal in theme format,
|
||||
* once we implement vertical/diagonal in gradient.c
|
||||
*/
|
||||
spec = meta_alpha_gradient_spec_new (META_GRADIENT_HORIZONTAL,
|
||||
n_alphas);
|
||||
|
||||
@ -2147,9 +2150,11 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
const char *width;
|
||||
const char *height;
|
||||
const char *alpha;
|
||||
const char *colorize;
|
||||
const char *fill_type;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
GdkPixbuf *pixbuf;
|
||||
MetaColorSpec *colorize_spec = NULL;
|
||||
MetaImageFillType fill_type_val;
|
||||
int h, w, c;
|
||||
int pixbuf_width, pixbuf_height, pixbuf_n_channels, pixbuf_rowstride;
|
||||
@ -2160,6 +2165,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
"!x", &x, "!y", &y,
|
||||
"!width", &width, "!height", &height,
|
||||
"alpha", &alpha, "!filename", &filename,
|
||||
"colorize", &colorize,
|
||||
"fill_type", &fill_type,
|
||||
NULL))
|
||||
return;
|
||||
@ -2205,6 +2211,18 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
return;
|
||||
}
|
||||
|
||||
if (colorize)
|
||||
{
|
||||
colorize_spec = parse_color (info->theme, colorize, error);
|
||||
|
||||
if (colorize_spec == NULL)
|
||||
{
|
||||
add_context_to_error (error, context);
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
alpha_spec = NULL;
|
||||
if (alpha && !parse_alpha (alpha, &alpha_spec, context, error))
|
||||
{
|
||||
@ -2215,6 +2233,7 @@ parse_draw_op_element (GMarkupParseContext *context,
|
||||
op = meta_draw_op_new (META_DRAW_IMAGE);
|
||||
|
||||
op->data.image.pixbuf = pixbuf;
|
||||
op->data.image.colorize_spec = colorize_spec;
|
||||
|
||||
op->data.image.x = meta_draw_spec_new (info->theme, x, NULL);
|
||||
op->data.image.y = meta_draw_spec_new (info->theme, y, NULL);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define META_THEME_PRIVATE_H
|
||||
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/gradient.h>
|
||||
#include <meta/theme.h>
|
||||
#include <meta/common.h>
|
||||
#include <gtk/gtk.h>
|
||||
@ -272,14 +273,6 @@ typedef enum
|
||||
META_IMAGE_FILL_TILE
|
||||
} MetaImageFillType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_GRADIENT_VERTICAL,
|
||||
META_GRADIENT_HORIZONTAL,
|
||||
META_GRADIENT_DIAGONAL,
|
||||
META_GRADIENT_LAST
|
||||
} MetaGradientType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_COLOR_SPEC_BASIC,
|
||||
@ -545,6 +538,7 @@ struct _MetaDrawOp
|
||||
} gradient;
|
||||
|
||||
struct {
|
||||
MetaColorSpec *colorize_spec;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
GdkPixbuf *pixbuf;
|
||||
MetaDrawSpec *x;
|
||||
@ -552,6 +546,8 @@ struct _MetaDrawOp
|
||||
MetaDrawSpec *width;
|
||||
MetaDrawSpec *height;
|
||||
|
||||
guint32 colorize_cache_pixel;
|
||||
GdkPixbuf *colorize_cache_pixbuf;
|
||||
MetaImageFillType fill_type;
|
||||
unsigned int vertical_stripes : 1;
|
||||
unsigned int horizontal_stripes : 1;
|
||||
@ -976,12 +972,8 @@ gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list,
|
||||
|
||||
MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type);
|
||||
void meta_gradient_spec_free (MetaGradientSpec *desc);
|
||||
void meta_gradient_spec_render (const MetaGradientSpec *spec,
|
||||
const MetaAlphaGradientSpec *alpha_spec,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *style,
|
||||
int x,
|
||||
int y,
|
||||
GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
|
||||
GtkStyleContext *gtk_style,
|
||||
int width,
|
||||
int height);
|
||||
gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
|
||||
|
760
src/ui/theme.c
760
src/ui/theme.c
@ -38,6 +38,7 @@
|
||||
#include "theme-private.h"
|
||||
#include "frames.h" /* for META_TYPE_FRAMES */
|
||||
#include "util-private.h"
|
||||
#include <meta/gradient.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
@ -74,6 +75,84 @@ static void hls_to_rgb (gdouble *h,
|
||||
*/
|
||||
static MetaTheme *meta_current_theme = NULL;
|
||||
|
||||
static GdkPixbuf *
|
||||
colorize_pixbuf (GdkPixbuf *orig,
|
||||
GdkRGBA *new_color)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
double intensity;
|
||||
int x, y;
|
||||
const guchar *src;
|
||||
guchar *dest;
|
||||
int orig_rowstride;
|
||||
int dest_rowstride;
|
||||
int width, height;
|
||||
gboolean has_alpha;
|
||||
const guchar *src_pixels;
|
||||
guchar *dest_pixels;
|
||||
|
||||
pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig),
|
||||
gdk_pixbuf_get_bits_per_sample (orig),
|
||||
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
|
||||
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
orig_rowstride = gdk_pixbuf_get_rowstride (orig);
|
||||
dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
||||
width = gdk_pixbuf_get_width (pixbuf);
|
||||
height = gdk_pixbuf_get_height (pixbuf);
|
||||
has_alpha = gdk_pixbuf_get_has_alpha (orig);
|
||||
src_pixels = gdk_pixbuf_get_pixels (orig);
|
||||
dest_pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src = src_pixels + y * orig_rowstride;
|
||||
dest = dest_pixels + y * dest_rowstride;
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
double dr, dg, db;
|
||||
|
||||
intensity = INTENSITY (src[0], src[1], src[2]) / 255.0;
|
||||
|
||||
if (intensity <= 0.5)
|
||||
{
|
||||
/* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */
|
||||
dr = new_color->red * intensity * 2.0;
|
||||
dg = new_color->green * intensity * 2.0;
|
||||
db = new_color->blue * intensity * 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Go from new_color at intensity = 0.5 to white at intensity = 1.0 */
|
||||
dr = new_color->red + (1.0 - new_color->red) * (intensity - 0.5) * 2.0;
|
||||
dg = new_color->green + (1.0 - new_color->green) * (intensity - 0.5) * 2.0;
|
||||
db = new_color->blue + (1.0 - new_color->blue) * (intensity - 0.5) * 2.0;
|
||||
}
|
||||
|
||||
dest[0] = CLAMP_UCHAR (255 * dr);
|
||||
dest[1] = CLAMP_UCHAR (255 * dg);
|
||||
dest[2] = CLAMP_UCHAR (255 * db);
|
||||
|
||||
if (has_alpha)
|
||||
{
|
||||
dest[3] = src[3];
|
||||
src += 4;
|
||||
dest += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
src += 3;
|
||||
dest += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
color_composite (const GdkRGBA *bg,
|
||||
const GdkRGBA *fg,
|
||||
@ -931,84 +1010,42 @@ meta_gradient_spec_free (MetaGradientSpec *spec)
|
||||
g_free (spec);
|
||||
}
|
||||
|
||||
static cairo_pattern_t *
|
||||
meta_gradient_spec_pattern (const MetaGradientSpec *spec,
|
||||
const MetaAlphaGradientSpec *alpha_spec,
|
||||
GtkStyleContext *style)
|
||||
GdkPixbuf*
|
||||
meta_gradient_spec_render (const MetaGradientSpec *spec,
|
||||
GtkStyleContext *style,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
int n_colors;
|
||||
GSList *l;
|
||||
GdkRGBA *colors;
|
||||
GSList *tmp;
|
||||
int i;
|
||||
|
||||
if (spec->type == META_GRADIENT_HORIZONTAL)
|
||||
pattern = cairo_pattern_create_linear (0, 0, 1, 0);
|
||||
if (spec->type == META_GRADIENT_VERTICAL)
|
||||
pattern = cairo_pattern_create_linear (0, 0, 0, 1);
|
||||
else if (spec->type == META_GRADIENT_DIAGONAL)
|
||||
pattern = cairo_pattern_create_linear (0, 0, 1, 1);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
n_colors = g_slist_length (spec->color_specs);
|
||||
|
||||
if (n_colors == 0)
|
||||
return NULL;
|
||||
|
||||
if (alpha_spec != NULL)
|
||||
g_assert (n_colors == alpha_spec->n_alphas);
|
||||
colors = g_new (GdkRGBA, n_colors);
|
||||
|
||||
i = 0;
|
||||
for (l = spec->color_specs; l != NULL; l = l->next)
|
||||
tmp = spec->color_specs;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaColorSpec *color_spec = l->data;
|
||||
GdkRGBA color;
|
||||
meta_color_spec_render (tmp->data, style, &colors[i]);
|
||||
|
||||
meta_color_spec_render (color_spec, style, &color);
|
||||
|
||||
if (alpha_spec != NULL)
|
||||
color.alpha *= alpha_spec->alphas[i];
|
||||
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
i / (float) n_colors,
|
||||
color.red,
|
||||
color.green,
|
||||
color.blue,
|
||||
color.alpha);
|
||||
tmp = tmp->next;
|
||||
++i;
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
pixbuf = meta_gradient_create_multi (width, height,
|
||||
colors, n_colors,
|
||||
spec->type);
|
||||
|
||||
void
|
||||
meta_gradient_spec_render (const MetaGradientSpec *spec,
|
||||
const MetaAlphaGradientSpec *alpha_spec,
|
||||
cairo_t *cr,
|
||||
GtkStyleContext *style,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
g_free (colors);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
pattern = meta_gradient_spec_pattern (spec, alpha_spec, style);
|
||||
if (pattern == NULL)
|
||||
return;
|
||||
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
|
||||
cairo_translate (cr, x, y);
|
||||
cairo_scale (cr, width, height);
|
||||
|
||||
cairo_set_source (cr, pattern);
|
||||
cairo_fill (cr);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_restore (cr);
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -3015,6 +3052,12 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
if (op->data.image.pixbuf)
|
||||
g_object_unref (G_OBJECT (op->data.image.pixbuf));
|
||||
|
||||
if (op->data.image.colorize_spec)
|
||||
meta_color_spec_free (op->data.image.colorize_spec);
|
||||
|
||||
if (op->data.image.colorize_cache_pixbuf)
|
||||
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
|
||||
|
||||
meta_draw_spec_free (op->data.image.x);
|
||||
meta_draw_spec_free (op->data.image.y);
|
||||
meta_draw_spec_free (op->data.image.width);
|
||||
@ -3089,6 +3132,413 @@ meta_draw_op_free (MetaDrawOp *op)
|
||||
g_free (op);
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
apply_alpha (GdkPixbuf *pixbuf,
|
||||
MetaAlphaGradientSpec *spec,
|
||||
gboolean force_copy)
|
||||
{
|
||||
GdkPixbuf *new_pixbuf;
|
||||
gboolean needs_alpha;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
needs_alpha = spec && (spec->n_alphas > 1 ||
|
||||
spec->alphas[0] != 0xff);
|
||||
|
||||
if (!needs_alpha)
|
||||
return pixbuf;
|
||||
|
||||
if (!gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
new_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
pixbuf = new_pixbuf;
|
||||
}
|
||||
else if (force_copy)
|
||||
{
|
||||
new_pixbuf = gdk_pixbuf_copy (pixbuf);
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
pixbuf = new_pixbuf;
|
||||
}
|
||||
|
||||
g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
|
||||
|
||||
meta_gradient_add_alpha (pixbuf, spec->alphas, spec->n_alphas, spec->type);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
pixbuf_tile (GdkPixbuf *tile,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
int tile_width;
|
||||
int tile_height;
|
||||
int i, j;
|
||||
|
||||
tile_width = gdk_pixbuf_get_width (tile);
|
||||
tile_height = gdk_pixbuf_get_height (tile);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
gdk_pixbuf_get_has_alpha (tile),
|
||||
8, width, height);
|
||||
|
||||
i = 0;
|
||||
while (i < width)
|
||||
{
|
||||
j = 0;
|
||||
while (j < height)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
w = MIN (tile_width, width - i);
|
||||
h = MIN (tile_height, height - j);
|
||||
|
||||
gdk_pixbuf_copy_area (tile,
|
||||
0, 0,
|
||||
w, h,
|
||||
pixbuf,
|
||||
i, j);
|
||||
|
||||
j += tile_height;
|
||||
}
|
||||
|
||||
i += tile_width;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
replicate_rows (GdkPixbuf *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
|
||||
unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
|
||||
unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
|
||||
* n_channels);
|
||||
unsigned char *dest_pixels;
|
||||
GdkPixbuf *result;
|
||||
unsigned int dest_rowstride;
|
||||
int i;
|
||||
|
||||
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
|
||||
width, height);
|
||||
dest_rowstride = gdk_pixbuf_get_rowstride (result);
|
||||
dest_pixels = gdk_pixbuf_get_pixels (result);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
replicate_cols (GdkPixbuf *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
unsigned int n_channels = gdk_pixbuf_get_n_channels (src);
|
||||
unsigned int src_rowstride = gdk_pixbuf_get_rowstride (src);
|
||||
unsigned char *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x
|
||||
* n_channels);
|
||||
unsigned char *dest_pixels;
|
||||
GdkPixbuf *result;
|
||||
unsigned int dest_rowstride;
|
||||
int i, j;
|
||||
|
||||
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
|
||||
width, height);
|
||||
dest_rowstride = gdk_pixbuf_get_rowstride (result);
|
||||
dest_pixels = gdk_pixbuf_get_pixels (result);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
unsigned char *p = dest_pixels + dest_rowstride * i;
|
||||
unsigned char *q = pixels + src_rowstride * i;
|
||||
|
||||
unsigned char r = *(q++);
|
||||
unsigned char g = *(q++);
|
||||
unsigned char b = *(q++);
|
||||
|
||||
if (n_channels == 4)
|
||||
{
|
||||
unsigned char a;
|
||||
|
||||
a = *(q++);
|
||||
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
*(p++) = r;
|
||||
*(p++) = g;
|
||||
*(p++) = b;
|
||||
*(p++) = a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < width; j++)
|
||||
{
|
||||
*(p++) = r;
|
||||
*(p++) = g;
|
||||
*(p++) = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
scale_and_alpha_pixbuf (GdkPixbuf *src,
|
||||
MetaAlphaGradientSpec *alpha_spec,
|
||||
MetaImageFillType fill_type,
|
||||
int width,
|
||||
int height,
|
||||
gboolean vertical_stripes,
|
||||
gboolean horizontal_stripes)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *temp_pixbuf;
|
||||
|
||||
pixbuf = NULL;
|
||||
|
||||
pixbuf = src;
|
||||
|
||||
if (gdk_pixbuf_get_width (pixbuf) == width &&
|
||||
gdk_pixbuf_get_height (pixbuf) == height)
|
||||
{
|
||||
g_object_ref (G_OBJECT (pixbuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fill_type == META_IMAGE_FILL_TILE)
|
||||
{
|
||||
pixbuf = pixbuf_tile (pixbuf, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
int src_h, src_w, dest_h, dest_w;
|
||||
src_h = gdk_pixbuf_get_height (src);
|
||||
src_w = gdk_pixbuf_get_width (src);
|
||||
|
||||
/* prefer to replicate_cols if possible, as that
|
||||
* is faster (no memory reads)
|
||||
*/
|
||||
if (horizontal_stripes)
|
||||
{
|
||||
dest_w = gdk_pixbuf_get_width (src);
|
||||
dest_h = height;
|
||||
}
|
||||
else if (vertical_stripes)
|
||||
{
|
||||
dest_w = width;
|
||||
dest_h = gdk_pixbuf_get_height (src);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
dest_w = width;
|
||||
dest_h = height;
|
||||
}
|
||||
|
||||
if (dest_w == src_w && dest_h == src_h)
|
||||
{
|
||||
temp_pixbuf = src;
|
||||
g_object_ref (G_OBJECT (temp_pixbuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_pixbuf = gdk_pixbuf_scale_simple (src,
|
||||
dest_w, dest_h,
|
||||
GDK_INTERP_BILINEAR);
|
||||
}
|
||||
|
||||
/* prefer to replicate_cols if possible, as that
|
||||
* is faster (no memory reads)
|
||||
*/
|
||||
if (horizontal_stripes)
|
||||
{
|
||||
pixbuf = replicate_cols (temp_pixbuf, 0, 0, width, height);
|
||||
g_object_unref (G_OBJECT (temp_pixbuf));
|
||||
}
|
||||
else if (vertical_stripes)
|
||||
{
|
||||
pixbuf = replicate_rows (temp_pixbuf, 0, 0, width, height);
|
||||
g_object_unref (G_OBJECT (temp_pixbuf));
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = temp_pixbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pixbuf)
|
||||
pixbuf = apply_alpha (pixbuf, alpha_spec, pixbuf == src);
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
draw_op_as_pixbuf (const MetaDrawOp *op,
|
||||
GtkStyleContext *context,
|
||||
const MetaDrawInfo *info,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
/* Try to get the op as a pixbuf, assuming w/h in the op
|
||||
* matches the width/height passed in. return NULL
|
||||
* if the op can't be converted to an equivalent pixbuf.
|
||||
*/
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
pixbuf = NULL;
|
||||
|
||||
switch (op->type)
|
||||
{
|
||||
case META_DRAW_TINT:
|
||||
{
|
||||
GdkRGBA color;
|
||||
guint32 rgba;
|
||||
gboolean has_alpha;
|
||||
|
||||
meta_color_spec_render (op->data.rectangle.color_spec,
|
||||
context,
|
||||
&color);
|
||||
|
||||
has_alpha =
|
||||
op->data.tint.alpha_spec &&
|
||||
(op->data.tint.alpha_spec->n_alphas > 1 ||
|
||||
op->data.tint.alpha_spec->alphas[0] != 0xff);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
has_alpha,
|
||||
8, width, height);
|
||||
|
||||
if (!has_alpha)
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
}
|
||||
else if (op->data.tint.alpha_spec->n_alphas == 1)
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
rgba &= ~0xff;
|
||||
rgba |= op->data.tint.alpha_spec->alphas[0];
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba = GDK_COLOR_RGBA (color);
|
||||
|
||||
gdk_pixbuf_fill (pixbuf, rgba);
|
||||
|
||||
meta_gradient_add_alpha (pixbuf,
|
||||
op->data.tint.alpha_spec->alphas,
|
||||
op->data.tint.alpha_spec->n_alphas,
|
||||
op->data.tint.alpha_spec->type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_GRADIENT:
|
||||
{
|
||||
pixbuf = meta_gradient_spec_render (op->data.gradient.gradient_spec,
|
||||
context, width, height);
|
||||
|
||||
pixbuf = apply_alpha (pixbuf,
|
||||
op->data.gradient.alpha_spec,
|
||||
FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_IMAGE:
|
||||
{
|
||||
if (op->data.image.colorize_spec)
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_color_spec_render (op->data.image.colorize_spec,
|
||||
context, &color);
|
||||
|
||||
if (op->data.image.colorize_cache_pixbuf == NULL ||
|
||||
op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color))
|
||||
{
|
||||
if (op->data.image.colorize_cache_pixbuf)
|
||||
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
|
||||
|
||||
/* const cast here */
|
||||
((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf =
|
||||
colorize_pixbuf (op->data.image.pixbuf,
|
||||
&color);
|
||||
((MetaDrawOp*)op)->data.image.colorize_cache_pixel =
|
||||
GDK_COLOR_RGB (color);
|
||||
}
|
||||
|
||||
if (op->data.image.colorize_cache_pixbuf)
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.colorize_cache_pixbuf,
|
||||
op->data.image.alpha_spec,
|
||||
op->data.image.fill_type,
|
||||
width, height,
|
||||
op->data.image.vertical_stripes,
|
||||
op->data.image.horizontal_stripes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
|
||||
op->data.image.alpha_spec,
|
||||
op->data.image.fill_type,
|
||||
width, height,
|
||||
op->data.image.vertical_stripes,
|
||||
op->data.image.horizontal_stripes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case META_DRAW_ICON:
|
||||
if (info->mini_icon &&
|
||||
width <= gdk_pixbuf_get_width (info->mini_icon) &&
|
||||
height <= gdk_pixbuf_get_height (info->mini_icon))
|
||||
pixbuf = scale_and_alpha_pixbuf (info->mini_icon,
|
||||
op->data.icon.alpha_spec,
|
||||
op->data.icon.fill_type,
|
||||
width, height,
|
||||
FALSE, FALSE);
|
||||
else if (info->icon)
|
||||
pixbuf = scale_and_alpha_pixbuf (info->icon,
|
||||
op->data.icon.alpha_spec,
|
||||
op->data.icon.fill_type,
|
||||
width, height,
|
||||
FALSE, FALSE);
|
||||
break;
|
||||
|
||||
case META_DRAW_LINE:
|
||||
case META_DRAW_RECTANGLE:
|
||||
case META_DRAW_ARC:
|
||||
case META_DRAW_CLIP:
|
||||
case META_DRAW_GTK_ARROW:
|
||||
case META_DRAW_GTK_BOX:
|
||||
case META_DRAW_GTK_VLINE:
|
||||
case META_DRAW_TITLE:
|
||||
case META_DRAW_OP_LIST:
|
||||
case META_DRAW_TILE:
|
||||
break;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_env (MetaPositionExprEnv *env,
|
||||
const MetaDrawInfo *info,
|
||||
@ -3128,86 +3578,6 @@ fill_env (MetaPositionExprEnv *env,
|
||||
env->theme = meta_current_theme;
|
||||
}
|
||||
|
||||
static cairo_pattern_t *
|
||||
meta_alpha_gradient_spec_pattern (const MetaAlphaGradientSpec *alpha_spec)
|
||||
{
|
||||
|
||||
/* Hardcoded in theme-parser.c */
|
||||
g_assert (alpha_spec->type == META_GRADIENT_HORIZONTAL);
|
||||
|
||||
int n_alphas = alpha_spec->n_alphas;
|
||||
if (n_alphas == 0)
|
||||
return NULL;
|
||||
else if (n_alphas == 1)
|
||||
return cairo_pattern_create_rgba (0, 0, 0, alpha_spec->alphas[0]);
|
||||
else
|
||||
{
|
||||
cairo_pattern_t *pattern = cairo_pattern_create_linear (0, 0, 1, 0);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_alphas; i++)
|
||||
cairo_pattern_add_color_stop_rgba (pattern,
|
||||
i / (float) n_alphas,
|
||||
0, 0, 0, alpha_spec->alphas[i]);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_image (cairo_t *cr,
|
||||
GdkPixbuf *src,
|
||||
MetaImageFillType fill_type,
|
||||
MetaAlphaGradientSpec *alpha_spec,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
|
||||
if (fill_type == META_IMAGE_FILL_TILE)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, src, 0, 0);
|
||||
|
||||
cairo_pattern_set_extend (cairo_get_source (cr),
|
||||
CAIRO_EXTEND_REPEAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
float pixbuf_width, pixbuf_height;
|
||||
|
||||
pixbuf_width = gdk_pixbuf_get_width (src);
|
||||
pixbuf_height = gdk_pixbuf_get_height (src);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr, x, y);
|
||||
cairo_scale (cr,
|
||||
pixbuf_width / width,
|
||||
pixbuf_height / height);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, src, 0, 0);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
if (alpha_spec)
|
||||
{
|
||||
cairo_translate (cr, x, y);
|
||||
cairo_scale (cr, width, height);
|
||||
|
||||
cairo_pattern_t *pattern = meta_alpha_gradient_spec_pattern (alpha_spec);
|
||||
cairo_mask (cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
/* This code was originally rendering anti-aliased using X primitives, and
|
||||
* now has been switched to draw anti-aliased using cairo. In general, the
|
||||
@ -3231,6 +3601,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
GdkRGBA color;
|
||||
|
||||
cairo_save (cr);
|
||||
gtk_style_context_save (style_gtk);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
@ -3388,63 +3759,94 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
case META_DRAW_TINT:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
gboolean needs_alpha;
|
||||
|
||||
needs_alpha = op->data.tint.alpha_spec &&
|
||||
(op->data.tint.alpha_spec->n_alphas > 1 ||
|
||||
op->data.tint.alpha_spec->alphas[0] != 0xff);
|
||||
|
||||
rx = parse_x_position_unchecked (op->data.tint.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.tint.y, env);
|
||||
rwidth = parse_size_unchecked (op->data.tint.width, env);
|
||||
rheight = parse_size_unchecked (op->data.tint.height, env);
|
||||
|
||||
meta_color_spec_render (op->data.tint.color_spec,
|
||||
style_gtk, &color);
|
||||
if (!needs_alpha)
|
||||
{
|
||||
meta_color_spec_render (op->data.tint.color_spec,
|
||||
style_gtk, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
if (op->data.tint.alpha_spec &&
|
||||
op->data.tint.alpha_spec->n_alphas == 1)
|
||||
color.alpha = op->data.tint.alpha_spec->alphas[0];
|
||||
cairo_rectangle (cr, rx, ry, rwidth, rheight);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
|
||||
cairo_rectangle (cr, rx, ry, rwidth, rheight);
|
||||
cairo_fill (cr);
|
||||
if (pixbuf)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_GRADIENT:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
rx = parse_x_position_unchecked (op->data.gradient.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.gradient.y, env);
|
||||
rwidth = parse_size_unchecked (op->data.gradient.width, env);
|
||||
rheight = parse_size_unchecked (op->data.gradient.height, env);
|
||||
|
||||
meta_gradient_spec_render (op->data.gradient.gradient_spec,
|
||||
op->data.gradient.alpha_spec,
|
||||
cr, style_gtk,
|
||||
rx, ry, rwidth, rheight);
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_IMAGE:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
if (op->data.image.pixbuf == NULL)
|
||||
break;
|
||||
|
||||
env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf);
|
||||
env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf);
|
||||
|
||||
rx = parse_x_position_unchecked (op->data.image.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.image.y, env);
|
||||
if (op->data.image.pixbuf)
|
||||
{
|
||||
env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf);
|
||||
env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf);
|
||||
}
|
||||
|
||||
rwidth = parse_size_unchecked (op->data.image.width, env);
|
||||
rheight = parse_size_unchecked (op->data.image.height, env);
|
||||
|
||||
draw_image (cr,
|
||||
op->data.image.pixbuf,
|
||||
op->data.image.fill_type,
|
||||
op->data.image.alpha_spec,
|
||||
rx, ry, rwidth, rheight);
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
rx = parse_x_position_unchecked (op->data.image.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.image.y, env);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3514,27 +3916,24 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
case META_DRAW_ICON:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
GdkPixbuf *src;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
rwidth = parse_size_unchecked (op->data.icon.width, env);
|
||||
rheight = parse_size_unchecked (op->data.icon.height, env);
|
||||
|
||||
if (info->mini_icon &&
|
||||
rwidth < gdk_pixbuf_get_width (info->mini_icon) &&
|
||||
rheight < gdk_pixbuf_get_height (info->mini_icon))
|
||||
src = info->mini_icon;
|
||||
else if (info->icon)
|
||||
src = info->icon;
|
||||
else
|
||||
break;
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
|
||||
rx = parse_x_position_unchecked (op->data.icon.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.icon.y, env);
|
||||
if (pixbuf)
|
||||
{
|
||||
rx = parse_x_position_unchecked (op->data.icon.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.icon.y, env);
|
||||
|
||||
draw_image (cr, src,
|
||||
op->data.icon.fill_type,
|
||||
op->data.icon.alpha_spec,
|
||||
rx, ry, rwidth, rheight);
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3654,6 +4053,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
gtk_style_context_restore (style_gtk);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -547,16 +547,9 @@ data_device_set_selection (struct wl_client *client,
|
||||
meta_wayland_data_device_set_selection (data_device, source, serial);
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct wl_data_device_interface data_device_interface = {
|
||||
data_device_start_drag,
|
||||
data_device_set_selection,
|
||||
data_device_release,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -75,14 +75,6 @@ compute_scale (MetaOutput *output)
|
||||
output->crtc->rect.width >= SMALLEST_4K_WIDTH)
|
||||
goto out;
|
||||
|
||||
/* Somebody encoded the aspect ratio (16/9 or 16/10)
|
||||
* instead of the physical size */
|
||||
if ((output->width_mm == 160 && output->height_mm == 90) ||
|
||||
(output->width_mm == 160 && output->height_mm == 100) ||
|
||||
(output->width_mm == 16 && output->height_mm == 9) ||
|
||||
(output->width_mm == 16 && output->height_mm == 10))
|
||||
goto out;
|
||||
|
||||
if (output->width_mm > 0 && output->height_mm > 0)
|
||||
{
|
||||
double dpi_x, dpi_y;
|
||||
|
@ -65,33 +65,6 @@ unbind_resource (struct wl_resource *resource)
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
sync_focus_surface (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
switch (display->event_route)
|
||||
{
|
||||
case META_EVENT_ROUTE_WINDOW_OP:
|
||||
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
|
||||
/* The compositor has a grab, so remove our focus... */
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
break;
|
||||
|
||||
case META_EVENT_ROUTE_NORMAL:
|
||||
case META_EVENT_ROUTE_WAYLAND_POPUP:
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
|
||||
interface->focus (pointer->grab, pointer->current);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
set_cursor_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
@ -206,7 +179,7 @@ default_grab_button (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
|
||||
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
|
||||
sync_focus_surface (pointer);
|
||||
meta_wayland_pointer_set_focus (pointer, pointer->current);
|
||||
}
|
||||
|
||||
static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
||||
@ -274,6 +247,36 @@ count_buttons (const ClutterEvent *event)
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_focus_surface (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaWaylandSurface *focus_surface;
|
||||
|
||||
switch (display->event_route)
|
||||
{
|
||||
case META_EVENT_ROUTE_WINDOW_OP:
|
||||
/* Don't update the focus surface while we're grabbing a window. */
|
||||
return;
|
||||
|
||||
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
|
||||
/* The compositor has focus, so remove our focus... */
|
||||
focus_surface = NULL;
|
||||
break;
|
||||
|
||||
case META_EVENT_ROUTE_NORMAL:
|
||||
case META_EVENT_ROUTE_WAYLAND_POPUP:
|
||||
focus_surface = pointer->current;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
|
||||
interface->focus (pointer->grab, focus_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
repick_for_event (MetaWaylandPointer *pointer,
|
||||
const ClutterEvent *for_event)
|
||||
@ -304,7 +307,6 @@ repick_for_event (MetaWaylandPointer *pointer,
|
||||
pointer->current = NULL;
|
||||
|
||||
sync_focus_surface (pointer);
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -516,11 +518,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
|
||||
clutter_input_device_get_coords (pointer->device, NULL, &pos);
|
||||
|
||||
if (pointer->focus_surface->window)
|
||||
meta_window_handle_enter (pointer->focus_surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
pos.x, pos.y);
|
||||
meta_window_handle_enter (pointer->focus_surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
pos.x, pos.y);
|
||||
|
||||
move_resources_for_client (&pointer->focus_resource_list,
|
||||
&pointer->resource_list,
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||
#define META_WL_COMPOSITOR_VERSION 3
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 2
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
|
||||
#define META_XDG_SHELL_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 4
|
||||
|
@ -1073,9 +1073,10 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
|
||||
/* Compute new frame size */
|
||||
new_w = window->rect.width + borders.invisible.left + borders.invisible.right;
|
||||
|
||||
new_h = borders.invisible.top + borders.invisible.bottom;
|
||||
if (!window->shaded)
|
||||
new_h += window->rect.height;
|
||||
if (window->shaded)
|
||||
new_h = borders.total.top + borders.total.bottom;
|
||||
else
|
||||
new_h = window->rect.height + borders.invisible.top + borders.invisible.bottom;
|
||||
|
||||
if (new_w != window->frame->rect.width ||
|
||||
new_h != window->frame->rect.height)
|
||||
|
Reference in New Issue
Block a user