Compare commits
128 Commits
wip/dnd-su
...
3.15.2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
00535b34b6 | ||
![]() |
a2b2a7a26f | ||
![]() |
9fdf487da1 | ||
![]() |
c5033616e9 | ||
![]() |
a0e038f34b | ||
![]() |
71dab32769 | ||
![]() |
c408cf7aac | ||
![]() |
e96eb0e82e | ||
![]() |
0015963457 | ||
![]() |
b832bc7424 | ||
![]() |
89b14babb9 | ||
![]() |
7ecde19aee | ||
![]() |
d7854794cf | ||
![]() |
f6f5f624d4 | ||
![]() |
7012c82fc7 | ||
![]() |
a0d2d207e7 | ||
![]() |
6e25c37da1 | ||
![]() |
061f434201 | ||
![]() |
638087fe78 | ||
![]() |
286a6ada5a | ||
![]() |
cb66ab5a87 | ||
![]() |
e72c6916aa | ||
![]() |
8b98cb818c | ||
![]() |
f8a4d450a5 | ||
![]() |
681cf95236 | ||
![]() |
90d6734f8c | ||
![]() |
213cd8a334 | ||
![]() |
3b1271d9be | ||
![]() |
13b6bd20ca | ||
![]() |
63e31af476 | ||
![]() |
718a89eb2f | ||
![]() |
a43ca7b5b1 | ||
![]() |
af00ca534a | ||
![]() |
4b2b431700 | ||
![]() |
2c1a6b6a12 | ||
![]() |
b3544f8ec1 | ||
![]() |
df384965c3 | ||
![]() |
700d367937 | ||
![]() |
7c5989c978 | ||
![]() |
8819d9ce66 | ||
![]() |
b63413e5b0 | ||
![]() |
cd1e1d4bf1 | ||
![]() |
9710c013c5 | ||
![]() |
05f8d79323 | ||
![]() |
f2546dfeea | ||
![]() |
47e339b46e | ||
![]() |
016b8f5b4a | ||
![]() |
b3821c4f90 | ||
![]() |
29e5c6c363 | ||
![]() |
e1704acda4 | ||
![]() |
60cbb41f42 | ||
![]() |
d88c8d9ced | ||
![]() |
60ab11ecbf | ||
![]() |
34516aeab6 | ||
![]() |
a37f632b1b | ||
![]() |
8a6542c242 | ||
![]() |
7e12000d97 | ||
![]() |
23f086da8a | ||
![]() |
4c2c1c4dd2 | ||
![]() |
545f298921 | ||
![]() |
64295e8cd7 | ||
![]() |
722d4c6c17 | ||
![]() |
cc8462969d | ||
![]() |
989bb6ebb1 | ||
![]() |
1dbda68839 | ||
![]() |
a460f88b31 | ||
![]() |
3e511b9591 | ||
![]() |
5664c703b7 | ||
![]() |
5c80c4b006 | ||
![]() |
22f91eba8d | ||
![]() |
d07e2f4090 | ||
![]() |
cd32e4a68a | ||
![]() |
4040a70781 | ||
![]() |
cb084cc841 | ||
![]() |
2deea6e0a3 | ||
![]() |
a116509301 | ||
![]() |
ead79f834c | ||
![]() |
7e431bd6bc | ||
![]() |
272e1fb296 | ||
![]() |
c39f18c2d4 | ||
![]() |
33acb5fea0 | ||
![]() |
591718dc02 | ||
![]() |
b6127eeda4 | ||
![]() |
eeff1b8b02 | ||
![]() |
354cc466af | ||
![]() |
9f5c38d121 | ||
![]() |
ead0e902ed | ||
![]() |
5d16194b03 | ||
![]() |
a74acf0ec2 | ||
![]() |
3044cfb7bf | ||
![]() |
f658740043 | ||
![]() |
c1613a16c0 | ||
![]() |
8e85015f91 | ||
![]() |
f127ee3bde | ||
![]() |
acd928044f | ||
![]() |
4ef2f2ce09 | ||
![]() |
bc81736e6b | ||
![]() |
49092397f2 | ||
![]() |
97705d3cfe | ||
![]() |
0364ea9140 | ||
![]() |
c0bdb3018b | ||
![]() |
924eaac358 | ||
![]() |
a9f5a5661f | ||
![]() |
9c589b6798 | ||
![]() |
113be01ce8 | ||
![]() |
28e59c5a8f | ||
![]() |
b588baf9f5 | ||
![]() |
9a825d9bee | ||
![]() |
f211b3ec90 | ||
![]() |
0510c3a621 | ||
![]() |
18db5d0799 | ||
![]() |
c061e26da5 | ||
![]() |
166668adc4 | ||
![]() |
ec797b055d | ||
![]() |
082cc9c83a | ||
![]() |
993bec37d7 | ||
![]() |
e496ed50d6 | ||
![]() |
a127d05790 | ||
![]() |
607730e96c | ||
![]() |
9203db0655 | ||
![]() |
64d40792c4 | ||
![]() |
e7356917b0 | ||
![]() |
fa58752276 | ||
![]() |
478b75e803 | ||
![]() |
492a1b244f | ||
![]() |
5d8ff2e34d | ||
![]() |
310083aeb2 | ||
![]() |
0faa900207 |
52
NEWS
52
NEWS
@@ -1,3 +1,55 @@
|
||||
3.15.2
|
||||
======
|
||||
* 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]
|
||||
|
||||
Contributors:
|
||||
Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
|
||||
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb]
|
||||
|
||||
3.15.1
|
||||
======
|
||||
* 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]
|
||||
|
||||
Contributors:
|
||||
Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre
|
||||
|
||||
3.14.1
|
||||
======
|
||||
* Fix move-titlebar-onscreen function [Florian; #736915]
|
||||
* Fix stacking of the guard window [Owen; #737233]
|
||||
* Fix keycode lookup for non-default layouts [Rui; #737134]
|
||||
* Fix workspaces-only-on-primary handling [Florian; #737178]
|
||||
* Don't unstick sticky windows on workspace removal [Florian; #737625]
|
||||
* Do not auto-minimize fullscreen windows [Jasper; #705177]
|
||||
* Upload keymap to newly added keyboard devices [Rui; #737673]
|
||||
* Apply keyboard repeat settings [Rui; #728055]
|
||||
* Don't send pressed keys on enter [Rui; #727178]
|
||||
* Fix build without wayland/native [Rico; #738225]
|
||||
* Send modifiers after the key event [Rui; #738238]
|
||||
* Fix unredirect heuristic [Adel; #738271]
|
||||
* Do not show system chrome over fullscreen windows [Florian; #693991]
|
||||
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
|
||||
|
||||
Contributors:
|
||||
Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
|
||||
Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
|
||||
Rūdolfs Mazurs [lv]
|
||||
|
||||
3.14.0
|
||||
======
|
||||
* Fix placement of popup windows on wayland [Jasper; #736812]
|
||||
|
@@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [14])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
m4_define([mutter_minor_version], [15])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -77,9 +77,7 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
$CLUTTER_PACKAGE >= 1.19.5
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
gbm >= 10.3
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
@@ -202,7 +200,7 @@ AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
|
||||
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])
|
||||
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,6 +111,15 @@ 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,8 +259,6 @@ 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.13.x\n"
|
||||
"Project-Id-Version: mutter 3.15.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-09-06 14:13+0200\n"
|
||||
"PO-Revision-Date: 2014-08-23 13:37+0200\n"
|
||||
"POT-Creation-Date: 2014-11-15 18:32+0100\n"
|
||||
"PO-Revision-Date: 2014-11-15 18:34+0100\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 ""
|
||||
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."
|
||||
|
||||
#: ../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 ""
|
||||
msgstr "Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt område på skjermen."
|
||||
|
||||
#: ../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:412
|
||||
#: ../src/backends/meta-monitor-manager.c:350
|
||||
msgid "Built-in display"
|
||||
msgstr "Innebygget skjerm"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:437
|
||||
#: ../src/backends/meta-monitor-manager.c:375
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjent"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:439
|
||||
#: ../src/backends/meta-monitor-manager.c:377
|
||||
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:447
|
||||
#: ../src/backends/meta-monitor-manager.c:385
|
||||
#, 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:443
|
||||
#: ../src/compositor/compositor.c:456
|
||||
#, 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:547
|
||||
#: ../src/core/display.c:550
|
||||
#, 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:459
|
||||
#: ../src/core/main.c:451
|
||||
#, c-format
|
||||
msgid "Failed to scan themes directory: %s\n"
|
||||
msgstr "Feil under søk i temakatalog: %s\n"
|
||||
|
||||
#: ../src/core/main.c:475
|
||||
#: ../src/core/main.c:467
|
||||
#, 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:2101
|
||||
#: ../src/core/prefs.c:2064
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Arbeidsområde %d"
|
||||
|
||||
#: ../src/core/screen.c:548
|
||||
#: ../src/core/screen.c:543
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Skjerm %d på display «%s» er ugyldig\n"
|
||||
|
||||
#: ../src/core/screen.c:564
|
||||
#: ../src/core/screen.c:559
|
||||
#, 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:657
|
||||
#: ../src/core/screen.c:652
|
||||
#, 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:233
|
||||
#: ../src/ui/theme.c:154
|
||||
msgid "top"
|
||||
msgstr "topp"
|
||||
|
||||
#: ../src/ui/theme.c:235
|
||||
#: ../src/ui/theme.c:156
|
||||
msgid "bottom"
|
||||
msgstr "bunn"
|
||||
|
||||
#: ../src/ui/theme.c:237
|
||||
#: ../src/ui/theme.c:158
|
||||
msgid "left"
|
||||
msgstr "venstre"
|
||||
|
||||
#: ../src/ui/theme.c:239
|
||||
#: ../src/ui/theme.c:160
|
||||
msgid "right"
|
||||
msgstr "høyre"
|
||||
|
||||
#: ../src/ui/theme.c:267
|
||||
#: ../src/ui/theme.c:188
|
||||
#, c-format
|
||||
msgid "frame geometry does not specify \"%s\" dimension"
|
||||
msgstr "rammegeometrien spesifiserer ikke «%s»-dimensjon"
|
||||
|
||||
#: ../src/ui/theme.c:286
|
||||
#: ../src/ui/theme.c:207
|
||||
#, 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:323
|
||||
#: ../src/ui/theme.c:244
|
||||
#, c-format
|
||||
msgid "Button aspect ratio %g is not reasonable"
|
||||
msgstr "Aspektrate %g for knapp er ikke fornuftig"
|
||||
|
||||
#: ../src/ui/theme.c:335
|
||||
#: ../src/ui/theme.c:256
|
||||
#, c-format
|
||||
msgid "Frame geometry does not specify size of buttons"
|
||||
msgstr "Rammegeometrien spesifiserer ikke størrelse på knapper"
|
||||
|
||||
#: ../src/ui/theme.c:1061
|
||||
#: ../src/ui/theme.c:1024
|
||||
#, c-format
|
||||
msgid "Gradients should have at least two colors"
|
||||
msgstr "Gradienter må ha minst to farger"
|
||||
|
||||
#: ../src/ui/theme.c:1211
|
||||
#: ../src/ui/theme.c:1174
|
||||
#, 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:1227
|
||||
#: ../src/ui/theme.c:1190
|
||||
#, 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:1241
|
||||
#: ../src/ui/theme.c:1204
|
||||
#, 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:1286
|
||||
#: ../src/ui/theme.c:1249
|
||||
#, 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:1300
|
||||
#: ../src/ui/theme.c:1263
|
||||
#, 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:1311
|
||||
#: ../src/ui/theme.c:1274
|
||||
#, c-format
|
||||
msgid "Did not understand state \"%s\" in color specification"
|
||||
msgstr "Forsto ikke tilstand «%s» i fargespesifikasjonen"
|
||||
|
||||
#: ../src/ui/theme.c:1324
|
||||
#: ../src/ui/theme.c:1287
|
||||
#, c-format
|
||||
msgid "Did not understand color component \"%s\" in color specification"
|
||||
msgstr "Forsto ikke fargekomponent «%s» i fargespesifikasjonen"
|
||||
|
||||
#: ../src/ui/theme.c:1352
|
||||
#: ../src/ui/theme.c:1315
|
||||
#, 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:1363
|
||||
#: ../src/ui/theme.c:1326
|
||||
#, 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:1373
|
||||
#: ../src/ui/theme.c:1336
|
||||
#, 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:1419
|
||||
#: ../src/ui/theme.c:1382
|
||||
#, 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:1430
|
||||
#: ../src/ui/theme.c:1393
|
||||
#, 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:1440
|
||||
#: ../src/ui/theme.c:1403
|
||||
#, c-format
|
||||
msgid "Shade factor \"%s\" in shaded color is negative"
|
||||
msgstr "Skyggefaktor «%s» i skyggelagt farge er negativ"
|
||||
|
||||
#: ../src/ui/theme.c:1469
|
||||
#: ../src/ui/theme.c:1432
|
||||
#, c-format
|
||||
msgid "Could not parse color \"%s\""
|
||||
msgstr "Kunne ikke lese farge «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:1778
|
||||
#: ../src/ui/theme.c:1741
|
||||
#, 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:1805
|
||||
#: ../src/ui/theme.c:1768
|
||||
#, 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:1819
|
||||
#: ../src/ui/theme.c:1782
|
||||
#, 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:1940
|
||||
#: ../src/ui/theme.c:1903
|
||||
#, 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:1997
|
||||
#: ../src/ui/theme.c:1960
|
||||
#, c-format
|
||||
msgid "Coordinate expression was empty or not understood"
|
||||
msgstr "Koordinatuttrykket var tomt eller ble ikke forstått"
|
||||
|
||||
#: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154
|
||||
#: ../src/ui/theme.c:2073 ../src/ui/theme.c:2083 ../src/ui/theme.c:2117
|
||||
#, c-format
|
||||
msgid "Coordinate expression results in division by zero"
|
||||
msgstr "Koordinatuttrykket resulterer i divisjon med null"
|
||||
|
||||
#: ../src/ui/theme.c:2162
|
||||
#: ../src/ui/theme.c:2125
|
||||
#, 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:2218
|
||||
#: ../src/ui/theme.c:2181
|
||||
#, 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:2227
|
||||
#: ../src/ui/theme.c:2190
|
||||
#, 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:2235
|
||||
#: ../src/ui/theme.c:2198
|
||||
#, 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:2245
|
||||
#: ../src/ui/theme.c:2208
|
||||
#, 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:2396 ../src/ui/theme.c:2441
|
||||
#: ../src/ui/theme.c:2359 ../src/ui/theme.c:2404
|
||||
#, c-format
|
||||
msgid "Coordinate expression had unknown variable or constant \"%s\""
|
||||
msgstr "Koordinatuttrykket haddeen ukjent variabel eller konstant «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:2495
|
||||
#: ../src/ui/theme.c:2458
|
||||
#, c-format
|
||||
msgid "Coordinate expression parser overflowed its buffer."
|
||||
msgstr "Tolkeren for koordinatuttrykk oversteg buffergrensen."
|
||||
|
||||
#: ../src/ui/theme.c:2524
|
||||
#: ../src/ui/theme.c:2487
|
||||
#, 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:2588
|
||||
#: ../src/ui/theme.c:2551
|
||||
#, 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:2599
|
||||
#: ../src/ui/theme.c:2562
|
||||
#, 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:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852
|
||||
#: ../src/ui/theme.c:2775 ../src/ui/theme.c:2795 ../src/ui/theme.c:2815
|
||||
#, 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:4455
|
||||
#: ../src/ui/theme.c:4055
|
||||
#, 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:4970 ../src/ui/theme.c:4995
|
||||
#: ../src/ui/theme.c:4570 ../src/ui/theme.c:4595
|
||||
#, 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:5041
|
||||
#: ../src/ui/theme.c:4641
|
||||
#, c-format
|
||||
msgid "Failed to load theme \"%s\": %s\n"
|
||||
msgstr "Klarte ikke å laste tema «%s»: %s\n"
|
||||
|
||||
#: ../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
|
||||
#: ../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
|
||||
#, c-format
|
||||
msgid "No <%s> set for theme \"%s\""
|
||||
msgstr "<%s> er ikke satt for tema «%s»"
|
||||
|
||||
#: ../src/ui/theme.c:5213
|
||||
#: ../src/ui/theme.c:4813
|
||||
#, 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:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745
|
||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5282 ../src/ui/theme.c:5345
|
||||
#, 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:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753
|
||||
#: ../src/ui/theme.c:5228 ../src/ui/theme.c:5290 ../src/ui/theme.c:5353
|
||||
#, 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:800
|
||||
#: ../src/ui/theme-parser.c:797
|
||||
#, 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:865
|
||||
#: ../src/ui/theme-parser.c:862
|
||||
#, 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:1021 ../src/ui/theme-parser.c:1084
|
||||
#: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221
|
||||
#: ../src/ui/theme-parser.c:1018 ../src/ui/theme-parser.c:1081
|
||||
#: ../src/ui/theme-parser.c:1115 ../src/ui/theme-parser.c:1218
|
||||
#, c-format
|
||||
msgid "<%s> name \"%s\" used a second time"
|
||||
msgstr "<%s> navn «%s» brukt på nytt"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130
|
||||
#: ../src/ui/theme-parser.c:1233
|
||||
#: ../src/ui/theme-parser.c:1030 ../src/ui/theme-parser.c:1127
|
||||
#: ../src/ui/theme-parser.c:1230
|
||||
#, c-format
|
||||
msgid "<%s> parent \"%s\" has not been defined"
|
||||
msgstr "<%s> opphav «%s» er ikke definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1143
|
||||
#: ../src/ui/theme-parser.c:1140
|
||||
#, c-format
|
||||
msgid "<%s> geometry \"%s\" has not been defined"
|
||||
msgstr "<%s> geometri «%s» er ikke definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1156
|
||||
#: ../src/ui/theme-parser.c:1153
|
||||
#, 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:1198
|
||||
#: ../src/ui/theme-parser.c:1195
|
||||
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:1266
|
||||
#: ../src/ui/theme-parser.c:1263
|
||||
#, c-format
|
||||
msgid "Unknown type \"%s\" on <%s> element"
|
||||
msgstr "Ukjent type «%s» på <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1277
|
||||
#: ../src/ui/theme-parser.c:1274
|
||||
#, c-format
|
||||
msgid "Unknown style_set \"%s\" on <%s> element"
|
||||
msgstr "Ukjent style_set «%s» på <%s>-element"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1285
|
||||
#: ../src/ui/theme-parser.c:1282
|
||||
#, 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: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
|
||||
#: ../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
|
||||
#, c-format
|
||||
msgid "Element <%s> is not allowed below <%s>"
|
||||
msgstr "Element <%s> er ikke tillatt under <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443
|
||||
#: ../src/ui/theme-parser.c:1488
|
||||
#: ../src/ui/theme-parser.c:1426 ../src/ui/theme-parser.c:1440
|
||||
#: ../src/ui/theme-parser.c:1485
|
||||
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:1452
|
||||
#: ../src/ui/theme-parser.c:1449
|
||||
#, c-format
|
||||
msgid "Distance \"%s\" is unknown"
|
||||
msgstr "Avstand «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1497
|
||||
#: ../src/ui/theme-parser.c:1494
|
||||
#, c-format
|
||||
msgid "Aspect ratio \"%s\" is unknown"
|
||||
msgstr "Aspektrate «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1559
|
||||
#: ../src/ui/theme-parser.c:1556
|
||||
#, c-format
|
||||
msgid "Border \"%s\" is unknown"
|
||||
msgstr "Grense «%s» er ukjent"
|
||||
|
||||
#: ../src/ui/theme-parser.c:1870
|
||||
#: ../src/ui/theme-parser.c:1867
|
||||
#, 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:1877
|
||||
#: ../src/ui/theme-parser.c:1874
|
||||
#, 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:2117
|
||||
#: ../src/ui/theme-parser.c:2114
|
||||
#, c-format
|
||||
msgid "Did not understand value \"%s\" for type of gradient"
|
||||
msgstr "Forsto ikke verdi «%s» for gradienttype"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570
|
||||
#: ../src/ui/theme-parser.c:2189 ../src/ui/theme-parser.c:2551
|
||||
#, 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:2362 ../src/ui/theme-parser.c:2445
|
||||
#: ../src/ui/theme-parser.c:2508
|
||||
#: ../src/ui/theme-parser.c:2343 ../src/ui/theme-parser.c:2426
|
||||
#: ../src/ui/theme-parser.c:2489
|
||||
#, c-format
|
||||
msgid "Did not understand state \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke tilstand «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455
|
||||
#: ../src/ui/theme-parser.c:2353 ../src/ui/theme-parser.c:2436
|
||||
#, c-format
|
||||
msgid "Did not understand shadow \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke skygge «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2382
|
||||
#: ../src/ui/theme-parser.c:2363
|
||||
#, c-format
|
||||
msgid "Did not understand arrow \"%s\" for <%s> element"
|
||||
msgstr "Forsto ikke pil «%s» for element <%s>"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792
|
||||
#: ../src/ui/theme-parser.c:2677 ../src/ui/theme-parser.c:2773
|
||||
#, c-format
|
||||
msgid "No <draw_ops> called \"%s\" has been defined"
|
||||
msgstr "Ingen <draw_ops> kalt «%s» er definert"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804
|
||||
#: ../src/ui/theme-parser.c:2689 ../src/ui/theme-parser.c:2785
|
||||
#, 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:2919
|
||||
#: ../src/ui/theme-parser.c:2900
|
||||
#, c-format
|
||||
msgid "Unknown position \"%s\" for frame piece"
|
||||
msgstr "Ukjent posisjon «%s» for rammesdel"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2927
|
||||
#: ../src/ui/theme-parser.c:2908
|
||||
#, 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:2944 ../src/ui/theme-parser.c:3021
|
||||
#: ../src/ui/theme-parser.c:2925 ../src/ui/theme-parser.c:3002
|
||||
#, 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:2974
|
||||
#: ../src/ui/theme-parser.c:2955
|
||||
#, c-format
|
||||
msgid "Unknown function \"%s\" for button"
|
||||
msgstr "Ukjent funksjon «%s» for knapp"
|
||||
|
||||
#: ../src/ui/theme-parser.c:2984
|
||||
#: ../src/ui/theme-parser.c:2965
|
||||
#, 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:2996
|
||||
#: ../src/ui/theme-parser.c:2977
|
||||
#, c-format
|
||||
msgid "Unknown state \"%s\" for button"
|
||||
msgstr "Ukjent tilstand «%s» for knapp"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3004
|
||||
#: ../src/ui/theme-parser.c:2985
|
||||
#, 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:3075
|
||||
#: ../src/ui/theme-parser.c:3056
|
||||
#, 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:3084
|
||||
#: ../src/ui/theme-parser.c:3065
|
||||
#, 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:3094
|
||||
#: ../src/ui/theme-parser.c:3075
|
||||
#, 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:3115 ../src/ui/theme-parser.c:3138
|
||||
#: ../src/ui/theme-parser.c:3096 ../src/ui/theme-parser.c:3119
|
||||
#, 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:3149
|
||||
#: ../src/ui/theme-parser.c:3130
|
||||
#, 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:3163
|
||||
#: ../src/ui/theme-parser.c:3144
|
||||
#, 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:3177 ../src/ui/theme-parser.c:3221
|
||||
#: ../src/ui/theme-parser.c:3158 ../src/ui/theme-parser.c:3202
|
||||
#, 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: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
|
||||
#: ../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
|
||||
#, 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:3293
|
||||
#: ../src/ui/theme-parser.c:3274
|
||||
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:3331
|
||||
#: ../src/ui/theme-parser.c:3312
|
||||
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:3369
|
||||
#: ../src/ui/theme-parser.c:3350
|
||||
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:3433
|
||||
#: ../src/ui/theme-parser.c:3414
|
||||
#, c-format
|
||||
msgid "Bad version specification '%s'"
|
||||
msgstr "Ugyldig versjonspesifikasjon «%s»"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3506
|
||||
#: ../src/ui/theme-parser.c:3487
|
||||
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:3529
|
||||
#: ../src/ui/theme-parser.c:3510
|
||||
#, 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:3561
|
||||
#: ../src/ui/theme-parser.c:3542
|
||||
#, 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:3581
|
||||
#: ../src/ui/theme-parser.c:3562
|
||||
#, 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:3586
|
||||
#: ../src/ui/theme-parser.c:3567
|
||||
#, 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:3598
|
||||
#: ../src/ui/theme-parser.c:3579
|
||||
#, 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:3620
|
||||
#: ../src/ui/theme-parser.c:3601
|
||||
#, 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:3630 ../src/ui/theme-parser.c:3660
|
||||
#: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670
|
||||
#: ../src/ui/theme-parser.c:3611 ../src/ui/theme-parser.c:3641
|
||||
#: ../src/ui/theme-parser.c:3646 ../src/ui/theme-parser.c:3651
|
||||
#, 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:3898
|
||||
#: ../src/ui/theme-parser.c:3879
|
||||
msgid "No draw_ops provided for frame piece"
|
||||
msgstr "Ingen draw_ops tilbys for rammedelen"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3913
|
||||
#: ../src/ui/theme-parser.c:3894
|
||||
msgid "No draw_ops provided for button"
|
||||
msgstr "Ingen draw_ops tilbys for knappen"
|
||||
|
||||
#: ../src/ui/theme-parser.c:3967
|
||||
#: ../src/ui/theme-parser.c:3948
|
||||
#, c-format
|
||||
msgid "No text is allowed inside element <%s>"
|
||||
msgstr "Ingen tekst er tillatt inne i element <%s>"
|
||||
|
||||
#: ../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
|
||||
#: ../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
|
||||
#, c-format
|
||||
msgid "<%s> specified twice for this theme"
|
||||
msgstr "<%s> spesifisert to ganger for dette temaet"
|
||||
|
||||
#: ../src/ui/theme-parser.c:4335
|
||||
#: ../src/ui/theme-parser.c:4316
|
||||
#, c-format
|
||||
msgid "Failed to find a valid file for theme %s\n"
|
||||
msgstr "Fant ikke en gyldig fil for tema %s\n"
|
||||
@@ -1261,10 +1261,7 @@ 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:515
|
||||
#: ../src/x11/window-props.c:558
|
||||
#, 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,11 +41,9 @@ 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 testgradient testasyncgetprop
|
||||
noinst_PROGRAMS+=testboxes testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
@@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
EXTRA_DIST =
|
||||
NULL =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
@@ -31,26 +32,30 @@ AM_CPPFLAGS = \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" \
|
||||
$(NULL)
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_display_config_built_sources) \
|
||||
$(dbus_login1_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c
|
||||
mutter-enum-types.c \
|
||||
$(NULL)
|
||||
|
||||
if HAVE_WAYLAND
|
||||
mutter_built_sources += \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h
|
||||
xdg-shell-server-protocol.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
wayland_protocols = \
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
wayland/protocol/xdg-shell.xml
|
||||
wayland/protocol/xdg-shell.xml \
|
||||
$(NULL)
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
backends/meta-backend.c \
|
||||
@@ -109,6 +114,10 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-background-group.c \
|
||||
compositor/meta-cullable.c \
|
||||
compositor/meta-cullable.h \
|
||||
compositor/meta-dnd-actor.c \
|
||||
compositor/meta-dnd-actor-private.h \
|
||||
compositor/meta-feedback-actor.c \
|
||||
compositor/meta-feedback-actor-private.h \
|
||||
compositor/meta-module.c \
|
||||
compositor/meta-module.h \
|
||||
compositor/meta-plugin.c \
|
||||
@@ -158,8 +167,6 @@ 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 \
|
||||
@@ -218,7 +225,8 @@ libmutter_la_SOURCES = \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
x11/mutter-Xatomtype.h
|
||||
x11/mutter-Xatomtype.h \
|
||||
$(NULL)
|
||||
|
||||
if HAVE_WAYLAND
|
||||
libmutter_la_SOURCES += \
|
||||
@@ -230,6 +238,10 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-xwayland.c \
|
||||
wayland/meta-xwayland.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-wayland-buffer.c \
|
||||
wayland/meta-wayland-buffer.h \
|
||||
wayland/meta-wayland-region.c \
|
||||
wayland/meta-wayland-region.h \
|
||||
wayland/meta-wayland-data-device.c \
|
||||
wayland/meta-wayland-data-device.h \
|
||||
wayland/meta-wayland-keyboard.c \
|
||||
@@ -247,7 +259,8 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
wayland/window-wayland.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if HAVE_NATIVE_BACKEND
|
||||
@@ -263,11 +276,11 @@ libmutter_la_SOURCES += \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/native/dbus-utils.c \
|
||||
backends/native/dbus-utils.h
|
||||
backends/native/dbus-utils.h \
|
||||
$(NULL)
|
||||
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)
|
||||
@@ -282,7 +295,6 @@ libmutterinclude_headers = \
|
||||
meta/compositor.h \
|
||||
meta/display.h \
|
||||
meta/errors.h \
|
||||
meta/gradient.h \
|
||||
meta/group.h \
|
||||
meta/keybindings.h \
|
||||
meta/main.h \
|
||||
@@ -303,7 +315,8 @@ libmutterinclude_headers = \
|
||||
meta/types.h \
|
||||
meta/util.h \
|
||||
meta/window.h \
|
||||
meta/workspace.h
|
||||
meta/workspace.h \
|
||||
$(NULL)
|
||||
|
||||
libmutterinclude_built_headers = \
|
||||
meta/meta-version.h
|
||||
@@ -384,14 +397,15 @@ 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
|
||||
org.gnome.Mutter.IdleMonitor.xml \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
$(mutter_built_sources) \
|
||||
|
@@ -29,8 +29,11 @@
|
||||
|
||||
typedef struct {
|
||||
CoglTexture2D *texture;
|
||||
struct gbm_bo *bo;
|
||||
int hot_x, hot_y;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *bo;
|
||||
#endif
|
||||
} MetaCursorImage;
|
||||
|
||||
struct _MetaCursorReference {
|
||||
@@ -44,8 +47,10 @@ CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
#endif
|
||||
|
||||
#endif /* META_CURSOR_PRIVATE_H */
|
||||
|
@@ -35,21 +35,13 @@
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglTexture *texture;
|
||||
MetaRectangle current_rect;
|
||||
int current_x, current_y;
|
||||
} MetaCursorLayer;
|
||||
|
||||
struct _MetaCursorRendererPrivate
|
||||
{
|
||||
MetaCursorLayer core_layer;
|
||||
MetaCursorLayer dnd_layer;
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
int dnd_surface_offset_x, dnd_surface_offset_y;
|
||||
gboolean cursor_handled_by_backend;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
@@ -67,19 +59,12 @@ queue_redraw (MetaCursorRenderer *renderer)
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
/* Pointer cursor */
|
||||
if (!priv->cursor_handled_by_backend)
|
||||
texture = priv->core_layer.texture;
|
||||
if (priv->displayed_cursor && !priv->handled_by_backend)
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture,
|
||||
&priv->core_layer.current_rect);
|
||||
|
||||
/* DnD surface */
|
||||
meta_stage_set_dnd_surface (META_STAGE (stage),
|
||||
priv->dnd_layer.texture,
|
||||
&priv->dnd_layer.current_rect);
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -100,76 +85,46 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
|
||||
}
|
||||
|
||||
static void
|
||||
update_layer (MetaCursorRenderer *renderer,
|
||||
MetaCursorLayer *layer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
layer->texture = texture;
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend;
|
||||
gboolean should_redraw = FALSE;
|
||||
|
||||
if (layer->texture)
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
layer->current_rect.x = layer->current_x + offset_x;
|
||||
layer->current_rect.y = layer->current_y + offset_y;
|
||||
layer->current_rect.width = cogl_texture_get_width (layer->texture);
|
||||
layer->current_rect.height = cogl_texture_get_height (layer->texture);
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
|
||||
|
||||
priv->current_rect.x = priv->current_x - hot_x;
|
||||
priv->current_rect.y = priv->current_y - hot_y;
|
||||
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
||||
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
layer->current_rect.x = 0;
|
||||
layer->current_rect.y = 0;
|
||||
layer->current_rect.width = 0;
|
||||
layer->current_rect.height = 0;
|
||||
priv->current_rect.x = 0;
|
||||
priv->current_rect.y = 0;
|
||||
priv->current_rect.width = 0;
|
||||
priv->current_rect.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_update_cursor (MetaCursorRenderer *renderer,
|
||||
gboolean force)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend, should_redraw = FALSE;
|
||||
|
||||
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
|
||||
if (handled_by_backend != priv->cursor_handled_by_backend)
|
||||
if (handled_by_backend != priv->handled_by_backend)
|
||||
{
|
||||
priv->cursor_handled_by_backend = handled_by_backend;
|
||||
priv->handled_by_backend = handled_by_backend;
|
||||
should_redraw = TRUE;
|
||||
}
|
||||
|
||||
if (force || !handled_by_backend || priv->dnd_layer.texture)
|
||||
if (!handled_by_backend)
|
||||
should_redraw = TRUE;
|
||||
|
||||
if (should_redraw)
|
||||
queue_redraw (renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
/* Cursor layer */
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor,
|
||||
&hot_x, &hot_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = NULL;
|
||||
hot_x = 0;
|
||||
hot_y = 0;
|
||||
}
|
||||
|
||||
update_layer (renderer, &priv->core_layer, texture, -hot_x, -hot_y);
|
||||
emit_update_cursor (renderer, FALSE);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_cursor_renderer_new (void)
|
||||
{
|
||||
@@ -189,23 +144,6 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->dnd_surface_offset_x = offset_x;
|
||||
priv->dnd_surface_offset_y = offset_y;
|
||||
|
||||
update_layer (renderer, &priv->dnd_layer, texture, offset_x, offset_y);
|
||||
emit_update_cursor (renderer, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
int x, int y)
|
||||
@@ -214,46 +152,12 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->core_layer.current_x = x;
|
||||
priv->core_layer.current_y = y;
|
||||
priv->current_x = x;
|
||||
priv->current_y = y;
|
||||
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->dnd_layer.current_x = x;
|
||||
priv->dnd_layer.current_y = y;
|
||||
|
||||
update_layer (renderer, &priv->dnd_layer, priv->dnd_layer.texture,
|
||||
priv->dnd_surface_offset_x, priv->dnd_surface_offset_y);
|
||||
emit_update_cursor (renderer, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (priv->dnd_layer.texture)
|
||||
meta_stage_dnd_failed (META_STAGE (stage),
|
||||
dest_x + priv->dnd_surface_offset_x,
|
||||
dest_y + priv->dnd_surface_offset_y);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
@@ -267,5 +171,5 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return &priv->core_layer.current_rect;
|
||||
return &priv->current_rect;
|
||||
}
|
||||
|
@@ -67,14 +67,4 @@ void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
|
||||
|
||||
void meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y);
|
||||
void meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
|
||||
int x, int y);
|
||||
|
||||
void meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
|
||||
int dest_x, int dest_y);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_H */
|
||||
|
@@ -62,20 +62,10 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y);
|
||||
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
|
||||
int dest_x,
|
||||
int dest_y);
|
||||
|
||||
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
|
@@ -27,7 +27,9 @@
|
||||
* pointer abstraction"
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/util.h>
|
||||
@@ -38,11 +40,10 @@
|
||||
|
||||
#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);
|
||||
|
||||
@@ -358,28 +359,6 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_set_dnd_surface (tracker->renderer, texture,
|
||||
offset_x, offset_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_dnd_failed (tracker->renderer, dest_x, dest_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
@@ -390,17 +369,6 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_set_dnd_surface_position (tracker->renderer,
|
||||
new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_gdk (int *x,
|
||||
int *y,
|
||||
|
@@ -56,8 +56,11 @@ static void
|
||||
meta_cursor_image_free (MetaCursorImage *image)
|
||||
{
|
||||
cogl_object_unref (image->texture);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (image->bo)
|
||||
gbm_bo_destroy (image->bo);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,10 +142,10 @@ load_cursor_on_client (MetaCursor cursor)
|
||||
meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
@@ -151,11 +154,12 @@ get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
@@ -193,20 +197,21 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
@@ -214,16 +219,13 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
{
|
||||
uint width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
CoglContext *cogl_context;
|
||||
struct gbm_device *gbm;
|
||||
|
||||
width = xc_image->width;
|
||||
height = xc_image->height;
|
||||
rowstride = width * 4;
|
||||
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
@@ -242,13 +244,15 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
NULL);
|
||||
|
||||
gbm = get_gbm_device ();
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
GBM_FORMAT_ARGB8888);
|
||||
#endif
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
@@ -277,14 +281,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
image->hot_x = hot_x;
|
||||
image->hot_y = hot_y;
|
||||
@@ -294,13 +292,19 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
|
||||
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
{
|
||||
if (gbm)
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
|
||||
@@ -332,10 +336,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gbm)
|
||||
else
|
||||
{
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
|
||||
size, so themed cursors must be padded with transparent pixels to fill the
|
||||
@@ -356,6 +357,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
@@ -385,6 +387,7 @@ meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
||||
return COGL_TEXTURE (cursor->image.texture);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *
|
||||
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
@@ -396,6 +399,7 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
*hot_y = cursor->image.hot_y;
|
||||
return cursor->image.bo;
|
||||
}
|
||||
#endif
|
||||
|
||||
MetaCursor
|
||||
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
|
||||
|
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "boxes-private.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -67,6 +68,7 @@ typedef struct {
|
||||
} MetaOutputConfig;
|
||||
|
||||
typedef struct {
|
||||
guint refcount;
|
||||
MetaOutputKey *keys;
|
||||
MetaOutputConfig *outputs;
|
||||
unsigned int n_outputs;
|
||||
@@ -77,7 +79,6 @@ struct _MetaMonitorConfig {
|
||||
|
||||
GHashTable *configs;
|
||||
MetaConfiguration *current;
|
||||
gboolean current_is_stored;
|
||||
gboolean current_is_for_laptop_lid;
|
||||
MetaConfiguration *previous;
|
||||
|
||||
@@ -124,11 +125,29 @@ config_clear (MetaConfiguration *config)
|
||||
g_free (config->outputs);
|
||||
}
|
||||
|
||||
static void
|
||||
config_free (gpointer config)
|
||||
static MetaConfiguration *
|
||||
config_ref (MetaConfiguration *config)
|
||||
{
|
||||
config_clear (config);
|
||||
g_slice_free (MetaConfiguration, config);
|
||||
config->refcount++;
|
||||
return config;
|
||||
}
|
||||
|
||||
static void
|
||||
config_unref (MetaConfiguration *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;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
@@ -220,7 +239,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
||||
const char *filename;
|
||||
char *path;
|
||||
|
||||
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free);
|
||||
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref);
|
||||
|
||||
filename = g_getenv ("MUTTER_MONITOR_FILENAME");
|
||||
if (filename == NULL)
|
||||
@@ -796,27 +815,6 @@ make_config_key (MetaConfiguration *key,
|
||||
key->n_outputs = o;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_config_match_current (MetaMonitorConfig *self,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
MetaOutput *outputs;
|
||||
unsigned n_outputs;
|
||||
MetaConfiguration key;
|
||||
gboolean ok;
|
||||
|
||||
if (self->current == NULL)
|
||||
return FALSE;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
|
||||
make_config_key (&key, outputs, n_outputs, -1);
|
||||
ok = config_equal (&key, self->current);
|
||||
|
||||
config_clear (&key);
|
||||
return ok;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
|
||||
{
|
||||
@@ -851,73 +849,45 @@ 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,
|
||||
gboolean stored)
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
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))
|
||||
{
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
if (!stored)
|
||||
config_free (config);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
goto out;
|
||||
|
||||
meta_monitor_manager_apply_configuration (manager,
|
||||
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
|
||||
(MetaOutputInfo**)outputs->pdata, outputs->len);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
set_current (self, config);
|
||||
|
||||
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()
|
||||
*/
|
||||
* inside turn_off_laptop_display / apply_configuration_with_lid */
|
||||
self->current_is_for_laptop_lid = FALSE;
|
||||
|
||||
if (self->current == self->previous)
|
||||
self->previous = NULL;
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
g_ptr_array_unref (crtcs);
|
||||
g_ptr_array_unref (outputs);
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -945,6 +915,19 @@ laptop_display_is_on (MetaConfiguration *config)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
multiple_outputs_are_enabled (MetaConfiguration *config)
|
||||
{
|
||||
unsigned int i, enabled;
|
||||
|
||||
enabled = 0;
|
||||
for (i = 0; i < config->n_outputs; i++)
|
||||
if (config->outputs[i].enabled)
|
||||
enabled++;
|
||||
|
||||
return enabled > 1;
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
make_laptop_lid_config (MetaConfiguration *reference)
|
||||
{
|
||||
@@ -954,9 +937,9 @@ make_laptop_lid_config (MetaConfiguration *reference)
|
||||
int x_after, y_after;
|
||||
int x_offset, y_offset;
|
||||
|
||||
g_assert (reference->n_outputs > 1);
|
||||
g_assert (multiple_outputs_are_enabled (reference));
|
||||
|
||||
new = g_slice_new0 (MetaConfiguration);
|
||||
new = config_new ();
|
||||
new->n_outputs = reference->n_outputs;
|
||||
new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
|
||||
new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
|
||||
@@ -1011,6 +994,32 @@ 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)
|
||||
@@ -1023,23 +1032,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
||||
stored = meta_monitor_config_get_stored (self, outputs, n_outputs);
|
||||
|
||||
if (stored)
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
stored->n_outputs > 1 &&
|
||||
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);
|
||||
}
|
||||
return apply_configuration_with_lid (self, stored, manager);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1089,47 +1082,123 @@ find_primary_output (MetaOutput *outputs,
|
||||
return best;
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
make_default_config (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs,
|
||||
int max_width,
|
||||
int max_height)
|
||||
static void
|
||||
init_config_from_preferred_mode (MetaOutputConfig *config,
|
||||
MetaOutput *output)
|
||||
{
|
||||
unsigned i, j;
|
||||
int x, y;
|
||||
MetaConfiguration *ret;
|
||||
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;
|
||||
|
||||
ret = g_slice_new (MetaConfiguration);
|
||||
make_config_key (ret, outputs, n_outputs, -1);
|
||||
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
/* Special case the simple case: one output, primary at preferred mode,
|
||||
nothing else to do */
|
||||
if (n_outputs == 1)
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
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;
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
|
||||
return ret;
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
g_list_free (region);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
XXX: but presentation mode is not implemented in the control-center
|
||||
or in mutter core, so let's do extended for now.
|
||||
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;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
@@ -1147,69 +1216,80 @@ make_default_config (MetaMonitorConfig *self,
|
||||
{
|
||||
if (j < i)
|
||||
{
|
||||
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
|
||||
ret->outputs[j] = ref->outputs[j];
|
||||
g_assert (output_key_equal (&config->keys[j], &ref->keys[j]));
|
||||
config->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 (&ret->keys[j], &ref->keys[j - 1]));
|
||||
ret->outputs[j] = ref->outputs[j - 1];
|
||||
g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1]));
|
||||
config->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
|
||||
{
|
||||
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;
|
||||
init_config_from_preferred_mode (&config->outputs[j], &outputs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 + 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;
|
||||
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;
|
||||
else
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
config->outputs[i].enabled = FALSE;
|
||||
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
x = primary->preferred_mode->width;
|
||||
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 */
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1221,7 +1301,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
unsigned n_outputs)
|
||||
{
|
||||
MetaConfiguration *ret;
|
||||
MetaConfiguration *config;
|
||||
MetaOutput *primary;
|
||||
unsigned i;
|
||||
|
||||
@@ -1232,34 +1312,29 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
|
||||
/* Oh no, we don't! Activate the primary one and disable everything else */
|
||||
|
||||
ret = g_slice_new (MetaConfiguration);
|
||||
make_config_key (ret, outputs, n_outputs, -1);
|
||||
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
config = config_new ();
|
||||
make_config_key (config, outputs, n_outputs, -1);
|
||||
config->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
|
||||
primary = find_primary_output (outputs, n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &outputs[i];
|
||||
gboolean is_primary = (&outputs[i] == primary);
|
||||
|
||||
if (output == primary)
|
||||
if (is_primary)
|
||||
{
|
||||
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;
|
||||
init_config_from_preferred_mode (&config->outputs[i], &outputs[0]);
|
||||
config->outputs[i].is_primary = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret->outputs[i].enabled = FALSE;
|
||||
config->outputs[i].enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
apply_configuration (self, ret, manager, FALSE);
|
||||
apply_configuration (self, config, manager);
|
||||
config_unref (config);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1270,8 +1345,9 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs;
|
||||
MetaConfiguration *default_config;
|
||||
unsigned n_outputs;
|
||||
gboolean ok;
|
||||
gboolean ok = FALSE;
|
||||
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);
|
||||
@@ -1282,23 +1358,21 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
return;
|
||||
}
|
||||
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||
/* 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);
|
||||
|
||||
if (default_config != NULL)
|
||||
{
|
||||
if (self->lid_is_closed &&
|
||||
default_config->n_outputs > 1 &&
|
||||
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);
|
||||
ok = apply_configuration_with_lid (self, default_config, manager);
|
||||
config_unref (default_config);
|
||||
}
|
||||
else
|
||||
ok = FALSE;
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
@@ -1335,7 +1409,7 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
|
||||
current = g_slice_new (MetaConfiguration);
|
||||
current = config_new ();
|
||||
current->n_outputs = n_outputs;
|
||||
current->outputs = g_new0 (MetaOutputConfig, n_outputs);
|
||||
current->keys = g_new0 (MetaOutputKey, n_outputs);
|
||||
@@ -1348,15 +1422,11 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
|
||||
|
||||
if (self->current && config_equal_full (current, self->current))
|
||||
{
|
||||
config_free (current);
|
||||
config_unref (current);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->current && !self->current_is_stored)
|
||||
config_free (self->current);
|
||||
|
||||
self->current = current;
|
||||
self->current_is_stored = FALSE;
|
||||
set_current (self, current);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1364,7 +1434,17 @@ meta_monitor_config_restore_previous (MetaMonitorConfig *self,
|
||||
MetaMonitorManager *manager)
|
||||
{
|
||||
if (self->previous)
|
||||
apply_configuration (self, self->previous, manager, FALSE);
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!meta_monitor_config_apply_stored (self, manager))
|
||||
@@ -1378,11 +1458,12 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
{
|
||||
MetaConfiguration *new;
|
||||
|
||||
if (self->current->n_outputs == 1)
|
||||
if (!multiple_outputs_are_enabled (self->current))
|
||||
return;
|
||||
|
||||
new = make_laptop_lid_config (self->current);
|
||||
apply_configuration (self, new, manager, FALSE);
|
||||
apply_configuration (self, new, manager);
|
||||
config_unref (new);
|
||||
self->current_is_for_laptop_lid = TRUE;
|
||||
}
|
||||
|
||||
@@ -1541,16 +1622,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
void
|
||||
meta_monitor_config_make_persistent (MetaMonitorConfig *self)
|
||||
{
|
||||
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;
|
||||
|
||||
g_hash_table_replace (self->configs, self->current, config_ref (self->current));
|
||||
meta_monitor_config_save (self);
|
||||
}
|
||||
|
||||
|
@@ -36,9 +36,6 @@ GType meta_monitor_config_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaMonitorConfig *meta_monitor_config_new (void);
|
||||
|
||||
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
|
||||
MetaMonitorManager *manager);
|
||||
|
||||
|
@@ -58,14 +58,6 @@ 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:
|
||||
*
|
||||
@@ -198,7 +190,7 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
|
||||
manager->config = meta_monitor_config_new ();
|
||||
|
||||
read_current_config (manager);
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
|
||||
if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
@@ -211,24 +203,7 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
so this is not needed.
|
||||
*/
|
||||
if (META_IS_MONITOR_MANAGER_XRANDR (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);
|
||||
}
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
|
||||
make_logical_config (manager);
|
||||
initialize_dbus_interface (manager);
|
||||
@@ -236,7 +211,7 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
manager->in_init = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs)
|
||||
{
|
||||
@@ -259,7 +234,7 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
g_free (old_outputs);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
|
||||
int n_old_modes)
|
||||
{
|
||||
@@ -1162,6 +1137,31 @@ 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,3 +1179,22 @@ 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,6 +116,8 @@ 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
|
||||
@@ -339,11 +341,9 @@ 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 */
|
||||
|
@@ -28,8 +28,6 @@
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#define DRAG_FAILED_MSECS 500
|
||||
|
||||
typedef struct {
|
||||
gboolean enabled;
|
||||
|
||||
@@ -41,20 +39,8 @@ typedef struct {
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
|
||||
typedef struct {
|
||||
MetaStage *stage;
|
||||
MetaOverlay overlay;
|
||||
ClutterTimeline *timeline;
|
||||
int orig_x;
|
||||
int orig_y;
|
||||
int dest_x;
|
||||
int dest_y;
|
||||
} MetaDragFailedAnimation;
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay dnd_overlay;
|
||||
MetaOverlay cursor_overlay;
|
||||
GList *drag_failed_animations;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
@@ -68,15 +54,6 @@ meta_overlay_init (MetaOverlay *overlay)
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_copy (MetaOverlay *src,
|
||||
MetaOverlay *dst)
|
||||
{
|
||||
*dst = *src;
|
||||
dst->pipeline = cogl_pipeline_copy (src->pipeline);
|
||||
dst->texture = src->texture;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
@@ -135,7 +112,6 @@ meta_stage_finalize (GObject *object)
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_free (&priv->dnd_overlay);
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
@@ -144,18 +120,9 @@ meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *animation;
|
||||
GList *l;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
for (l = priv->drag_failed_animations; l; l = l->next)
|
||||
{
|
||||
animation = l->data;
|
||||
meta_overlay_paint (&animation->overlay);
|
||||
}
|
||||
|
||||
meta_overlay_paint (&priv->dnd_overlay);
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
@@ -175,7 +142,6 @@ meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_init (&priv->dnd_overlay);
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
@@ -217,19 +183,6 @@ queue_redraw_for_overlay (MetaStage *stage,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_overlay_set (&priv->dnd_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->dnd_overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
@@ -242,84 +195,3 @@ meta_stage_set_cursor (MetaStage *stage,
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_failed_animation_frame_cb (ClutterTimeline *timeline,
|
||||
guint pos,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaDragFailedAnimation *data = user_data;
|
||||
gdouble progress = clutter_timeline_get_progress (timeline);
|
||||
CoglColor color;
|
||||
|
||||
cogl_color_init_from_4f (&color, 0, 0, 0, 1 - progress);
|
||||
cogl_pipeline_set_layer_combine_constant (data->overlay.pipeline, 0, &color);
|
||||
|
||||
data->overlay.current_rect.x = data->orig_x + ((data->dest_x - data->orig_x) * progress);
|
||||
data->overlay.current_rect.y = data->orig_y + ((data->dest_y - data->orig_y) * progress);
|
||||
queue_redraw_for_overlay (data->stage, &data->overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drag_failed_animation_free (MetaDragFailedAnimation *data)
|
||||
{
|
||||
MetaStage *stage = data->stage;
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
priv->drag_failed_animations =
|
||||
g_list_remove (priv->drag_failed_animations, data);
|
||||
|
||||
g_object_unref (data->timeline);
|
||||
meta_overlay_free (&data->overlay);
|
||||
g_slice_free (MetaDragFailedAnimation, data);
|
||||
}
|
||||
|
||||
static MetaDragFailedAnimation *
|
||||
meta_drag_failed_animation_new (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *data;
|
||||
|
||||
data = g_slice_new0 (MetaDragFailedAnimation);
|
||||
data->stage = stage;
|
||||
data->orig_x = priv->dnd_overlay.current_rect.x;
|
||||
data->orig_y = priv->dnd_overlay.current_rect.y;
|
||||
data->dest_x = dest_x;
|
||||
data->dest_y = dest_y;
|
||||
|
||||
meta_overlay_copy (&priv->dnd_overlay, &data->overlay);
|
||||
|
||||
data->timeline = clutter_timeline_new (DRAG_FAILED_MSECS);
|
||||
clutter_timeline_set_progress_mode (data->timeline, CLUTTER_EASE_OUT_CUBIC);
|
||||
g_signal_connect (data->timeline, "new-frame",
|
||||
G_CALLBACK (drag_failed_animation_frame_cb), data);
|
||||
g_signal_connect_swapped (data->timeline, "completed",
|
||||
G_CALLBACK (meta_drag_failed_animation_free), data);
|
||||
|
||||
priv->drag_failed_animations =
|
||||
g_list_prepend (priv->drag_failed_animations, data);
|
||||
|
||||
cogl_pipeline_set_layer_combine (data->overlay.pipeline, 0,
|
||||
"RGBA = MODULATE (TEXTURE, CONSTANT[A])",
|
||||
NULL);
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_dnd_failed (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *data;
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (!priv->dnd_overlay.enabled)
|
||||
return;
|
||||
|
||||
data = meta_drag_failed_animation_new (stage, dest_x, dest_y);
|
||||
clutter_timeline_start (data->timeline);
|
||||
}
|
||||
|
@@ -51,18 +51,9 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_dnd_failed (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_STAGE_H */
|
||||
|
@@ -36,11 +36,24 @@
|
||||
struct _MetaBackendNativePrivate
|
||||
{
|
||||
MetaLauncher *launcher;
|
||||
|
||||
GSettings *keyboard_settings;
|
||||
};
|
||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
|
||||
|
||||
static void
|
||||
meta_backend_native_finalize (GObject *object)
|
||||
{
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (object);
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
|
||||
g_clear_object (&priv->keyboard_settings);
|
||||
|
||||
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
|
||||
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
|
||||
@@ -142,15 +155,46 @@ pointer_constrain_callback (ClutterInputDevice *device,
|
||||
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
set_keyboard_repeat (MetaBackendNative *native)
|
||||
{
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
gboolean repeat;
|
||||
unsigned int delay, interval;
|
||||
|
||||
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
|
||||
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
|
||||
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
|
||||
|
||||
clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval);
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_settings_changed (GSettings *settings,
|
||||
const char *key,
|
||||
gpointer data)
|
||||
{
|
||||
MetaBackendNative *native = data;
|
||||
set_keyboard_repeat (native);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
|
||||
|
||||
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
|
||||
NULL, NULL);
|
||||
|
||||
priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
|
||||
g_signal_connect (priv->keyboard_settings, "changed",
|
||||
G_CALLBACK (keyboard_settings_changed), native);
|
||||
set_keyboard_repeat (native);
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
@@ -236,6 +280,9 @@ static void
|
||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
{
|
||||
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_backend_native_finalize;
|
||||
|
||||
backend_class->post_init = meta_backend_native_post_init;
|
||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
||||
@@ -271,7 +318,7 @@ meta_activate_vt (int vt, GError **error)
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* display server, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
|
@@ -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,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-monitor-manager-kms.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@@ -40,6 +41,8 @@
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
@@ -68,6 +71,8 @@ struct _MetaMonitorManagerKms
|
||||
unsigned int n_encoders;
|
||||
|
||||
drmModeEncoder *current_encoder;
|
||||
|
||||
GUdevClient *udev;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerKmsClass
|
||||
@@ -410,6 +415,8 @@ 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)
|
||||
{
|
||||
@@ -893,6 +900,23 @@ 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)
|
||||
{
|
||||
@@ -907,6 +931,21 @@ 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
|
||||
@@ -925,6 +964,7 @@ 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;
|
||||
|
@@ -65,9 +65,14 @@ struct _MetaBackendX11Private
|
||||
uint8_t xkb_error_base;
|
||||
|
||||
struct xkb_keymap *keymap;
|
||||
gchar *keymap_layouts;
|
||||
gchar *keymap_variants;
|
||||
gchar *keymap_options;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
static void apply_keymap (MetaBackendX11 *x11);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
|
||||
|
||||
static void
|
||||
@@ -326,6 +331,17 @@ take_touch_grab (MetaBackend *backend)
|
||||
False, &mask, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_added (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
|
||||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
|
||||
apply_keymap (x11);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
@@ -376,6 +392,9 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
|
||||
|
||||
g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
|
||||
G_CALLBACK (on_device_added), backend, 0);
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||
}
|
||||
|
||||
@@ -560,21 +579,22 @@ upload_xkb_description (Display *xdisplay,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
apply_keymap (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
XkbRF_RulesRec *xkb_rules;
|
||||
XkbRF_VarDefsRec xkb_var_defs = { 0 };
|
||||
gchar *rules_file_path;
|
||||
|
||||
if (!priv->keymap_layouts ||
|
||||
!priv->keymap_variants ||
|
||||
!priv->keymap_options)
|
||||
return;
|
||||
|
||||
get_xkbrf_var_defs (priv->xdisplay,
|
||||
layouts,
|
||||
variants,
|
||||
options,
|
||||
priv->keymap_layouts,
|
||||
priv->keymap_variants,
|
||||
priv->keymap_options,
|
||||
&rules_file_path,
|
||||
&xkb_var_defs);
|
||||
|
||||
@@ -598,6 +618,25 @@ meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||
g_free (rules_file_path);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
g_free (priv->keymap_layouts);
|
||||
priv->keymap_layouts = g_strdup (layouts);
|
||||
g_free (priv->keymap_variants);
|
||||
priv->keymap_variants = g_strdup (variants);
|
||||
g_free (priv->keymap_options);
|
||||
priv->keymap_options = g_strdup (options);
|
||||
|
||||
apply_keymap (x11);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
meta_backend_x11_get_keymap (MetaBackend *backend)
|
||||
{
|
||||
|
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "meta-cursor-renderer-x11.h"
|
||||
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
|
@@ -57,7 +57,6 @@ struct _MetaMonitorManagerXrandr
|
||||
|
||||
Display *xdisplay;
|
||||
XRRScreenResources *resources;
|
||||
int time;
|
||||
int rr_event_base;
|
||||
int rr_error_base;
|
||||
};
|
||||
@@ -140,6 +139,58 @@ 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)
|
||||
{
|
||||
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, AnyPropertyType,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
exists = (actual_type != None);
|
||||
|
||||
XFree (buffer);
|
||||
return exists;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
@@ -330,7 +381,29 @@ static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
|
||||
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 *
|
||||
@@ -413,7 +486,6 @@ 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;
|
||||
@@ -521,6 +593,8 @@ 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);
|
||||
@@ -747,7 +821,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
CurrentTime,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
@@ -777,7 +851,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
CurrentTime,
|
||||
0, 0,
|
||||
None,
|
||||
RR_Rotate_0,
|
||||
@@ -860,7 +934,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
manager_xrandr->time,
|
||||
CurrentTime,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
meta_monitor_transform_to_xrandr (crtc_info->transform),
|
||||
@@ -1001,16 +1075,6 @@ 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)
|
||||
{
|
||||
@@ -1070,63 +1134,30 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
||||
XEvent *event)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
unsigned int n_old_outputs, n_old_modes;
|
||||
gboolean new_config;
|
||||
gboolean hotplug;
|
||||
Time old_timestamp;
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
return FALSE;
|
||||
|
||||
XRRUpdateConfiguration (event);
|
||||
|
||||
/* 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;
|
||||
old_timestamp = manager_xrandr->resources->timestamp;
|
||||
|
||||
manager->serial++;
|
||||
meta_monitor_manager_xrandr_read_current (manager);
|
||||
|
||||
new_config = manager_xrandr->resources->timestamp >=
|
||||
manager_xrandr->resources->configTimestamp;
|
||||
if (meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
meta_monitor_manager_read_current_config (manager);
|
||||
|
||||
hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp;
|
||||
if (hotplug)
|
||||
{
|
||||
/* Check if the current intended configuration is a result of an
|
||||
XRandR call. Otherwise, hotplug_mode_update tells us to get
|
||||
a new preferred mode on hotplug events to handle dynamic
|
||||
guest resizing. */
|
||||
if (new_config)
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
/* This is a hotplug event, so go ahead and build a new configuration. */
|
||||
meta_monitor_manager_on_hotplug (manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if the current intended configuration has the same outputs
|
||||
as the new real one, or if the event is a result of an XRandR call.
|
||||
If so, we can go straight to rebuild the logical config and tell
|
||||
the outside world.
|
||||
Otherwise, this event was caused by hotplug, so give a chance to
|
||||
MetaMonitorConfig.
|
||||
|
||||
Note that we need to check both the timestamps and the list of
|
||||
outputs, because the X server might emit spurious events with new
|
||||
configTimestamps (bug 702804), and the driver may have changed
|
||||
the EDID for some other reason (old qxl and vbox drivers). */
|
||||
if (new_config || meta_monitor_config_match_current (manager->config, manager))
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
/* If something else changed -- tell the world about it. */
|
||||
if (old_timestamp < manager_xrandr->resources->timestamp)
|
||||
meta_monitor_manager_rebuild_derived (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);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ struct _MetaCompositor
|
||||
guint server_time_is_monotonic_time : 1;
|
||||
guint no_mipmaps : 1;
|
||||
|
||||
ClutterActor *stage, *window_group, *top_window_group;
|
||||
ClutterActor *stage, *window_group, *top_window_group, *feedback_group;
|
||||
ClutterActor *background_actor;
|
||||
GList *windows;
|
||||
Window output;
|
||||
|
@@ -185,6 +185,19 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
|
||||
return compositor->top_window_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_feedback_group_for_screen:
|
||||
* @screen: a #MetaScreen
|
||||
*
|
||||
* Returns: (transfer none): The feedback group corresponding to @screen
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_get_feedback_group_for_screen (MetaScreen *screen)
|
||||
{
|
||||
MetaCompositor *compositor = get_compositor_for_screen (screen);
|
||||
return compositor->feedback_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_get_window_actors:
|
||||
* @screen: a #MetaScreen
|
||||
@@ -478,9 +491,11 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
|
||||
compositor->window_group = meta_window_group_new (screen);
|
||||
compositor->top_window_group = meta_window_group_new (screen);
|
||||
compositor->feedback_group = meta_window_group_new (screen);
|
||||
|
||||
clutter_actor_add_child (compositor->stage, compositor->window_group);
|
||||
clutter_actor_add_child (compositor->stage, compositor->top_window_group);
|
||||
clutter_actor_add_child (compositor->stage, compositor->feedback_group);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
|
@@ -708,6 +708,7 @@ on_background_changed (MetaBackground *background,
|
||||
MetaBackgroundActor *self)
|
||||
{
|
||||
invalidate_pipeline (self, CHANGED_BACKGROUND);
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -53,7 +53,7 @@ struct _MetaBackgroundImageCacheClass
|
||||
struct _MetaBackgroundImage
|
||||
{
|
||||
GObject parent_instance;
|
||||
char *filename;
|
||||
GFile *file;
|
||||
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_str_hash, g_str_equal);
|
||||
cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -124,9 +124,17 @@ load_file (GTask *task,
|
||||
{
|
||||
GError *error = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
GFileInputStream *stream;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_file (image->filename,
|
||||
&error);
|
||||
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);
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
@@ -156,9 +164,11 @@ file_loaded (GObject *source_object,
|
||||
|
||||
if (pixbuf == NULL)
|
||||
{
|
||||
char *uri = g_file_get_uri (image->file);
|
||||
g_warning ("Failed to load background '%s': %s",
|
||||
image->filename, error->message);
|
||||
uri, error->message);
|
||||
g_clear_error (&error);
|
||||
g_free (uri);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -195,7 +205,7 @@ out:
|
||||
/**
|
||||
* meta_background_image_cache_load:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @filename: filename to load
|
||||
* @file: #GFile 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
|
||||
@@ -209,23 +219,23 @@ out:
|
||||
*/
|
||||
MetaBackgroundImage *
|
||||
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
const char *filename)
|
||||
GFile *file)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
GTask *task;
|
||||
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
image = g_hash_table_lookup (cache->images, file);
|
||||
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->filename = g_strdup (filename);
|
||||
g_hash_table_insert (cache->images, image->filename, image);
|
||||
image->file = g_object_ref (file);
|
||||
g_hash_table_insert (cache->images, image->file, image);
|
||||
|
||||
task = g_task_new (image, NULL, file_loaded, NULL);
|
||||
|
||||
@@ -238,25 +248,25 @@ meta_background_image_cache_load (MetaBackgroundImageCache *cache,
|
||||
/**
|
||||
* meta_background_image_cache_purge:
|
||||
* @cache: a #MetaBackgroundImageCache
|
||||
* @filename: filename to remove from the cache
|
||||
* @file: file 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,
|
||||
const char *filename)
|
||||
GFile *file)
|
||||
{
|
||||
MetaBackgroundImage *image;
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
|
||||
g_return_if_fail (filename != NULL);
|
||||
g_return_if_fail (file != NULL);
|
||||
|
||||
image = g_hash_table_lookup (cache->images, filename);
|
||||
image = g_hash_table_lookup (cache->images, file);
|
||||
if (image == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_remove (cache->images, image->filename);
|
||||
g_hash_table_remove (cache->images, image->file);
|
||||
image->in_cache = FALSE;
|
||||
}
|
||||
|
||||
@@ -273,12 +283,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->filename);
|
||||
g_hash_table_remove (image->cache->images, image->file);
|
||||
|
||||
if (image->texture)
|
||||
cogl_object_unref (image->texture);
|
||||
if (image->filename)
|
||||
g_free (image->filename);
|
||||
if (image->file)
|
||||
g_object_unref (image->file);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
@@ -50,9 +50,9 @@ struct _MetaBackgroundPrivate
|
||||
ClutterColor color;
|
||||
ClutterColor second_color;
|
||||
|
||||
char *filename1;
|
||||
GFile *file1;
|
||||
MetaBackgroundImage *background_image1;
|
||||
char *filename2;
|
||||
GFile *file2;
|
||||
MetaBackgroundImage *background_image2;
|
||||
|
||||
CoglTexture *color_texture;
|
||||
@@ -241,16 +241,28 @@ on_background_loaded (MetaBackgroundImage *image,
|
||||
mark_changed (self);
|
||||
}
|
||||
|
||||
static void
|
||||
set_filename (MetaBackground *self,
|
||||
char **filenamep,
|
||||
MetaBackgroundImage **imagep,
|
||||
const char *filename)
|
||||
static gboolean
|
||||
file_equal0 (GFile *file1,
|
||||
GFile *file2)
|
||||
{
|
||||
if (g_strcmp0 (filename, *filenamep) != 0)
|
||||
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)
|
||||
{
|
||||
if (!file_equal0 (*filep, file))
|
||||
{
|
||||
g_free (*filenamep);
|
||||
*filenamep = g_strdup (filename);
|
||||
g_clear_object (filep);
|
||||
|
||||
if (*imagep)
|
||||
{
|
||||
@@ -261,10 +273,12 @@ set_filename (MetaBackground *self,
|
||||
*imagep = NULL;
|
||||
}
|
||||
|
||||
if (filename)
|
||||
if (file)
|
||||
{
|
||||
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
|
||||
*imagep = meta_background_image_cache_load (cache, filename);
|
||||
|
||||
*filep = g_object_ref (file);
|
||||
*imagep = meta_background_image_cache_load (cache, file);
|
||||
g_signal_connect (*imagep, "loaded",
|
||||
G_CALLBACK (on_background_loaded), self);
|
||||
}
|
||||
@@ -280,8 +294,8 @@ meta_background_dispose (GObject *object)
|
||||
free_color_texture (self);
|
||||
free_wallpaper_texture (self);
|
||||
|
||||
set_filename (self, &priv->filename1, &priv->background_image1, NULL);
|
||||
set_filename (self, &priv->filename2, &priv->background_image2, NULL);
|
||||
set_file (self, &priv->file1, &priv->background_image1, NULL);
|
||||
set_file (self, &priv->file2, &priv->background_image2, NULL);
|
||||
|
||||
set_screen (self, NULL);
|
||||
|
||||
@@ -867,19 +881,19 @@ meta_background_set_gradient (MetaBackground *self,
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_set_filename (MetaBackground *self,
|
||||
const char *filename,
|
||||
GDesktopBackgroundStyle style)
|
||||
meta_background_set_file (MetaBackground *self,
|
||||
GFile *file,
|
||||
GDesktopBackgroundStyle style)
|
||||
{
|
||||
g_return_if_fail (META_IS_BACKGROUND (self));
|
||||
|
||||
meta_background_set_blend (self, filename, NULL, 0.0, style);
|
||||
meta_background_set_blend (self, file, NULL, 0.0, style);
|
||||
}
|
||||
|
||||
void
|
||||
meta_background_set_blend (MetaBackground *self,
|
||||
const char *filename1,
|
||||
const char *filename2,
|
||||
GFile *file1,
|
||||
GFile *file2,
|
||||
double blend_factor,
|
||||
GDesktopBackgroundStyle style)
|
||||
{
|
||||
@@ -890,8 +904,8 @@ meta_background_set_blend (MetaBackground *self,
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
set_filename (self, &priv->filename1, &priv->background_image1, filename1);
|
||||
set_filename (self, &priv->filename2, &priv->background_image2, filename2);
|
||||
set_file (self, &priv->file1, &priv->background_image1, file1);
|
||||
set_file (self, &priv->file2, &priv->background_image2, file2);
|
||||
|
||||
priv->blend_factor = blend_factor;
|
||||
priv->style = style;
|
||||
|
64
src/compositor/meta-dnd-actor-private.h
Normal file
64
src/compositor/meta-dnd-actor-private.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* meta-dnd-actor-private.h: Actor for painting the DnD surface
|
||||
*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_DND_ACTOR_PRIVATE_H
|
||||
#define META_DND_ACTOR_PRIVATE_H
|
||||
|
||||
#include "meta-feedback-actor-private.h"
|
||||
|
||||
/**
|
||||
* MetaDnDActor:
|
||||
*
|
||||
* This class handles the rendering of the DnD surface
|
||||
*/
|
||||
|
||||
#define META_TYPE_DND_ACTOR (meta_dnd_actor_get_type ())
|
||||
#define META_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DND_ACTOR, MetaDnDActor))
|
||||
#define META_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DND_ACTOR, MetaDnDActorClass))
|
||||
#define META_IS_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DND_ACTOR))
|
||||
#define META_IS_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DND_ACTOR))
|
||||
#define META_DND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DND_ACTOR, MetaDnDActorClass))
|
||||
|
||||
typedef struct _MetaDnDActor MetaDnDActor;
|
||||
typedef struct _MetaDnDActorClass MetaDnDActorClass;
|
||||
|
||||
struct _MetaDnDActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
MetaFeedbackActorClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaDnDActor
|
||||
{
|
||||
MetaFeedbackActor parent;
|
||||
};
|
||||
|
||||
GType meta_dnd_actor_get_type (void);
|
||||
|
||||
ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin,
|
||||
int start_x,
|
||||
int start_y);
|
||||
|
||||
void meta_dnd_actor_drag_finish (MetaDnDActor *self,
|
||||
gboolean success);
|
||||
|
||||
#endif /* META_DND_ACTOR_PRIVATE_H */
|
231
src/compositor/meta-dnd-actor.c
Normal file
231
src/compositor/meta-dnd-actor.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:meta-dnd-actor
|
||||
* @title: MetaDnDActor
|
||||
* @short_description: Actor for painting the drag and drop surface
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-dnd-actor-private.h"
|
||||
|
||||
#define DRAG_FAILED_DURATION 500
|
||||
|
||||
enum {
|
||||
PROP_DRAG_ORIGIN = 1,
|
||||
PROP_DRAG_START_X,
|
||||
PROP_DRAG_START_Y
|
||||
};
|
||||
|
||||
typedef struct _MetaDnDActorPrivate MetaDnDActorPrivate;
|
||||
|
||||
struct _MetaDnDActorPrivate
|
||||
{
|
||||
ClutterActor *drag_origin;
|
||||
int drag_start_x;
|
||||
int drag_start_y;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR)
|
||||
|
||||
static void
|
||||
meta_dnd_actor_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDnDActor *self = META_DND_ACTOR (object);
|
||||
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DRAG_ORIGIN:
|
||||
priv->drag_origin = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_DRAG_START_X:
|
||||
priv->drag_start_x = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_DRAG_START_Y:
|
||||
priv->drag_start_y = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_dnd_actor_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDnDActor *self = META_DND_ACTOR (object);
|
||||
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DRAG_ORIGIN:
|
||||
g_value_set_object (value, priv->drag_origin);
|
||||
break;
|
||||
case PROP_DRAG_START_X:
|
||||
g_value_set_int (value, priv->drag_start_x);
|
||||
break;
|
||||
case PROP_DRAG_START_Y:
|
||||
g_value_set_int (value, priv->drag_start_y);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_dnd_actor_class_init (MetaDnDActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
object_class->set_property = meta_dnd_actor_set_property;
|
||||
object_class->get_property = meta_dnd_actor_get_property;
|
||||
|
||||
pspec = g_param_spec_object ("drag-origin",
|
||||
"Drag origin",
|
||||
"The origin of the DnD operation",
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DRAG_ORIGIN,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_int ("drag-start-x",
|
||||
"Drag start X",
|
||||
"The X axis of the drag start point",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DRAG_START_X,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_int ("drag-start-y",
|
||||
"Drag start Y",
|
||||
"The Y axis of the drag start point",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DRAG_START_Y,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_dnd_actor_init (MetaDnDActor *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_dnd_actor_new:
|
||||
*
|
||||
* Creates a new actor to draw the current drag and drop surface.
|
||||
*
|
||||
* Return value: the newly created background actor
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_dnd_actor_new (ClutterActor *drag_origin,
|
||||
int drag_start_x,
|
||||
int drag_start_y)
|
||||
{
|
||||
MetaDnDActor *self;
|
||||
|
||||
self = g_object_new (META_TYPE_DND_ACTOR,
|
||||
"drag-origin", drag_origin,
|
||||
"drag-start-x", drag_start_x,
|
||||
"drag-start-y", drag_start_y,
|
||||
NULL);
|
||||
|
||||
return CLUTTER_ACTOR (self);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_failed_complete (ClutterTimeline *timeline,
|
||||
gboolean is_finished,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterActor *self = user_data;
|
||||
|
||||
clutter_actor_remove_all_children (self);
|
||||
clutter_actor_destroy (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_dnd_actor_drag_finish (MetaDnDActor *self,
|
||||
gboolean success)
|
||||
{
|
||||
MetaDnDActorPrivate *priv;
|
||||
ClutterActor *actor;
|
||||
|
||||
g_return_if_fail (META_IS_DND_ACTOR (self));
|
||||
|
||||
actor = CLUTTER_ACTOR (self);
|
||||
priv = meta_dnd_actor_get_instance_private (self);
|
||||
|
||||
if (success)
|
||||
{
|
||||
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (self));
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterTransition *transition;
|
||||
|
||||
clutter_actor_save_easing_state (actor);
|
||||
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
|
||||
clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION);
|
||||
clutter_actor_set_opacity (actor, 0);
|
||||
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (priv->drag_origin))
|
||||
{
|
||||
int anchor_x, anchor_y;
|
||||
ClutterPoint dest;
|
||||
|
||||
clutter_actor_get_transformed_position (priv->drag_origin,
|
||||
&dest.x, &dest.y);
|
||||
meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self),
|
||||
&anchor_x, &anchor_y);
|
||||
|
||||
dest.x += priv->drag_start_x - anchor_x;
|
||||
dest.y += priv->drag_start_y - anchor_y;
|
||||
clutter_actor_set_position (actor, dest.x, dest.y);
|
||||
}
|
||||
|
||||
transition = clutter_actor_get_transition (actor, "opacity");
|
||||
g_signal_connect (transition, "stopped",
|
||||
G_CALLBACK (drag_failed_complete), self);
|
||||
|
||||
clutter_actor_restore_easing_state (actor);
|
||||
}
|
||||
}
|
74
src/compositor/meta-feedback-actor-private.h
Normal file
74
src/compositor/meta-feedback-actor-private.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* meta-feedback-actor-private.h: Actor for painting user interaction feedback
|
||||
*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_FEEDBACK_ACTOR_PRIVATE_H
|
||||
#define META_FEEDBACK_ACTOR_PRIVATE_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
/**
|
||||
* MetaFeedbackActor:
|
||||
*
|
||||
* This class handles the rendering of user interaction feedback
|
||||
*/
|
||||
|
||||
#define META_TYPE_FEEDBACK_ACTOR (meta_feedback_actor_get_type ())
|
||||
#define META_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActor))
|
||||
#define META_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
|
||||
#define META_IS_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FEEDBACK_ACTOR))
|
||||
#define META_IS_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FEEDBACK_ACTOR))
|
||||
#define META_FEEDBACK_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
|
||||
|
||||
typedef struct _MetaFeedbackActor MetaFeedbackActor;
|
||||
typedef struct _MetaFeedbackActorClass MetaFeedbackActorClass;
|
||||
|
||||
struct _MetaFeedbackActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaFeedbackActor
|
||||
{
|
||||
ClutterActor parent;
|
||||
};
|
||||
|
||||
GType meta_feedback_actor_get_type (void);
|
||||
|
||||
ClutterActor *meta_feedback_actor_new (int anchor_x,
|
||||
int anchor_y);
|
||||
|
||||
void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor,
|
||||
int anchor_x,
|
||||
int anchor_y);
|
||||
void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor,
|
||||
int *anchor_x,
|
||||
int *anchor_y);
|
||||
|
||||
void meta_feedback_actor_set_position (MetaFeedbackActor *self,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_feedback_actor_update (MetaFeedbackActor *self,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#endif /* META_FEEDBACK_ACTOR_PRIVATE_H */
|
249
src/compositor/meta-feedback-actor.c
Normal file
249
src/compositor/meta-feedback-actor.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:meta-feedback-actor
|
||||
* @title: MetaFeedbackActor
|
||||
* @short_description: Actor for painting user interaction feedback
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "display-private.h"
|
||||
#include "compositor-private.h"
|
||||
#include "meta-feedback-actor-private.h"
|
||||
|
||||
enum {
|
||||
PROP_ANCHOR_X = 1,
|
||||
PROP_ANCHOR_Y
|
||||
};
|
||||
|
||||
typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate;
|
||||
|
||||
struct _MetaFeedbackActorPrivate
|
||||
{
|
||||
int anchor_x;
|
||||
int anchor_y;
|
||||
int pos_x;
|
||||
int pos_y;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
static void
|
||||
meta_feedback_actor_constructed (GObject *object)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_get_display ();
|
||||
clutter_actor_add_child (display->compositor->feedback_group,
|
||||
CLUTTER_ACTOR (object));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_feedback_actor_update_position (MetaFeedbackActor *self)
|
||||
{
|
||||
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
|
||||
|
||||
clutter_actor_set_position (CLUTTER_ACTOR (self),
|
||||
priv->pos_x - priv->anchor_x,
|
||||
priv->pos_y - priv->anchor_y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_feedback_actor_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
|
||||
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ANCHOR_X:
|
||||
priv->anchor_x = g_value_get_int (value);
|
||||
meta_feedback_actor_update_position (self);
|
||||
break;
|
||||
case PROP_ANCHOR_Y:
|
||||
priv->anchor_y = g_value_get_int (value);
|
||||
meta_feedback_actor_update_position (self);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_feedback_actor_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
|
||||
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ANCHOR_X:
|
||||
g_value_set_int (value, priv->anchor_x);
|
||||
break;
|
||||
case PROP_ANCHOR_Y:
|
||||
g_value_set_int (value, priv->anchor_y);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_feedback_actor_class_init (MetaFeedbackActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
object_class->constructed = meta_feedback_actor_constructed;
|
||||
object_class->set_property = meta_feedback_actor_set_property;
|
||||
object_class->get_property = meta_feedback_actor_get_property;
|
||||
|
||||
pspec = g_param_spec_int ("anchor-x",
|
||||
"Anchor X",
|
||||
"The X axis of the anchor point",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ANCHOR_X,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_int ("anchor-y",
|
||||
"Anchor Y",
|
||||
"The Y axis of the anchor point",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_ANCHOR_Y,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_feedback_actor_init (MetaFeedbackActor *self)
|
||||
{
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_feedback_actor_new:
|
||||
*
|
||||
* Creates a new actor to draw the current drag and drop surface.
|
||||
*
|
||||
* Return value: the newly created background actor
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_feedback_actor_new (int anchor_x,
|
||||
int anchor_y)
|
||||
{
|
||||
MetaFeedbackActor *self;
|
||||
|
||||
self = g_object_new (META_TYPE_FEEDBACK_ACTOR,
|
||||
"anchor-x", anchor_x,
|
||||
"anchor-y", anchor_y,
|
||||
NULL);
|
||||
|
||||
return CLUTTER_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
|
||||
int anchor_x,
|
||||
int anchor_y)
|
||||
{
|
||||
MetaFeedbackActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
|
||||
|
||||
priv = meta_feedback_actor_get_instance_private (self);
|
||||
|
||||
if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
|
||||
return;
|
||||
|
||||
if (priv->anchor_x != anchor_y)
|
||||
{
|
||||
priv->anchor_x = anchor_x;
|
||||
g_object_notify (G_OBJECT (self), "anchor-x");
|
||||
}
|
||||
|
||||
if (priv->anchor_y != anchor_y)
|
||||
{
|
||||
priv->anchor_y = anchor_y;
|
||||
g_object_notify (G_OBJECT (self), "anchor-y");
|
||||
}
|
||||
|
||||
meta_feedback_actor_update_position (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_feedback_actor_get_anchor (MetaFeedbackActor *self,
|
||||
int *anchor_x,
|
||||
int *anchor_y)
|
||||
{
|
||||
MetaFeedbackActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
|
||||
|
||||
priv = meta_feedback_actor_get_instance_private (self);
|
||||
|
||||
if (anchor_x)
|
||||
*anchor_x = priv->anchor_x;
|
||||
if (anchor_y)
|
||||
*anchor_y = priv->anchor_y;
|
||||
}
|
||||
|
||||
void
|
||||
meta_feedback_actor_set_position (MetaFeedbackActor *self,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaFeedbackActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
|
||||
|
||||
priv = meta_feedback_actor_get_instance_private (self);
|
||||
priv->pos_x = x;
|
||||
priv->pos_y = y;
|
||||
|
||||
meta_feedback_actor_update_position (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_feedback_actor_update (MetaFeedbackActor *self,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterPoint point;
|
||||
|
||||
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
clutter_event_get_position (event, &point);
|
||||
meta_feedback_actor_set_position (self, point.x, point.y);
|
||||
}
|
@@ -193,8 +193,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == x &&
|
||||
window_rect.y == y &&
|
||||
if (x == 0 &&
|
||||
y == 0 &&
|
||||
window_rect.width == width &&
|
||||
window_rect.height == height)
|
||||
priv->full_damage_frames_count++;
|
||||
@@ -383,6 +383,7 @@ window_decorated_notify (MetaWindow *window,
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
||||
|
||||
detach_pixmap (self);
|
||||
free_damage (self);
|
||||
create_damage (self);
|
||||
}
|
||||
|
@@ -49,6 +49,8 @@ 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;
|
||||
@@ -92,6 +94,11 @@ 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
|
||||
|
@@ -1155,7 +1155,7 @@ gboolean
|
||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
if (priv->surface)
|
||||
if (!meta_window_actor_is_destroyed (self) && priv->surface)
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
else
|
||||
return FALSE;
|
||||
|
@@ -295,7 +295,7 @@ on_monitors_changed (MetaScreen *screen,
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
int i, n;
|
||||
GRand *rand = g_rand_new_with_seed (12345);
|
||||
GRand *rand = g_rand_new_with_seed (123456);
|
||||
|
||||
clutter_actor_destroy_all_children (self->priv->background_group);
|
||||
|
||||
|
@@ -1017,6 +1017,7 @@ 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;
|
||||
@@ -1068,15 +1069,18 @@ constrain_aspect_ratio (MetaWindow *window,
|
||||
fudge = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
|
||||
|
||||
constraint_already_satisfied =
|
||||
info->current.width - (info->current.height * minr ) > -minr*fudge &&
|
||||
info->current.width - (info->current.height * maxr ) < maxr*fudge;
|
||||
client_rect.width - (client_rect.height * minr ) > -minr*fudge &&
|
||||
client_rect.width - (client_rect.height * maxr ) < maxr*fudge;
|
||||
if (check_only || constraint_already_satisfied)
|
||||
return constraint_already_satisfied;
|
||||
|
||||
/*** Enforce constraint ***/
|
||||
new_width = info->current.width;
|
||||
new_height = info->current.height;
|
||||
new_width = client_rect.width;
|
||||
new_height = client_rect.height;
|
||||
|
||||
switch (info->resize_gravity)
|
||||
{
|
||||
@@ -1123,6 +1127,14 @@ 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
|
||||
*/
|
||||
|
@@ -1007,7 +1007,7 @@ meta_display_list_windows (MetaDisplay *display,
|
||||
{
|
||||
MetaWindow *window = value;
|
||||
|
||||
if (!META_IS_WINDOW (window))
|
||||
if (!META_IS_WINDOW (window) || window->unmanaging)
|
||||
continue;
|
||||
|
||||
if (!window->override_redirect ||
|
||||
@@ -1020,7 +1020,7 @@ meta_display_list_windows (MetaDisplay *display,
|
||||
{
|
||||
MetaWindow *window = value;
|
||||
|
||||
if (!META_IS_WINDOW (window))
|
||||
if (!META_IS_WINDOW (window) || window->unmanaging)
|
||||
continue;
|
||||
|
||||
if (!window->override_redirect ||
|
||||
@@ -1953,6 +1953,11 @@ 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 */
|
||||
@@ -1965,7 +1970,7 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
* beginning of the grab_op.
|
||||
*/
|
||||
if (!meta_prefs_get_raise_on_click () &&
|
||||
display->grab_threshold_movement_reached)
|
||||
!display->grab_threshold_movement_reached)
|
||||
meta_window_raise (display->grab_window);
|
||||
|
||||
meta_window_grab_op_ended (grab_window, grab_op);
|
||||
@@ -1985,7 +1990,6 @@ 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;
|
||||
@@ -2440,13 +2444,22 @@ meta_display_get_tab_list (MetaDisplay *display,
|
||||
|
||||
mru_list = workspace ? workspace->mru_list : global_mru_list;
|
||||
|
||||
/* Windows sellout mode - MRU order.
|
||||
/* Windows sellout mode - MRU order. Collect unminimized windows
|
||||
* then minimized so minimized windows aren't in the way so much.
|
||||
*/
|
||||
for (tmp = mru_list; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
|
||||
if (IN_TAB_CHAIN (window, type))
|
||||
if (!window->minimized && IN_TAB_CHAIN (window, type))
|
||||
tab_list = g_list_prepend (tab_list, window);
|
||||
}
|
||||
|
||||
for (tmp = mru_list; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
|
||||
if (window->minimized && IN_TAB_CHAIN (window, type))
|
||||
tab_list = g_list_prepend (tab_list, window);
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
@@ -35,7 +36,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
#include "meta-surface-actor.h"
|
||||
@@ -151,23 +151,6 @@ 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)
|
||||
@@ -176,8 +159,15 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
gboolean bypass_clutter = FALSE;
|
||||
G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
|
||||
MetaGestureTracker *tracker;
|
||||
ClutterEventSequence *sequence;
|
||||
|
||||
meta_display_update_pointer_emulating_sequence (display, event);
|
||||
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;
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
MetaWaylandCompositor *compositor = NULL;
|
||||
@@ -314,6 +304,11 @@ 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,13 +1660,14 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
|
||||
meta_display_freeze_keyboard (MetaDisplay *display, 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);
|
||||
}
|
||||
|
||||
@@ -2955,10 +2956,6 @@ do_choose_window (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Tab list = %u\n", type);
|
||||
|
||||
/* reverse direction if shift is down */
|
||||
if (event->modifier_state & CLUTTER_SHIFT_MASK)
|
||||
backward = !backward;
|
||||
|
||||
window = meta_display_get_tab_next (display,
|
||||
type,
|
||||
screen->active_workspace,
|
||||
|
@@ -496,15 +496,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
return guard_window;
|
||||
}
|
||||
|
||||
/* Set a black background on the root window so that we don't
|
||||
* see confusing old copies of old windows when debugging
|
||||
* and testing. */
|
||||
static void
|
||||
meta_screen_set_background (MetaScreen *screen)
|
||||
{
|
||||
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
|
||||
}
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
@@ -709,7 +700,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
meta_screen_set_background (screen);
|
||||
|
||||
/* Handle creating a no_focus_window for this screen */
|
||||
screen->no_focus_window =
|
||||
@@ -3021,38 +3011,32 @@ static gboolean
|
||||
check_fullscreen_func (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
GSList *windows;
|
||||
GSList *tmp;
|
||||
MetaWindow *window;
|
||||
GSList *fullscreen_monitors = NULL;
|
||||
GSList *obscured_monitors = NULL;
|
||||
gboolean in_fullscreen_changed = FALSE;
|
||||
int i;
|
||||
|
||||
screen->check_fullscreen_later = 0;
|
||||
|
||||
windows = meta_display_list_windows (screen->display,
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
|
||||
|
||||
for (tmp = windows; tmp != NULL; tmp = tmp->next)
|
||||
/* We consider a monitor in fullscreen if it contains a fullscreen window;
|
||||
* however we make an exception for maximized windows above the fullscreen
|
||||
* one, as in that case window+chrome fully obscure the fullscreen window.
|
||||
*/
|
||||
for (window = meta_stack_get_top (screen->stack);
|
||||
window;
|
||||
window = meta_stack_get_below (screen->stack, window, FALSE))
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
gboolean covers_monitors = FALSE;
|
||||
|
||||
if (window->screen != screen || window->hidden)
|
||||
continue;
|
||||
|
||||
if (window->fullscreen)
|
||||
/* The checks for determining a fullscreen window's layer are quite
|
||||
* elaborate, and we do a poor job at keeping it dynamically up-to-date.
|
||||
* (It depends, for example, on whether the focus window is on the
|
||||
* same monitor as the fullscreen window.) But because we minimize
|
||||
* fullscreen windows not in LAYER_FULLSCREEN (see below), if the
|
||||
* layer is stale here, it's really bad, so just force recomputation for
|
||||
* here. This is expensive, but hopefully this function won't be
|
||||
* called too often.
|
||||
*/
|
||||
meta_window_update_layer (window);
|
||||
|
||||
if (window->override_redirect)
|
||||
{
|
||||
covers_monitors = TRUE;
|
||||
}
|
||||
else if (window->override_redirect)
|
||||
{
|
||||
/* We want to handle the case where an application is creating an
|
||||
* override-redirect window the size of the screen (monitor) and treat
|
||||
@@ -3062,10 +3046,14 @@ check_fullscreen_func (gpointer data)
|
||||
if (meta_window_is_monitor_sized (window))
|
||||
covers_monitors = TRUE;
|
||||
}
|
||||
else
|
||||
else if (window->maximized_horizontally &&
|
||||
window->maximized_vertically)
|
||||
{
|
||||
if (window->layer == META_LAYER_FULLSCREEN)
|
||||
covers_monitors = TRUE;
|
||||
int monitor_index = meta_window_get_monitor (window);
|
||||
/* + 1 to avoid NULL */
|
||||
gpointer monitor_p = GINT_TO_POINTER(monitor_index + 1);
|
||||
if (!g_slist_find (obscured_monitors, monitor_p))
|
||||
obscured_monitors = g_slist_prepend (obscured_monitors, monitor_p);
|
||||
}
|
||||
|
||||
if (covers_monitors)
|
||||
@@ -3079,30 +3067,16 @@ check_fullscreen_func (gpointer data)
|
||||
{
|
||||
/* + 1 to avoid NULL */
|
||||
gpointer monitor_p = GINT_TO_POINTER(monitors[j] + 1);
|
||||
if (!g_slist_find (fullscreen_monitors, monitor_p))
|
||||
if (!g_slist_find (fullscreen_monitors, monitor_p) &&
|
||||
!g_slist_find (obscured_monitors, monitor_p))
|
||||
fullscreen_monitors = g_slist_prepend (fullscreen_monitors, monitor_p);
|
||||
}
|
||||
|
||||
g_free (monitors);
|
||||
}
|
||||
|
||||
/* If we find a window that is fullscreen but not in the FULLSCREEN
|
||||
* layer, it means that we've kicked it out of the layer because
|
||||
* we've focused another window on the same monitor. In this case
|
||||
* it would be confusing to keep the window fullscreen and visible,
|
||||
* so minimize it. We can't do the same thing for override-redirect
|
||||
* windows, so we just hope the application does the right thing.
|
||||
*/
|
||||
if (!covers_monitors && window->fullscreen)
|
||||
{
|
||||
meta_window_minimize (window);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Minimizing %s: was fullscreen but in a lower layer\n",
|
||||
window->desc);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
g_slist_free (obscured_monitors);
|
||||
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
{
|
||||
|
@@ -2622,6 +2622,9 @@ meta_window_maximize_internal (MetaWindow *window,
|
||||
meta_window_recalc_features (window);
|
||||
set_net_wm_state (window);
|
||||
|
||||
if (window->monitor->in_fullscreen)
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
|
||||
@@ -3066,6 +3069,8 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
|
||||
meta_window_recalc_features (window);
|
||||
set_net_wm_state (window);
|
||||
if (!window->monitor->in_fullscreen)
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
@@ -3208,7 +3213,9 @@ 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()
|
||||
*/
|
||||
@@ -4652,6 +4659,32 @@ meta_window_appears_focused_changed (MetaWindow *window)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_propagate_focus_appearance (MetaWindow *window)
|
||||
{
|
||||
/* Parents of attached modal dialogs should appear focused. */
|
||||
if (meta_window_is_attached_dialog (window))
|
||||
return TRUE;
|
||||
|
||||
/* Parents of these sorts of override-redirect windows should
|
||||
* appear focused. */
|
||||
switch (window->type)
|
||||
{
|
||||
case META_WINDOW_DROPDOWN_MENU:
|
||||
case META_WINDOW_POPUP_MENU:
|
||||
case META_WINDOW_COMBO:
|
||||
case META_WINDOW_TOOLTIP:
|
||||
case META_WINDOW_NOTIFICATION:
|
||||
case META_WINDOW_DND:
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_propagate_focus_appearance:
|
||||
* @window: the window to start propagating from
|
||||
@@ -4675,7 +4708,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
|
||||
child = window;
|
||||
parent = meta_window_get_transient_for (child);
|
||||
while (parent && (!focused || meta_window_is_attached_dialog (child)))
|
||||
while (parent && (!focused || should_propagate_focus_appearance (child)))
|
||||
{
|
||||
gboolean child_focus_state_changed;
|
||||
|
||||
@@ -5820,7 +5853,7 @@ update_resize (MetaWindow *window,
|
||||
int new_w, new_h;
|
||||
int gravity;
|
||||
MetaRectangle old;
|
||||
double remaining;
|
||||
double remaining = 0;
|
||||
MetaMaximizeFlags new_unmaximize;
|
||||
|
||||
window->display->grab_latest_motion_x = x;
|
||||
@@ -6079,10 +6112,8 @@ 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);
|
||||
return FALSE;
|
||||
}
|
||||
end_grab_op (window, event);
|
||||
|
||||
return TRUE;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
|
@@ -180,13 +180,6 @@ meta_workspace_new (MetaScreen *screen)
|
||||
workspace->windows = NULL;
|
||||
workspace->mru_list = NULL;
|
||||
|
||||
/* make sure sticky windows are in our mru_list */
|
||||
windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
|
||||
for (l = windows; l; l = l->next)
|
||||
if (meta_window_located_on_workspace (l->data, workspace))
|
||||
meta_workspace_add_window (workspace, l->data);
|
||||
g_slist_free (windows);
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
workspace->work_area_monitor = NULL;
|
||||
workspace->work_area_screen.x = 0;
|
||||
@@ -205,6 +198,13 @@ meta_workspace_new (MetaScreen *screen)
|
||||
|
||||
workspace->showing_desktop = FALSE;
|
||||
|
||||
/* make sure sticky windows are in our mru_list */
|
||||
windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
|
||||
for (l = windows; l; l = l->next)
|
||||
if (meta_window_located_on_workspace (l->data, workspace))
|
||||
meta_workspace_add_window (workspace, l->data);
|
||||
g_slist_free (windows);
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,7 @@ Window meta_get_overlay_window (MetaScreen *screen);
|
||||
GList *meta_get_window_actors (MetaScreen *screen);
|
||||
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
|
||||
ClutterActor *meta_get_top_window_group_for_screen (MetaScreen *screen);
|
||||
ClutterActor *meta_get_feedback_group_for_screen (MetaScreen *screen);
|
||||
|
||||
void meta_disable_unredirect_for_screen (MetaScreen *screen);
|
||||
void meta_enable_unredirect_for_screen (MetaScreen *screen);
|
||||
|
@@ -173,7 +173,6 @@ 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);
|
||||
|
@@ -1,71 +0,0 @@
|
||||
/* -*- 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,
|
||||
const char *filename);
|
||||
GFile *file);
|
||||
void meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
|
||||
const char *filename);
|
||||
GFile *file);
|
||||
|
||||
#endif /* __META_BACKGROUND_IMAGE_H__ */
|
||||
|
@@ -67,12 +67,12 @@ void meta_background_set_gradient (MetaBackground *self,
|
||||
GDesktopBackgroundShading shading_direction,
|
||||
ClutterColor *color,
|
||||
ClutterColor *second_color);
|
||||
void meta_background_set_filename (MetaBackground *self,
|
||||
const char *filename,
|
||||
void meta_background_set_file (MetaBackground *self,
|
||||
GFile *file,
|
||||
GDesktopBackgroundStyle style);
|
||||
void meta_background_set_blend (MetaBackground *self,
|
||||
const char *filename1,
|
||||
const char *filename2,
|
||||
GFile *file1,
|
||||
GFile *file2,
|
||||
double blend_factor,
|
||||
GDesktopBackgroundStyle style);
|
||||
|
||||
|
@@ -573,6 +573,7 @@ meta_frames_manage_window (MetaFrames *frames,
|
||||
frame->title = NULL;
|
||||
frame->shape_applied = FALSE;
|
||||
frame->prelit_control = META_FRAME_CONTROL_NONE;
|
||||
frame->button_state = META_BUTTON_STATE_NORMAL;
|
||||
|
||||
meta_core_grab_buttons (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
|
||||
|
||||
|
@@ -1,902 +0,0 @@
|
||||
/* -*- 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;
|
||||
}
|
||||
}
|
@@ -1,315 +0,0 @@
|
||||
/* -*- 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,9 +774,6 @@ 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);
|
||||
|
||||
@@ -2150,11 +2147,9 @@ 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;
|
||||
@@ -2165,7 +2160,6 @@ 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;
|
||||
@@ -2211,18 +2205,6 @@ 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))
|
||||
{
|
||||
@@ -2233,7 +2215,6 @@ 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,7 +23,6 @@
|
||||
#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>
|
||||
@@ -273,6 +272,14 @@ 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,
|
||||
@@ -538,7 +545,6 @@ struct _MetaDrawOp
|
||||
} gradient;
|
||||
|
||||
struct {
|
||||
MetaColorSpec *colorize_spec;
|
||||
MetaAlphaGradientSpec *alpha_spec;
|
||||
GdkPixbuf *pixbuf;
|
||||
MetaDrawSpec *x;
|
||||
@@ -546,8 +552,6 @@ 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;
|
||||
@@ -972,8 +976,12 @@ gboolean meta_draw_op_list_contains (MetaDrawOpList *op_list,
|
||||
|
||||
MetaGradientSpec* meta_gradient_spec_new (MetaGradientType type);
|
||||
void meta_gradient_spec_free (MetaGradientSpec *desc);
|
||||
GdkPixbuf* meta_gradient_spec_render (const MetaGradientSpec *desc,
|
||||
GtkStyleContext *gtk_style,
|
||||
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);
|
||||
gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
|
||||
|
760
src/ui/theme.c
760
src/ui/theme.c
@@ -38,7 +38,6 @@
|
||||
#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>
|
||||
@@ -75,84 +74,6 @@ 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,
|
||||
@@ -1010,42 +931,84 @@ meta_gradient_spec_free (MetaGradientSpec *spec)
|
||||
g_free (spec);
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_gradient_spec_render (const MetaGradientSpec *spec,
|
||||
GtkStyleContext *style,
|
||||
int width,
|
||||
int height)
|
||||
static cairo_pattern_t *
|
||||
meta_gradient_spec_pattern (const MetaGradientSpec *spec,
|
||||
const MetaAlphaGradientSpec *alpha_spec,
|
||||
GtkStyleContext *style)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
int n_colors;
|
||||
GdkRGBA *colors;
|
||||
GSList *tmp;
|
||||
GSList *l;
|
||||
int i;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
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 ();
|
||||
|
||||
n_colors = g_slist_length (spec->color_specs);
|
||||
|
||||
if (n_colors == 0)
|
||||
return NULL;
|
||||
|
||||
colors = g_new (GdkRGBA, n_colors);
|
||||
if (alpha_spec != NULL)
|
||||
g_assert (n_colors == alpha_spec->n_alphas);
|
||||
|
||||
i = 0;
|
||||
tmp = spec->color_specs;
|
||||
while (tmp != NULL)
|
||||
for (l = spec->color_specs; l != NULL; l = l->next)
|
||||
{
|
||||
meta_color_spec_render (tmp->data, style, &colors[i]);
|
||||
MetaColorSpec *color_spec = l->data;
|
||||
GdkRGBA color;
|
||||
|
||||
tmp = tmp->next;
|
||||
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);
|
||||
++i;
|
||||
}
|
||||
|
||||
pixbuf = meta_gradient_create_multi (width, height,
|
||||
colors, n_colors,
|
||||
spec->type);
|
||||
return pattern;
|
||||
}
|
||||
|
||||
g_free (colors);
|
||||
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;
|
||||
|
||||
return pixbuf;
|
||||
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);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -3052,12 +3015,6 @@ 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);
|
||||
@@ -3132,413 +3089,6 @@ 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,
|
||||
@@ -3578,6 +3128,86 @@ 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
|
||||
@@ -3601,7 +3231,6 @@ 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);
|
||||
|
||||
@@ -3759,94 +3388,63 @@ 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);
|
||||
|
||||
if (!needs_alpha)
|
||||
{
|
||||
meta_color_spec_render (op->data.tint.color_spec,
|
||||
style_gtk, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
meta_color_spec_render (op->data.tint.color_spec,
|
||||
style_gtk, &color);
|
||||
|
||||
cairo_rectangle (cr, rx, ry, rwidth, rheight);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
if (op->data.tint.alpha_spec &&
|
||||
op->data.tint.alpha_spec->n_alphas == 1)
|
||||
color.alpha = op->data.tint.alpha_spec->alphas[0];
|
||||
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
}
|
||||
cairo_rectangle (cr, rx, ry, rwidth, rheight);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
meta_gradient_spec_render (op->data.gradient.gradient_spec,
|
||||
op->data.gradient.alpha_spec,
|
||||
cr, style_gtk,
|
||||
rx, ry, rwidth, rheight);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_DRAW_IMAGE:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
rwidth = parse_size_unchecked (op->data.image.width, env);
|
||||
rheight = parse_size_unchecked (op->data.image.height, env);
|
||||
|
||||
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));
|
||||
}
|
||||
draw_image (cr,
|
||||
op->data.image.pixbuf,
|
||||
op->data.image.fill_type,
|
||||
op->data.image.alpha_spec,
|
||||
rx, ry, rwidth, rheight);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3916,24 +3514,27 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
case META_DRAW_ICON:
|
||||
{
|
||||
int rx, ry, rwidth, rheight;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *src;
|
||||
|
||||
rwidth = parse_size_unchecked (op->data.icon.width, env);
|
||||
rheight = parse_size_unchecked (op->data.icon.height, env);
|
||||
|
||||
pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
||||
rwidth, rheight);
|
||||
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;
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
rx = parse_x_position_unchecked (op->data.icon.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.icon.y, env);
|
||||
rx = parse_x_position_unchecked (op->data.icon.x, env);
|
||||
ry = parse_y_position_unchecked (op->data.icon.y, env);
|
||||
|
||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
||||
cairo_paint (cr);
|
||||
|
||||
g_object_unref (G_OBJECT (pixbuf));
|
||||
}
|
||||
draw_image (cr, src,
|
||||
op->data.icon.fill_type,
|
||||
op->data.icon.alpha_spec,
|
||||
rx, ry, rwidth, rheight);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4053,7 +3654,6 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
gtk_style_context_restore (style_gtk);
|
||||
}
|
||||
|
||||
void
|
||||
|
137
src/wayland/meta-wayland-buffer.c
Normal file
137
src/wayland/meta-wayland-buffer.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Endless Mobile
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-buffer.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
static void
|
||||
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandBuffer *buffer =
|
||||
wl_container_of (listener, buffer, destroy_listener);
|
||||
|
||||
wl_signal_emit (&buffer->destroy_signal, buffer);
|
||||
g_slice_free (MetaWaylandBuffer, buffer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
buffer->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
buffer->ref_count--;
|
||||
if (buffer->ref_count == 0)
|
||||
{
|
||||
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
||||
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
MetaWaylandBuffer *
|
||||
meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandBuffer *buffer;
|
||||
struct wl_listener *listener;
|
||||
|
||||
listener =
|
||||
wl_resource_get_destroy_listener (resource,
|
||||
meta_wayland_buffer_destroy_handler);
|
||||
|
||||
if (listener)
|
||||
{
|
||||
buffer = wl_container_of (listener, buffer, destroy_listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = g_slice_new0 (MetaWaylandBuffer);
|
||||
|
||||
buffer->resource = resource;
|
||||
wl_signal_init (&buffer->destroy_signal);
|
||||
buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
|
||||
wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglError *catch_error = NULL;
|
||||
CoglTexture *texture;
|
||||
|
||||
if (buffer->texture)
|
||||
goto out;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
||||
buffer->resource,
|
||||
&catch_error));
|
||||
if (!texture)
|
||||
{
|
||||
cogl_error_free (catch_error);
|
||||
meta_fatal ("Could not import pending buffer, ignoring commit\n");
|
||||
}
|
||||
|
||||
buffer->texture = texture;
|
||||
|
||||
out:
|
||||
return buffer->texture;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
|
||||
if (shm_buffer)
|
||||
{
|
||||
int i, n_rectangles;
|
||||
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (buffer->texture,
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
shm_buffer,
|
||||
rect.x, rect.y, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
51
src/wayland/meta-wayland-buffer.h
Normal file
51
src/wayland/meta-wayland-buffer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Endless Mobile
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_BUFFER_H
|
||||
#define META_WAYLAND_BUFFER_H
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cairo.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandBuffer
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_signal destroy_signal;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
CoglTexture *texture;
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
|
||||
CoglTexture * meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
cairo_region_t *region);
|
||||
|
||||
#endif /* META_WAYLAND_BUFFER_H */
|
@@ -34,7 +34,7 @@
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-dnd-actor-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -183,6 +183,8 @@ struct _MetaWaylandDragGrab {
|
||||
MetaWaylandDataSource *drag_data_source;
|
||||
struct wl_listener drag_data_source_listener;
|
||||
|
||||
ClutterActor *feedback_actor;
|
||||
|
||||
MetaWaylandSurface *drag_origin;
|
||||
struct wl_listener drag_origin_listener;
|
||||
|
||||
@@ -212,8 +214,6 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (drag_grab->drag_focus == surface)
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, surface, FALSE);
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
{
|
||||
wl_data_device_send_leave (drag_grab->drag_focus_data_device);
|
||||
@@ -253,40 +253,6 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_update_dnd_surface_position (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterPoint pos;
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
meta_cursor_tracker_update_dnd_surface_position (seat->pointer.cursor_tracker,
|
||||
(int) pos.x, (int) pos.y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_update_dnd_surface (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSurface *surface = drag_grab->drag_surface;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
CoglTexture *texture = NULL;
|
||||
int offset_x, offset_y;
|
||||
|
||||
if (surface)
|
||||
{
|
||||
if (surface->buffer)
|
||||
texture = surface->buffer->texture;
|
||||
|
||||
offset_x = surface->offset_x;
|
||||
offset_y = surface->offset_y;
|
||||
}
|
||||
else
|
||||
offset_x = offset_y = 0;
|
||||
|
||||
meta_cursor_tracker_set_dnd_surface (seat->pointer.cursor_tracker,
|
||||
texture, offset_x, offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
@@ -294,8 +260,6 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
drag_grab_update_dnd_surface_position (drag_grab);
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
{
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
|
||||
@@ -305,29 +269,10 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
clutter_event_get_time (event),
|
||||
sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_dnd_failed (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSurface *surface = drag_grab->drag_origin;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterPoint dest;
|
||||
|
||||
if (drag_grab->drag_origin &&
|
||||
!meta_window_is_hidden (surface->window))
|
||||
{
|
||||
/* Find out the snap back position */
|
||||
clutter_actor_get_transformed_position (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
&dest.x, &dest.y);
|
||||
dest.x += drag_grab->drag_start_x;
|
||||
dest.y += drag_grab->drag_start_y;
|
||||
}
|
||||
else
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &dest);
|
||||
|
||||
meta_cursor_tracker_dnd_failed (seat->pointer.cursor_tracker,
|
||||
dest.x, dest.y);
|
||||
if (drag_grab->drag_surface)
|
||||
meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
event);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -351,10 +296,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
}
|
||||
|
||||
if (drag_grab->feedback_actor)
|
||||
{
|
||||
clutter_actor_remove_all_children (drag_grab->feedback_actor);
|
||||
clutter_actor_destroy (drag_grab->feedback_actor);
|
||||
}
|
||||
|
||||
drag_grab->seat->data_device.current_grab = NULL;
|
||||
|
||||
drag_grab_focus (&drag_grab->generic, NULL);
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
|
||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
||||
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
||||
@@ -371,11 +321,19 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
|
||||
event_type == CLUTTER_BUTTON_RELEASE)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (drag_grab->drag_focus_data_device &&
|
||||
drag_grab->drag_data_source->has_target)
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
else
|
||||
data_device_dnd_failed (drag_grab);
|
||||
{
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
/* Finish drag and let actor self-destruct */
|
||||
meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor),
|
||||
success);
|
||||
drag_grab->feedback_actor = NULL;
|
||||
}
|
||||
|
||||
if (seat->pointer.button_count == 0 &&
|
||||
@@ -416,7 +374,9 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
|
||||
wl_container_of (listener, drag_grab, drag_data_source_listener);
|
||||
|
||||
drag_grab->drag_surface = NULL;
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
|
||||
if (drag_grab->feedback_actor)
|
||||
clutter_actor_remove_all_children (drag_grab->feedback_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -483,12 +443,23 @@ data_device_start_drag (struct wl_client *client,
|
||||
drag_grab->drag_icon_listener.notify = destroy_data_device_icon;
|
||||
wl_resource_add_destroy_listener (icon_resource,
|
||||
&drag_grab->drag_icon_listener);
|
||||
|
||||
drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (drag_grab->drag_origin->surface_actor),
|
||||
drag_grab->drag_start_x,
|
||||
drag_grab->drag_start_y);
|
||||
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
clutter_actor_add_child (drag_grab->feedback_actor,
|
||||
CLUTTER_ACTOR (drag_grab->drag_surface->surface_actor));
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
pos.x, pos.y);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, NULL, TRUE);
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
|
||||
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
|
||||
drag_grab_update_dnd_surface_position (drag_grab);
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -576,9 +547,16 @@ 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
|
||||
@@ -684,6 +662,17 @@ meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
|
||||
void
|
||||
meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
if (data_device->current_grab)
|
||||
drag_grab_update_dnd_surface (data_device->current_grab);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
|
||||
if (!data_device->current_grab)
|
||||
return;
|
||||
|
||||
drag_grab = data_device->current_grab;
|
||||
|
||||
if (!drag_grab->feedback_actor || !drag_grab->drag_surface)
|
||||
return;
|
||||
|
||||
meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
|
||||
-drag_grab->drag_surface->offset_x,
|
||||
-drag_grab->drag_surface->offset_y);
|
||||
}
|
||||
|
@@ -383,8 +383,6 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
|
||||
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
|
||||
|
||||
wl_array_init (&keyboard->pressed_keys);
|
||||
|
||||
keyboard->xkb_info.keymap_fd = -1;
|
||||
|
||||
keyboard->settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
|
||||
@@ -417,47 +415,12 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
|
||||
/* XXX: What about keyboard->resource_list? */
|
||||
wl_array_release (&keyboard->pressed_keys);
|
||||
|
||||
g_object_unref (keyboard->settings);
|
||||
|
||||
keyboard->display = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
update_pressed_keys (struct wl_array *keys,
|
||||
uint32_t evdev_code,
|
||||
gboolean is_press)
|
||||
{
|
||||
uint32_t *end = (void *) ((char *) keys->data + keys->size);
|
||||
uint32_t *k;
|
||||
|
||||
if (is_press)
|
||||
{
|
||||
/* Make sure we don't already have this key. */
|
||||
for (k = keys->data; k < end; k++)
|
||||
if (*k == evdev_code)
|
||||
return;
|
||||
|
||||
/* Otherwise add the key to the list of pressed keys */
|
||||
k = wl_array_add (keys, sizeof (*k));
|
||||
*k = evdev_code;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remove the key from the array */
|
||||
for (k = keys->data; k < end; k++)
|
||||
if (*k == evdev_code)
|
||||
{
|
||||
*k = *(end - 1);
|
||||
keys->size -= sizeof (*k);
|
||||
return;
|
||||
}
|
||||
|
||||
g_warning ("unexpected key release event for key 0x%x", evdev_code);
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
evdev_code (const ClutterKeyEvent *event)
|
||||
{
|
||||
@@ -471,18 +434,10 @@ meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
|
||||
const ClutterKeyEvent *event)
|
||||
{
|
||||
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
|
||||
struct xkb_state *state = keyboard->xkb_info.state;
|
||||
enum xkb_state_component changed_state;
|
||||
|
||||
update_pressed_keys (&keyboard->pressed_keys, evdev_code (event), is_press);
|
||||
|
||||
changed_state = xkb_state_update_key (state,
|
||||
event->hardware_keycode,
|
||||
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
if (changed_state == 0)
|
||||
return;
|
||||
|
||||
notify_modifiers (keyboard);
|
||||
keyboard->mods_changed = xkb_state_update_key (keyboard->xkb_info.state,
|
||||
event->hardware_keycode,
|
||||
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -508,6 +463,12 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
||||
else
|
||||
meta_verbose ("No wayland surface is focused, continuing normal operation\n");
|
||||
|
||||
if (keyboard->mods_changed != 0)
|
||||
{
|
||||
notify_modifiers (keyboard);
|
||||
keyboard->mods_changed = 0;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -538,8 +499,27 @@ static void
|
||||
broadcast_focus (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
struct wl_array fake_keys;
|
||||
struct xkb_state *state = keyboard->xkb_info.state;
|
||||
|
||||
/* We never want to send pressed keys to wayland clients on
|
||||
* enter. The protocol says that we should send them, presumably so
|
||||
* that clients can trigger their own key repeat routine in case
|
||||
* they are given focus and a key is physically pressed.
|
||||
*
|
||||
* Unfortunately this causes some clients, in particular Xwayland,
|
||||
* to register key events that they really shouldn't handle,
|
||||
* e.g. on an Alt+Tab keybinding, where Alt is released before Tab,
|
||||
* clients would see Tab being pressed on enter followed by a key
|
||||
* release event for Tab, meaning that Tab would be processed by
|
||||
* the client when it really shouldn't.
|
||||
*
|
||||
* Since the use case for the pressed keys array on enter seems weak
|
||||
* to us, we'll just fake that there are no pressed keys instead
|
||||
* which should be spec compliant even if it might not be true.
|
||||
*/
|
||||
wl_array_init (&fake_keys);
|
||||
|
||||
wl_keyboard_send_modifiers (resource, keyboard->focus_serial,
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
|
||||
@@ -547,7 +527,7 @@ broadcast_focus (MetaWaylandKeyboard *keyboard,
|
||||
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
|
||||
wl_keyboard_send_enter (resource, keyboard->focus_serial,
|
||||
keyboard->focus_surface->resource,
|
||||
&keyboard->pressed_keys);
|
||||
&fake_keys);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -69,9 +69,8 @@ struct _MetaWaylandKeyboard
|
||||
struct wl_listener focus_surface_listener;
|
||||
uint32_t focus_serial;
|
||||
|
||||
struct wl_array pressed_keys;
|
||||
|
||||
MetaWaylandXkbInfo xkb_info;
|
||||
enum xkb_state_component mods_changed;
|
||||
|
||||
GSettings *settings;
|
||||
};
|
||||
|
@@ -75,6 +75,14 @@ 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;
|
||||
|
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-buffer.h"
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
@@ -64,6 +65,33 @@ 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)
|
||||
@@ -95,7 +123,7 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -107,7 +135,7 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (pointer->button_count > 0)
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, surface, TRUE);
|
||||
meta_wayland_pointer_set_focus (pointer, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -178,7 +206,7 @@ default_grab_button (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
|
||||
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
|
||||
meta_wayland_pointer_set_focus (pointer, pointer->current, TRUE);
|
||||
sync_focus_surface (pointer);
|
||||
}
|
||||
|
||||
static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
||||
@@ -218,7 +246,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
set_cursor_surface (pointer, NULL);
|
||||
|
||||
pointer->display = NULL;
|
||||
@@ -246,39 +274,6 @@ 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 ();
|
||||
}
|
||||
|
||||
if (focus_surface != pointer->focus_surface)
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface;
|
||||
interface->focus (pointer->grab, focus_surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
repick_for_event (MetaWaylandPointer *pointer,
|
||||
const ClutterEvent *for_event)
|
||||
@@ -308,10 +303,8 @@ repick_for_event (MetaWaylandPointer *pointer,
|
||||
else
|
||||
pointer->current = NULL;
|
||||
|
||||
if (pointer->cursor_tracker && pointer->current == NULL)
|
||||
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
|
||||
|
||||
sync_focus_surface (pointer);
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -480,8 +473,7 @@ broadcast_focus (MetaWaylandPointer *pointer,
|
||||
|
||||
void
|
||||
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface,
|
||||
gboolean emit_crossing)
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
if (pointer->display == NULL)
|
||||
return;
|
||||
@@ -501,12 +493,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
if (emit_crossing)
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
|
||||
move_resources (&pointer->resource_list, &pointer->focus_resource_list);
|
||||
@@ -527,17 +516,18 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
|
||||
clutter_input_device_get_coords (pointer->device, NULL, &pos);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
move_resources_for_client (&pointer->focus_resource_list,
|
||||
&pointer->resource_list,
|
||||
wl_resource_get_client (pointer->focus_surface->resource));
|
||||
|
||||
l = &pointer->focus_resource_list;
|
||||
if (emit_crossing && !wl_list_empty (l))
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
@@ -549,6 +539,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -573,6 +565,8 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
pointer->grab = &pointer->default_grab;
|
||||
interface = pointer->grab->interface;
|
||||
interface->focus (pointer->grab, pointer->current);
|
||||
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -599,9 +593,9 @@ popup_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
/* Popup grabs are in owner-events mode (ie, events for the same client
|
||||
are reported as normal) */
|
||||
if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
|
||||
meta_wayland_pointer_set_focus (grab->pointer, surface, TRUE);
|
||||
meta_wayland_pointer_set_focus (grab->pointer, surface);
|
||||
else
|
||||
meta_wayland_pointer_set_focus (grab->pointer, NULL, TRUE);
|
||||
meta_wayland_pointer_set_focus (grab->pointer, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -722,10 +716,10 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
if (surface->xdg_popup.resource)
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
|
||||
if (surface->xdg_popup)
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup, &popup->surface_destroy_listener);
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_resource_add_destroy_listener (surface->wl_shell_surface, &popup->surface_destroy_listener);
|
||||
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
return TRUE;
|
||||
@@ -757,25 +751,32 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
if (pointer->cursor_tracker == NULL)
|
||||
return;
|
||||
|
||||
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
|
||||
if (pointer->current)
|
||||
{
|
||||
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
|
||||
cursor = meta_cursor_reference_from_buffer (buffer,
|
||||
pointer->hotspot_x,
|
||||
pointer->hotspot_y);
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
if (pointer->cursor_surface && pointer->cursor_surface->buffer)
|
||||
{
|
||||
struct wl_resource *buffer = pointer->cursor_surface->buffer->resource;
|
||||
cursor = meta_cursor_reference_from_buffer (buffer,
|
||||
pointer->hotspot_x,
|
||||
pointer->hotspot_y);
|
||||
}
|
||||
else
|
||||
cursor = NULL;
|
||||
|
||||
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
|
||||
|
||||
if (cursor)
|
||||
meta_cursor_reference_unref (cursor);
|
||||
}
|
||||
else
|
||||
cursor = NULL;
|
||||
|
||||
meta_cursor_tracker_set_window_cursor (pointer->cursor_tracker, cursor);
|
||||
|
||||
if (cursor)
|
||||
meta_cursor_reference_unref (cursor);
|
||||
{
|
||||
meta_cursor_tracker_unset_window_cursor (pointer->cursor_tracker);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -86,8 +86,7 @@ gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface,
|
||||
gboolean emit_crossing);
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandPointerGrab *grab);
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "window-private.h"
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
@@ -34,19 +33,6 @@
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
cairo_region_t *region;
|
||||
} MetaWaylandRegion;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GSource source;
|
||||
GPollFD pfd;
|
||||
struct wl_display *display;
|
||||
} WaylandEventSource;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_list link;
|
||||
@@ -71,7 +57,6 @@ struct _MetaWaylandCompositor
|
||||
{
|
||||
struct wl_display *wayland_display;
|
||||
const char *display_name;
|
||||
ClutterActor *stage;
|
||||
GHashTable *outputs;
|
||||
struct wl_list frame_callbacks;
|
||||
|
||||
@@ -80,8 +65,4 @@ struct _MetaWaylandCompositor
|
||||
MetaWaylandSeat *seat;
|
||||
};
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
|
||||
|
||||
#endif /* META_WAYLAND_PRIVATE_H */
|
||||
|
105
src/wayland/meta-wayland-region.c
Normal file
105
src/wayland/meta-wayland-region.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Endless Mobile
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-region.h"
|
||||
|
||||
struct _MetaWaylandRegion
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
cairo_region_t *region;
|
||||
};
|
||||
|
||||
static void
|
||||
wl_region_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_region_add (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
gint32 x,
|
||||
gint32 y,
|
||||
gint32 width,
|
||||
gint32 height)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
cairo_rectangle_int_t rectangle = { x, y, width, height };
|
||||
|
||||
cairo_region_union_rectangle (region->region, &rectangle);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_region_subtract (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
gint32 x,
|
||||
gint32 y,
|
||||
gint32 width,
|
||||
gint32 height)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
cairo_rectangle_int_t rectangle = { x, y, width, height };
|
||||
|
||||
cairo_region_subtract_rectangle (region->region, &rectangle);
|
||||
}
|
||||
|
||||
static const struct wl_region_interface meta_wayland_wl_region_interface = {
|
||||
wl_region_destroy,
|
||||
wl_region_add,
|
||||
wl_region_subtract
|
||||
};
|
||||
|
||||
static void
|
||||
wl_region_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
|
||||
cairo_region_destroy (region->region);
|
||||
g_slice_free (MetaWaylandRegion, region);
|
||||
}
|
||||
|
||||
MetaWaylandRegion *
|
||||
meta_wayland_region_create (MetaWaylandCompositor *compositor,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *compositor_resource,
|
||||
guint32 id)
|
||||
{
|
||||
MetaWaylandRegion *region = g_slice_new0 (MetaWaylandRegion);
|
||||
|
||||
region->resource = wl_resource_create (client, &wl_region_interface, wl_resource_get_version (compositor_resource), id);
|
||||
wl_resource_set_implementation (region->resource, &meta_wayland_wl_region_interface, region, wl_region_destructor);
|
||||
|
||||
region->region = cairo_region_create ();
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region)
|
||||
{
|
||||
return region->region;
|
||||
}
|
40
src/wayland/meta-wayland-region.h
Normal file
40
src/wayland/meta-wayland-region.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Endless Mobile
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_REGION_H
|
||||
#define META_WAYLAND_REGION_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <cairo.h>
|
||||
#include <wayland-server.h>
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
MetaWaylandRegion * meta_wayland_region_create (MetaWaylandCompositor *compositor,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *compositor_resource,
|
||||
guint32 id);
|
||||
|
||||
cairo_region_t * meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region);
|
||||
|
||||
#endif /* META_WAYLAND_REGION_H */
|
@@ -20,29 +20,23 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-surface.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/wayland/clutter-wayland-compositor.h>
|
||||
#include <clutter/wayland/clutter-wayland-surface.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include "gtk-shell-server-protocol.h"
|
||||
#include "xdg-shell-server-protocol.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-wayland-buffer.h"
|
||||
#include "meta-wayland-region.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
@@ -52,9 +46,6 @@
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
#include "window-wayland.h"
|
||||
#include <meta/types.h>
|
||||
#include <meta/main.h>
|
||||
#include "frame.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
@@ -106,67 +97,38 @@ static void
|
||||
surface_process_damage (MetaWaylandSurface *surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
int i, n_rectangles;
|
||||
cairo_rectangle_int_t buffer_rect;
|
||||
int scale = surface->scale;
|
||||
CoglTexture *texture;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int i, n_rectangles;
|
||||
|
||||
/* Damage without a buffer makes no sense so ignore that, otherwise we would crash */
|
||||
if (!surface->buffer)
|
||||
return;
|
||||
|
||||
texture = surface->buffer->texture;
|
||||
|
||||
buffer_rect.x = 0;
|
||||
buffer_rect.y = 0;
|
||||
buffer_rect.width = cogl_texture_get_width (surface->buffer->texture);
|
||||
buffer_rect.height = cogl_texture_get_height (surface->buffer->texture);
|
||||
|
||||
/* The region will get destroyed after this call anyway so we can
|
||||
just modify it here to avoid a copy */
|
||||
* just modify it here to avoid a copy. */
|
||||
cairo_region_intersect_rectangle (region, &buffer_rect);
|
||||
|
||||
/* First update the buffer. */
|
||||
meta_wayland_buffer_process_damage (surface->buffer, region);
|
||||
|
||||
/* Now damage the actor. */
|
||||
/* XXX: Should this be a signal / callback on MetaWaylandBuffer instead? */
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (surface->buffer->resource);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
if (shm_buffer)
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, rect.x, rect.y, rect.width, rect.height, shm_buffer, rect.x, rect.y, 0, NULL);
|
||||
|
||||
meta_surface_actor_process_damage (surface->surface_actor,
|
||||
rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_buffer_texture (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglError *catch_error = NULL;
|
||||
CoglTexture *texture;
|
||||
|
||||
if (buffer->texture)
|
||||
return;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
||||
buffer->resource,
|
||||
&catch_error));
|
||||
if (!texture)
|
||||
{
|
||||
cogl_error_free (catch_error);
|
||||
meta_warning ("Could not import pending buffer, ignoring commit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->texture = texture;
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
@@ -425,8 +387,8 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
|
||||
if (pending->buffer)
|
||||
{
|
||||
ensure_buffer_texture (pending->buffer);
|
||||
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), pending->buffer->texture);
|
||||
CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer);
|
||||
meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), texture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,21 +408,11 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
}
|
||||
if (pending->input_region)
|
||||
{
|
||||
pending->input_region = scale_region (pending->input_region, surface->scale);
|
||||
pending->input_region = scale_region (pending->input_region,
|
||||
meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor)));
|
||||
meta_surface_actor_set_input_region (surface->surface_actor, pending->input_region);
|
||||
}
|
||||
|
||||
if (surface == compositor->seat->pointer.cursor_surface)
|
||||
cursor_surface_commit (surface, pending);
|
||||
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
|
||||
dnd_surface_commit (surface, pending);
|
||||
else if (surface->window)
|
||||
toplevel_surface_commit (surface, pending);
|
||||
else if (surface->subsurface.resource)
|
||||
subsurface_surface_commit (surface, pending);
|
||||
|
||||
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
|
||||
|
||||
/* scale surface texture */
|
||||
meta_surface_actor_wayland_scale_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
|
||||
|
||||
@@ -468,6 +420,17 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
|
||||
if (surface == compositor->seat->pointer.cursor_surface)
|
||||
cursor_surface_commit (surface, pending);
|
||||
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
|
||||
dnd_surface_commit (surface, pending);
|
||||
else if (surface->window)
|
||||
toplevel_surface_commit (surface, pending);
|
||||
else if (surface->wl_subsurface)
|
||||
subsurface_surface_commit (surface, pending);
|
||||
|
||||
g_list_foreach (surface->subsurfaces, parent_surface_committed, NULL);
|
||||
|
||||
pending_state_reset (pending);
|
||||
}
|
||||
|
||||
@@ -578,7 +541,8 @@ wl_surface_set_opaque_region (struct wl_client *client,
|
||||
if (region_resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||
surface->pending.opaque_region = cairo_region_copy (region->region);
|
||||
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
||||
surface->pending.opaque_region = cairo_region_copy (cr_region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,7 +561,8 @@ wl_surface_set_input_region (struct wl_client *client,
|
||||
if (region_resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||
surface->pending.input_region = cairo_region_copy (region->region);
|
||||
cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region);
|
||||
surface->pending.input_region = cairo_region_copy (cr_region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +619,7 @@ surface_should_be_reactive (MetaWaylandSurface *surface)
|
||||
return TRUE;
|
||||
|
||||
/* If we're a subsurface, we should be reactive */
|
||||
if (surface->subsurface.resource)
|
||||
if (surface->wl_subsurface)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@@ -734,33 +699,6 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
|
||||
{
|
||||
extension->resource = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_surface_extension (MetaWaylandSurfaceExtension *extension,
|
||||
const struct wl_interface *interface,
|
||||
const void *implementation,
|
||||
wl_resource_destroy_func_t destructor,
|
||||
MetaWaylandSurface *surface,
|
||||
struct wl_resource *master_resource,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_client *client;
|
||||
|
||||
if (extension->resource != NULL)
|
||||
return FALSE;
|
||||
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
extension->resource = wl_resource_create (client, interface, wl_resource_get_version (master_resource), id);
|
||||
wl_resource_set_implementation (extension->resource, implementation, surface, destructor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_shell_use_unstable_version (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@@ -787,7 +725,7 @@ xdg_surface_destructor (struct wl_resource *resource)
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_surface);
|
||||
surface->xdg_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1025,11 +963,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWindow *window;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_surface,
|
||||
&xdg_surface_interface,
|
||||
&meta_wayland_xdg_surface_interface,
|
||||
xdg_surface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->xdg_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1037,6 +971,9 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->xdg_surface = wl_resource_create (client, &xdg_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->xdg_surface, &meta_wayland_xdg_surface_interface, surface, xdg_surface_destructor);
|
||||
|
||||
surface->xdg_shell_resource = resource;
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
@@ -1049,7 +986,7 @@ xdg_popup_destructor (struct wl_resource *resource)
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_window (surface);
|
||||
destroy_surface_extension (&surface->xdg_popup);
|
||||
surface->xdg_popup = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1079,15 +1016,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWindow *window;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_popup,
|
||||
&xdg_popup_interface,
|
||||
&meta_wayland_xdg_popup_interface,
|
||||
xdg_popup_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->xdg_popup != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1095,9 +1029,12 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->xdg_popup = wl_resource_create (client, &xdg_popup_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->xdg_popup, &meta_wayland_xdg_popup_interface, surface, xdg_popup_destructor);
|
||||
|
||||
surface->xdg_shell_resource = resource;
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
window = meta_window_wayland_new (display, surface);
|
||||
meta_window_move_frame (window, FALSE,
|
||||
parent_surf->window->rect.x + x,
|
||||
parent_surf->window->rect.y + y);
|
||||
@@ -1108,6 +1045,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
|
||||
meta_window_focus (window, meta_display_get_current_time (display));
|
||||
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
|
||||
}
|
||||
|
||||
@@ -1141,7 +1079,7 @@ wl_shell_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->wl_shell_surface);
|
||||
surface->wl_shell_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1349,11 +1287,7 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWindow *window;
|
||||
|
||||
if (!create_surface_extension (&surface->wl_shell_surface,
|
||||
&wl_shell_surface_interface,
|
||||
&meta_wayland_wl_shell_surface_interface,
|
||||
wl_shell_surface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->wl_shell_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1361,6 +1295,9 @@ wl_shell_get_shell_surface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->wl_shell_surface = wl_resource_create (client, &wl_shell_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->wl_shell_surface, &meta_wayland_wl_shell_surface_interface, surface, wl_shell_surface_destructor);
|
||||
|
||||
window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
}
|
||||
@@ -1386,7 +1323,7 @@ gtk_surface_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
|
||||
destroy_surface_extension (&surface->gtk_surface);
|
||||
surface->gtk_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1429,17 +1366,16 @@ get_gtk_surface (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->gtk_surface,
|
||||
>k_surface_interface,
|
||||
&meta_wayland_gtk_surface_interface,
|
||||
gtk_surface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->gtk_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"gtk_shell::get_gtk_surface already requested");
|
||||
return;
|
||||
}
|
||||
|
||||
surface->gtk_surface = wl_resource_create (client, >k_surface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->gtk_surface, &meta_wayland_gtk_surface_interface, surface, gtk_surface_destructor);
|
||||
}
|
||||
|
||||
static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = {
|
||||
@@ -1540,7 +1476,7 @@ wl_subsurface_destructor (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
pending_state_destroy (&surface->sub.pending);
|
||||
destroy_surface_extension (&surface->subsurface);
|
||||
surface->wl_subsurface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1666,7 +1602,7 @@ wl_subsurface_set_desync (struct wl_client *client,
|
||||
surface->sub.synchronous = FALSE;
|
||||
}
|
||||
|
||||
static const struct wl_subsurface_interface meta_wayland_subsurface_interface = {
|
||||
static const struct wl_subsurface_interface meta_wayland_wl_subsurface_interface = {
|
||||
wl_subsurface_destroy,
|
||||
wl_subsurface_set_position,
|
||||
wl_subsurface_place_above,
|
||||
@@ -1704,11 +1640,7 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
|
||||
if (!create_surface_extension (&surface->subsurface,
|
||||
&wl_subsurface_interface,
|
||||
&meta_wayland_subsurface_interface,
|
||||
wl_subsurface_destructor,
|
||||
surface, resource, id))
|
||||
if (surface->wl_subsurface != NULL)
|
||||
{
|
||||
wl_resource_post_error (surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
@@ -1716,6 +1648,9 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
return;
|
||||
}
|
||||
|
||||
surface->wl_subsurface = wl_resource_create (client, &wl_subsurface_interface, wl_resource_get_version (resource), id);
|
||||
wl_resource_set_implementation (surface->wl_subsurface, &meta_wayland_wl_subsurface_interface, surface, wl_subsurface_destructor);
|
||||
|
||||
pending_state_init (&surface->sub.pending);
|
||||
surface->sub.synchronous = TRUE;
|
||||
surface->sub.parent = parent;
|
||||
@@ -1807,9 +1742,9 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int new_height,
|
||||
MetaWaylandSerial *sent_serial)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
if (surface->xdg_surface)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
struct wl_array states;
|
||||
@@ -1823,7 +1758,7 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
new_width /= surface->scale;
|
||||
new_height /= surface->scale;
|
||||
|
||||
xdg_surface_send_configure (surface->xdg_surface.resource, new_width, new_height, &states, serial);
|
||||
xdg_surface_send_configure (surface->xdg_surface, new_width, new_height, &states, serial);
|
||||
|
||||
wl_array_release (&states);
|
||||
|
||||
@@ -1833,13 +1768,13 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
sent_serial->value = serial;
|
||||
}
|
||||
}
|
||||
else if (surface->xdg_popup.resource)
|
||||
else if (surface->xdg_popup)
|
||||
{
|
||||
/* This can happen if the popup window loses or receives focus.
|
||||
* Just ignore it. */
|
||||
}
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface.resource,
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_configure (surface->wl_shell_surface,
|
||||
0, new_width, new_height);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
@@ -1851,15 +1786,15 @@ meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
{
|
||||
if (surface->xdg_shell_resource)
|
||||
xdg_shell_send_ping (surface->xdg_shell_resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial);
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_ping (surface->wl_shell_surface, serial);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_delete (MetaWaylandSurface *surface)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
xdg_surface_send_close (surface->xdg_surface.resource);
|
||||
if (surface->xdg_surface)
|
||||
xdg_surface_send_close (surface->xdg_surface);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1869,8 +1804,8 @@ meta_wayland_surface_popup_done (MetaWaylandSurface *surface)
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
if (surface->xdg_popup.resource)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup.resource, serial);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource);
|
||||
if (surface->xdg_popup)
|
||||
xdg_popup_send_popup_done (surface->xdg_popup, serial);
|
||||
else if (surface->wl_shell_surface)
|
||||
wl_shell_surface_send_popup_done (surface->wl_shell_surface);
|
||||
}
|
||||
|
@@ -36,16 +36,6 @@ struct _MetaWaylandSerial {
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
struct _MetaWaylandBuffer
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_signal destroy_signal;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
CoglTexture *texture;
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* wl_surface.attach */
|
||||
@@ -70,30 +60,35 @@ typedef struct
|
||||
gboolean has_new_geometry;
|
||||
} MetaWaylandPendingState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandSurfaceExtension;
|
||||
|
||||
struct _MetaWaylandSurface
|
||||
{
|
||||
/* Generic stuff */
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
MetaWindow *window;
|
||||
struct wl_resource *xdg_shell_resource;
|
||||
MetaWaylandSurfaceExtension xdg_surface;
|
||||
MetaWaylandSurfaceExtension xdg_popup;
|
||||
MetaWaylandSurfaceExtension wl_shell_surface;
|
||||
MetaWaylandSurfaceExtension gtk_surface;
|
||||
MetaWaylandSurfaceExtension subsurface;
|
||||
int scale;
|
||||
|
||||
MetaWaylandBuffer *buffer;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
|
||||
int scale;
|
||||
int32_t offset_x, offset_y;
|
||||
GList *subsurfaces;
|
||||
|
||||
/* All the pending state that wl_surface.commit will apply. */
|
||||
MetaWaylandPendingState pending;
|
||||
|
||||
/* Extension resources. */
|
||||
struct wl_resource *xdg_surface;
|
||||
struct wl_resource *xdg_popup;
|
||||
struct wl_resource *wl_shell_surface;
|
||||
struct wl_resource *gtk_surface;
|
||||
struct wl_resource *wl_subsurface;
|
||||
|
||||
/* xdg_surface stuff */
|
||||
struct wl_resource *xdg_shell_resource;
|
||||
MetaWaylandSerial acked_configure_serial;
|
||||
gboolean has_set_geometry;
|
||||
|
||||
/* wl_subsurface stuff. */
|
||||
struct {
|
||||
MetaWaylandSurface *parent;
|
||||
struct wl_listener parent_destroy_listener;
|
||||
@@ -114,15 +109,6 @@ struct _MetaWaylandSurface
|
||||
gboolean pending_pos;
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
int32_t offset_x, offset_y;
|
||||
|
||||
gboolean has_set_geometry;
|
||||
|
||||
/* All the pending state that wl_surface.commit will apply. */
|
||||
MetaWaylandPendingState pending;
|
||||
|
||||
MetaWaylandSerial acked_configure_serial;
|
||||
};
|
||||
|
||||
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
|
||||
|
@@ -32,7 +32,7 @@ typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
|
||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||
|
||||
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
|
||||
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
|
||||
typedef struct _MetaWaylandRegion MetaWaylandRegion;
|
||||
|
||||
typedef struct _MetaWaylandSurface MetaWaylandSurface;
|
||||
|
||||
|
@@ -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 1
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 2
|
||||
#define META_XDG_SHELL_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 4
|
||||
|
@@ -19,40 +19,26 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/wayland/clutter-wayland-compositor.h>
|
||||
#include <clutter/wayland/clutter-wayland-surface.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include <meta/meta-backend.h>
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-wayland-region.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-outputs.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
#include <meta/types.h>
|
||||
#include <meta/main.h>
|
||||
#include "frame.h"
|
||||
|
||||
static MetaWaylandCompositor _meta_wayland_compositor;
|
||||
|
||||
@@ -70,6 +56,13 @@ get_time (void)
|
||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GSource source;
|
||||
GPollFD pfd;
|
||||
struct wl_display *display;
|
||||
} WaylandEventSource;
|
||||
|
||||
static gboolean
|
||||
wayland_event_source_prepare (GSource *base, int *timeout)
|
||||
{
|
||||
@@ -126,61 +119,6 @@ wayland_event_source_new (struct wl_display *display)
|
||||
return &source->source;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
|
||||
void *data)
|
||||
{
|
||||
MetaWaylandBuffer *buffer =
|
||||
wl_container_of (listener, buffer, destroy_listener);
|
||||
|
||||
wl_signal_emit (&buffer->destroy_signal, buffer);
|
||||
g_slice_free (MetaWaylandBuffer, buffer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
buffer->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
buffer->ref_count--;
|
||||
if (buffer->ref_count == 0)
|
||||
{
|
||||
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
||||
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
||||
}
|
||||
}
|
||||
|
||||
MetaWaylandBuffer *
|
||||
meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandBuffer *buffer;
|
||||
struct wl_listener *listener;
|
||||
|
||||
listener =
|
||||
wl_resource_get_destroy_listener (resource,
|
||||
meta_wayland_buffer_destroy_handler);
|
||||
|
||||
if (listener)
|
||||
{
|
||||
buffer = wl_container_of (listener, buffer, destroy_listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = g_slice_new0 (MetaWaylandBuffer);
|
||||
|
||||
buffer->resource = resource;
|
||||
wl_signal_init (&buffer->destroy_signal);
|
||||
buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
|
||||
wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
@@ -202,91 +140,23 @@ wl_compositor_create_surface (struct wl_client *client,
|
||||
guint32 id)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_wayland_surface_create (compositor, client, resource, id);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_region_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_region_add (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
gint32 x,
|
||||
gint32 y,
|
||||
gint32 width,
|
||||
gint32 height)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
cairo_rectangle_int_t rectangle = { x, y, width, height };
|
||||
|
||||
cairo_region_union_rectangle (region->region, &rectangle);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_region_subtract (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
gint32 x,
|
||||
gint32 y,
|
||||
gint32 width,
|
||||
gint32 height)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
cairo_rectangle_int_t rectangle = { x, y, width, height };
|
||||
|
||||
cairo_region_subtract_rectangle (region->region, &rectangle);
|
||||
}
|
||||
|
||||
static const struct wl_region_interface meta_wayland_region_interface = {
|
||||
wl_region_destroy,
|
||||
wl_region_add,
|
||||
wl_region_subtract
|
||||
};
|
||||
|
||||
static void
|
||||
meta_wayland_region_resource_destroy_cb (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandRegion *region = wl_resource_get_user_data (resource);
|
||||
|
||||
cairo_region_destroy (region->region);
|
||||
g_slice_free (MetaWaylandRegion, region);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_compositor_create_region (struct wl_client *client,
|
||||
struct wl_resource *compositor_resource,
|
||||
struct wl_resource *resource,
|
||||
uint32_t id)
|
||||
{
|
||||
MetaWaylandRegion *region = g_slice_new0 (MetaWaylandRegion);
|
||||
|
||||
region->resource = wl_resource_create (client, &wl_region_interface, wl_resource_get_version (compositor_resource), id);
|
||||
wl_resource_set_implementation (region->resource, &meta_wayland_region_interface, region, meta_wayland_region_resource_destroy_cb);
|
||||
|
||||
region->region = cairo_region_create ();
|
||||
MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource);
|
||||
meta_wayland_region_create (compositor, client, resource, id);
|
||||
}
|
||||
|
||||
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
|
||||
const static struct wl_compositor_interface meta_wayland_wl_compositor_interface = {
|
||||
wl_compositor_create_surface,
|
||||
wl_compositor_create_region
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
while (!wl_list_empty (&compositor->frame_callbacks))
|
||||
{
|
||||
MetaWaylandFrameCallback *callback =
|
||||
wl_container_of (compositor->frame_callbacks.next, callback, link);
|
||||
|
||||
wl_callback_send_done (callback->resource, get_time ());
|
||||
wl_resource_destroy (callback->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
compositor_bind (struct wl_client *client,
|
||||
void *data,
|
||||
@@ -297,7 +167,7 @@ compositor_bind (struct wl_client *client,
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &wl_compositor_interface, version, id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_compositor_interface, compositor, NULL);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_wl_compositor_interface, compositor, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,6 +186,19 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
meta_wayland_seat_update (compositor->seat, event);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
while (!wl_list_empty (&compositor->frame_callbacks))
|
||||
{
|
||||
MetaWaylandFrameCallback *callback =
|
||||
wl_container_of (compositor->frame_callbacks.next, callback, link);
|
||||
|
||||
wl_callback_send_done (callback->resource, get_time ());
|
||||
wl_resource_destroy (callback->resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_wayland_compositor_handle_event:
|
||||
* @compositor: the #MetaWaylandCompositor instance
|
||||
@@ -385,7 +268,6 @@ meta_wayland_pre_clutter_init (void)
|
||||
|
||||
meta_wayland_compositor_init (compositor);
|
||||
|
||||
/* Set up our logging. */
|
||||
wl_log_set_handler_server (meta_wayland_log_func);
|
||||
|
||||
compositor->wayland_display = wl_display_create ();
|
||||
@@ -401,12 +283,6 @@ meta_wayland_init (void)
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
GSource *wayland_event_source;
|
||||
|
||||
if (!wl_global_create (compositor->wayland_display,
|
||||
&wl_compositor_interface,
|
||||
META_WL_COMPOSITOR_VERSION,
|
||||
compositor, compositor_bind))
|
||||
g_error ("Failed to register the global wl_compositor");
|
||||
|
||||
wayland_event_source = wayland_event_source_new (compositor->wayland_display);
|
||||
|
||||
/* XXX: Here we are setting the wayland event source to have a
|
||||
@@ -414,13 +290,16 @@ meta_wayland_init (void)
|
||||
* much more likely to get confused being told about surface changes
|
||||
* relating to X clients when we don't know what's happened to them
|
||||
* according to the X protocol.
|
||||
*
|
||||
* At some point we could perhaps try and get the X protocol proxied
|
||||
* over the wayland protocol so that we don't have to worry about
|
||||
* synchronizing the two command streams. */
|
||||
*/
|
||||
g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1);
|
||||
g_source_attach (wayland_event_source, NULL);
|
||||
|
||||
if (!wl_global_create (compositor->wayland_display,
|
||||
&wl_compositor_interface,
|
||||
META_WL_COMPOSITOR_VERSION,
|
||||
compositor, compositor_bind))
|
||||
g_error ("Failed to register the global wl_compositor");
|
||||
|
||||
wl_display_init_shm (compositor->wayland_display);
|
||||
|
||||
meta_wayland_outputs_init (compositor);
|
||||
@@ -428,21 +307,10 @@ meta_wayland_init (void)
|
||||
meta_wayland_shell_init (compositor);
|
||||
meta_wayland_seat_init (compositor);
|
||||
|
||||
/* FIXME: find the first free name instead */
|
||||
compositor->display_name = wl_display_add_socket_auto (compositor->wayland_display);
|
||||
if (compositor->display_name == NULL)
|
||||
g_error ("Failed to create socket");
|
||||
|
||||
/* XXX: It's important that we only try and start xwayland after we
|
||||
* have initialized EGL because EGL implements the "wl_drm"
|
||||
* interface which xwayland requires to determine what drm device
|
||||
* name it should use.
|
||||
*
|
||||
* By waiting until we've shown the stage above we ensure that the
|
||||
* underlying GL resources for the surface have also been allocated
|
||||
* and so EGL must be initialized by this point.
|
||||
*/
|
||||
|
||||
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
|
||||
g_error ("Failed to start X Wayland");
|
||||
|
||||
|
@@ -23,6 +23,8 @@
|
||||
#ifndef META_WAYLAND_H
|
||||
#define META_WAYLAND_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/types.h>
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
void meta_wayland_pre_clutter_init (void);
|
||||
|
@@ -509,8 +509,6 @@ meta_window_x11_manage (MetaWindow *window)
|
||||
meta_icon_cache_init (&priv->icon_cache);
|
||||
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
meta_window_x11_update_shape_region (window);
|
||||
meta_window_x11_update_input_region (window);
|
||||
|
||||
/* assign the window to its group, or create a new group if needed */
|
||||
window->group = NULL;
|
||||
@@ -568,6 +566,9 @@ meta_window_x11_manage (MetaWindow *window)
|
||||
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
|
||||
meta_window_move_resize_internal (window, flags, gravity, rect);
|
||||
}
|
||||
|
||||
meta_window_x11_update_shape_region (window);
|
||||
meta_window_x11_update_input_region (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1683,7 +1684,7 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
/* Translate the set of XShape rectangles that we
|
||||
* get from the X server to a cairo_region. */
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, ordering;
|
||||
int n_rects = -1, ordering;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||
@@ -1693,21 +1694,46 @@ meta_window_x11_update_input_region (MetaWindow *window)
|
||||
&ordering);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* XXX: The x shape extension doesn't provide a way to only test if an
|
||||
* input shape has been specified, so we have to query and throw away the
|
||||
* rectangles. */
|
||||
if (rects)
|
||||
{
|
||||
if (n_rects > 1 ||
|
||||
(n_rects == 1 &&
|
||||
(rects[0].x != 0 ||
|
||||
rects[0].y != 0 ||
|
||||
rects[0].width != priv->client_rect.width ||
|
||||
rects[0].height != priv->client_rect.height)))
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
/* XXX: The X Shape specification is quite unfortunately specified.
|
||||
*
|
||||
* By default, the window has a shape the same as its bounding region,
|
||||
* which we consider "NULL".
|
||||
*
|
||||
* If the window sets an empty region, then we'll get n_rects as 0
|
||||
* and rects as NULL, which we need to transform back into an empty
|
||||
* region.
|
||||
*
|
||||
* It would be great to have a less-broken extension for this, but
|
||||
* hey, it's X11!
|
||||
*/
|
||||
|
||||
XFree (rects);
|
||||
if (n_rects == -1)
|
||||
{
|
||||
/* We had an error. */
|
||||
region = NULL;
|
||||
}
|
||||
else if (n_rects == 0)
|
||||
{
|
||||
/* Client set an empty region. */
|
||||
region = cairo_region_create ();
|
||||
}
|
||||
else if (n_rects == 1 &&
|
||||
(rects[0].x == 0 ||
|
||||
rects[0].y == 0 ||
|
||||
rects[0].width == priv->client_rect.width ||
|
||||
rects[0].height == priv->client_rect.height))
|
||||
{
|
||||
/* This is the bounding region case. Keep the
|
||||
* region as NULL. */
|
||||
region = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Window has a custom shape. */
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
}
|
||||
|
||||
meta_XFree (rects);
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
|
Reference in New Issue
Block a user