Compare commits

..

2 Commits

Author SHA1 Message Date
Milan Crha
13ddf1eb83 calendar-server: Add 'Dismiss' button and application action
- adds 'Dismiss' button to the notification
- introduces org.gnome.Shell.CalendarServer.desktop.in.in to benefit from GNotification API

Related to https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1064
2020-03-03 15:58:13 +01:00
Milan Crha
15ab33a11a Move functionality from evolution-alarm-notify to gnome-shell-calendar-server
Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/155
2020-03-03 12:00:27 +01:00
226 changed files with 17088 additions and 25641 deletions

1
.gitignore vendored
View File

@@ -60,6 +60,7 @@ src/calendar-server/evolution-calendar.desktop
src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell
src/gnome-shell-calendar-server
src/gnome-shell-extension-prefs
src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer
src/gnome-shell-perf-helper

View File

@@ -1,13 +1,9 @@
include: 'https://gitlab.gnome.org/GNOME/citemplates/raw/master/flatpak/flatpak_ci_initiative.yml'
stages:
- review
- build
- test
- deploy
variables:
BUNDLE: "extensions-git.flatpak"
JS_LOG: "js-report.txt"
POT_LOG: "pot-update.txt"
@@ -114,24 +110,3 @@ test-pot:
' | tee $POT_LOG
- (! grep -q . $POT_LOG)
<<: *only_default
flatpak:
stage: build
variables:
SUBPROJECT: "subprojects/extensions-app"
# Your manifest path
MANIFEST_PATH: "$SUBPROJECT/build-aux/flatpak/org.gnome.Extensions.json"
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
FLATPAK_MODULE: "gnome-extensions-app"
APP_ID: "org.gnome.Extensions"
MESON_ARGS: "$SUBPROJECT"
extends: .flatpak
before_script:
- flatpak run --command=$SUBPROJECT/generate-translations.sh
--filesystem=host org.gnome.Sdk//master
<<: *only_default
nightly:
extends: '.publish_nightly'
variables:
BUNDLES: '$BUNDLE'

View File

@@ -23,7 +23,7 @@ run_eslint() {
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js subprojects/extensions-app/js
eslint -f unix ${!extra_args} -o $output js
}
list_commit_range_additions() {

164
NEWS
View File

@@ -1,167 +1,3 @@
3.36.4
======
* Hide switch-user button on lock screen if unsupported [Chingkai; #2687]
* Improve world clocks styling [PrOF-kk; #2825]
* Improve calendar-server performance [Florian, Milan; #1875]
* Fix regressions in redesigned modal dialogs [Florian, Jonas; #2491, !1336]
* Better support sandboxed apps with multiple .desktop files [Florian; #219]
* Fix on-screen keyboard size in portrait orientation [Florian; #2349]
* Support scrolling anywhere in slider menu items [Peter; #2795]
* Fixed crash [Marco; #2643]
* Plugged leaks [Sebastian, Florian; !1306, !1341]
* Misc. bug fixes and cleanups [Jonas, Daniel, Florian, Sebastian, MOZGIII,
Koki; !1119, !1289, !1331, !1192, !1340, !1327, !1279]
Contributors:
Marco Trevisan (Treviño), Chingkai, Milan Crha, Jonas Dreßler, Koki Fukuda,
Sebastian Keller, MOZGIII, Robert Mader, Florian Müllner, PrOF-kk,
Peter Simonyi, Daniel van Vugt
Translators:
Matej Urbančič [sl], sicklylife [ja], Fabio Tomat [fur],
Baurzhan Muftakhidinov [kk], Daniel Șerbănescu [ro]
3.36.3
======
* Add gnome-shell-extension-prefs wrapper for compatibility [Florian; !1220]
* Fix distorted fallback icons in top bar [Florian; #2578]
* Lower timeout for scrolling in overview [Alexander; #2602]
* Only start systemd units when running under systemd
[Carlos, Florian; #2755, !1242, !1252]
* Fix "ghost" media controls [Bryan; #2776]
* Fix zombie sockets from extensions downloader [Michael; #2774]
* Update world clocks offsets when timezone changes [Bryan; #2209]
* Fix "Do Not Disturb" setting getting reset on startup [Florian; #2804]
* Fix pad OSD glitches [Carlos; !1290]
* Fix matching notifications by PID [Florian; #2592]
* Only allow updates for extensions that aren't cached [Florian; !1248]
* Fixed crashes [Jonas, Florian; #2709, #2757]
* Misc. bug fixes and cleanups [Michael, Piotr, Philip, Florian, Amr,
AsciiWolf; !1233, !1205, !1229, #2751, !1232, #2796, !1249, !1263,
!1277, #2286, !1288, !1291]
Contributors:
AsciiWolf, Michael Catanzaro, Philip Chimento, Jonas Dreßler, Bryan Dunsmore,
Carlos Garnacho, Amr Ibrahim, Michael Lass, Alexander Mikhaylenko,
Florian Müllner
Translators:
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Dušan Kazik [sk],
Piotr Drąg [pl], Daniel Mustieles [es], Nathan Follens [nl],
Bruce Cowan [en_GB], Florentina Mușat [ro], Yuri Chornoivan [uk],
Milo Casagrande [it], Anders Jonsson [sv], Charles Monzat [fr],
Daniel Șerbănescu [ro], sicklylife [ja], Kukuh Syafaat [id],
Emin Tufan Çetin [tr], Jiri Grönroos [fi], Марко Костић [sr],
Christian Kirbach [de], Changwoo Ryu [ko], Aurimas Černius [lt],
Matej Urbančič [sl]
3.36.2
======
* Add openPrefs() convenience method for extensions [Florian; !1163]
* Bring back support for empty StIcons [Andre, Jonas D.; !1173, !1178]
* Wake up screen when unlocking programmatically [Florian; !1158]
* Improve handling of scale-factor changes [Georges; !1176]
* Fix translations of folder names [Florian; #2623]
* Fix delay on lock screen after entering wrong password [Jonas D.; #2655]
* Match ASCII alternatives of system actions [Will; #2688]
* Tone down weekend days with events in calendar [Jakub; #2588]
* Fix area screenshots on multi-monitor systems [Jonas Å; !1224]
* Fix stuck lock screen after unlock [Jonas D., Florian; #2446]
* Fixed crashes [Jonas D., Florian, Carlos; #2584, #2625, !1223, !1218]
* Misc. bug fixes and cleanups [Jonas Å., Marco, Andre, Florian, Jonas D.;
!1155, !1156, !1169, !1168, #2551, #2563, !1172, !1179, !1160, #2562, #2578,
!1203, #2649, #2628, #2691, #1615, #2607, !1228]
Contributors:
Marco Trevisan (Treviño), Jonas Dreßler, Carlos Garnacho,
Andre Moreira Magalhaes, Florian Müllner, Georges Basile Stavracas Neto,
Jakub Steiner, Will Thompson, Jonas Ådahl
Translators:
Fabio Tomat [fur], Cheng-Chia Tseng [zh_TW], Danial Behzadi [fa],
Jiri Grönroos [fi], Ibai Oihanguren Sala [eu], Марко Костић [sr],
Rūdolfs Mazurs [lv], Rafael Fontenelle [pt_BR], Petr Kovář [cs],
Daniel Rusek [cs]
3.36.1
======
* Improve app folders [Jonas D.; !1011]
* Fix launching ibus daemon [Alynx; !1080]
* Do not shutdown ibus/xsettings on X11 compositor restart [Carlos; #2329]
* Hide hint text in entries when preedit is used [Carlos; !1084]
* Do not load app infos on main thread [Christian; #2282]
* Don't expose FDO Notifications interface on main bus name [Florian; !547]
* Fix icon of mobile broadband connections [Cosimo, Reik; !1097, !1105]
* Fix high-contrast/symbolic icon mix-up [Florian; #2414]
* Don't ellipsize times in world clock [Florian; !1090]
* Only check for extension updates if there are any extensions [Florian; !1100]
* Fix crash when trying to update removed extensions [Florian; #2343]
* Make Extensions app available as flatpak [Florian; !1081, !1106, !1087, !1133]
* Display fractional timezones as hours:minutes [Jonas D.; #2438]
* Fix assigning pad keybindings [Carlos; #2451]
* Handle embedded newlines in lock screen notifications [Florian; #2463]
* Fix OSK layout fallback for unsupported variants [Florian; #2471]
* Do not apply text color to color glyphs (emojis) [Carlos; #850]
* Check "Install pending software updates" by default [Michael; #2427]
* Do not warn about missing GDM on each login [Florian; #2432]
* Fix telepathy chat notifications [Marco; !1112]
* Fix offline updates support in end session dialog [Michael; #2276]
* Fix activating notifications by keyboard [Florian; #2319]
* Remove handling of 'blacklisted' extensions [Florian; !1132]
* Only update extensions if Extensions app is installed [Florian; #2346]
* Improve Norwegian on-screen-keyboard layout [Bjørn; !1073]
* Fix IM support for deleting surrounding text [Takao; !477]
* Fix blur effect with fractional scaling [Jonas D.; !1000]
* Use better location name in weather section [Florian; #2468]
* Fix glitch in sound feedback on volume changes [Florian; !1147]
* Fix on-screen keyboard regressions [Jonas D.; !1142]
* Improve screen-reader support [Luke; #2508, #2517]
* Fix password entry resize on login/lock screen [Florian; #2423]
* Fix crash when opening app picker [Jonas Å.; !1154]
* Misc. bug fixes and cleanups [Florian, Sebastian, Jan, Daniel, Philip, Mario,
Ray, Marco, Jonas D., Carlos, Georges; #2298, #2305, !1078, !1077, #2334,
#2381, !1093, !1098, #2386, !1108, !1109, !1114, !1076, !1072, !1115, !1088,
!1101, #2467, !1121, !1122, #2476, !1123, !1117, !1129, !1113, !1102, !1127,
#2238, !1131, !1135, !1136, !849, #2504, #2371, !1146, !1141, #2510, !1150]
Contributors:
Marco Trevisan (Treviño), Michael Catanzaro, Cosimo Cecchi, Jonas Dreßler,
Takao Fujiwara, Carlos Garnacho, Christian Hergert, Sebastian Keller,
Reik Keutterling, Bjørn Lie, Florian Müllner, Jwtiyar Nariman,
Georges Basile Stavracas Neto, Mario Sanchez Prada, Ray Strode, Jan Tojnar,
Daniel van Vugt, Philip Withnall, Luke Yelavich, Alynx Zhou, Jonas Ådahl
Translators:
Марко Костић [sr], Jordi Mas [ca], sicklylife [ja], Marek Černocký [cs],
Daniel Rusek [cs], Kjartan Maraas [nb], Tim Sabsch [de], Stas Solovey [ru],
Peter Mráz [sk], Rafael Fontenelle [pt_BR], Piotr Drąg [pl],
Milo Casagrande [it], Anders Jonsson [sv], Yuri Chornoivan [uk],
Kukuh Syafaat [id], Guillaume Bernard [fr], Daniel Mustieles [es],
Danial Behzadi [fa], Goran Vidović [hr], Yosef Or Boczko [he],
Emin Tufan Çetin [tr], Wolfgang Stöggl [de], Ibai Oihanguren Sala [eu],
Jwtiyar Nariman [ckb], Aurimas Černius [lt]
3.36.0
======
* Fix off-by-1900 error in date conversions [Florian; !1061]
* Fix crash on startup with topIcons* extension enabled [Florian; #2308]
* Don't require gsd-xsettings for X11 support on wayland [Olivier; !1065]
* Fix ibus support in Xorg session [Carlos; #1690]
* Improve Extensions D-Bus API [Florian; !1074]
* Allow session modes to specify alternative resource name [Marco; !1063]
* Fix link to location settings in aggregate menu [Sebastian; #2316]
* Fix illegible app folder titles with light theme [ub; !1059]
* Really fix visual glitch in sliders [Jonas; #1569]
Contributors:
Marco Trevisan (Treviño), Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Sebastian Keller, Florian Müllner, ub
Translators:
Aman Alam [pa], Goran Vidović [hr], Aurimas Černius [lt],
Milo Casagrande [it], Daniel Korostil [uk], sicklylife [ja],
Marek Černocký [cs], Nathan Follens [nl]
3.35.92
=======
* Plug a memory leak [Jonas D.; !1015]

View File

@@ -161,16 +161,12 @@ def convert_file(source_file, destination_path):
try:
xkb_name = locale_to_xkb(root["locale"], root["name"])
except KeyError as e:
logging.warning(e)
logging.warn(e)
return False
destination_file = os.path.join(destination_path, xkb_name + ".json")
try:
with open(destination_file, 'x', encoding="utf-8") as dest_fd:
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
except FileExistsError as e:
logging.info("File %s exists, not updating", destination_file)
return False
with open(destination_file, 'w', encoding="utf-8") as dest_fd:
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
logging.debug("written %s", destination_file)

View File

@@ -5,7 +5,7 @@
<arg type="x" name="until" direction="in"/>
<arg type="b" name="force_reload" direction="in"/>
</method>
<signal name="EventsAddedOrUpdated">
<signal name="EventsAdded">
<arg type="a(ssbxxa{sv})" name="events" direction="out"/>
</signal>
<signal name="EventsRemoved">

View File

@@ -199,37 +199,14 @@
<!--
LaunchExtensionPrefs:
Deprecated for OpenExtensionPrefs
@uuid: The UUID of the extension
Launch preferences of an extension.
-->
<method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
</method>
<!--
OpenExtensionPrefs:
@uuid: The UUID of the extension
@parent_window: Identifier for the application window
@options: Vardict with further options
Opens the prefs dialog of extension @uuid.
The following @options are recognized:
<variablelist>
<varlistentry>
<term>modal b</term>
<listitem>
<para>Whether the prefs window should be modal, default: false</para>
</listitem>
</varlistentry>
</variablelist>
-->
<method name="OpenExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="in" name="parent_window"/>
<arg type="a{sv}" direction="in" name="options"/>
</method>
<!--
CheckForUpdates:
Update all extensions for which updates are available
@@ -257,11 +234,5 @@
-->
<property name="ShellVersion" type="s" access="read"/>
<!--
UserExtensionsEnabled:
Whether user extensions are enabled
-->
<property name="UserExtensionsEnabled" type="b" access="readwrite"/>
</interface>
</node>

View File

@@ -19,10 +19,6 @@ Before=gnome-session-initialized.target
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# unset some environment variables that were set by the shell and won't work now that the shell is gone
ExecStopPost=-systemctl --user unset-environment GNOME_SETUP_DISPLAY WAYLAND_DISPLAY DISPLAY XAUTHORITY
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On wayland we cannot restart

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M6.5 1.031c-.371 0-.742-.035-1.11.016-.367.05-.73.203-.972.476-.125.141-.215.309-.266.485-.047.18-.054.367-.02.55.032.184.102.356.192.516.09.164.203.309.317.457L5 4H2a1.8 1.8 0 00-.41.035.791.791 0 00-.36.195.791.791 0 00-.195.36C1 4.723 1 4.863 1 5v2.75l.77-.344c.265-.117.542-.23.832-.242.289-.016.586.074.812.254.227.18.383.441.465.723.082.277.101.57.121.859.02.316.04.637-.016.95-.058.312-.199.616-.43.831a1.264 1.264 0 01-.874.32c-.317-.007-.618-.128-.91-.257L1 10.5V14c0 .137.004.277.035.41a.791.791 0 00.195.36c.098.097.227.16.36.195.133.035.273.035.41.035h3l-.328-.68c-.14-.293-.274-.597-.29-.922-.015-.32.095-.652.31-.894.214-.242.523-.39.84-.453.316-.067.644-.059.968-.059.324 0 .652-.008.969.059.316.062.625.21.84.453.214.242.324.574.308.894-.015.325-.148.63-.289.922L8 15h3a1.8 1.8 0 00.41-.035.791.791 0 00.36-.195.791.791 0 00.195-.36C12 14.277 12 14.137 12 14v-3.563l.703.297c.29.125.59.239.902.246.313.004.63-.101.864-.308.238-.203.386-.496.46-.8C15 9.565 15 9.25 15 8.937c0-.313 0-.63-.07-.934-.075-.305-.223-.598-.461-.8a1.288 1.288 0 00-.864-.31c-.312.008-.613.122-.902.247L12 7.437V5a1.8 1.8 0 00-.035-.41.791.791 0 00-.195-.36.791.791 0 00-.36-.195C11.277 4 11.137 4 11 4H8l.36-.469c.113-.148.226-.293.316-.457.09-.16.16-.332.191-.515a1.248 1.248 0 00-.02-.551 1.256 1.256 0 00-.265-.485c-.242-.273-.605-.425-.973-.476-.367-.05-.738-.016-1.109-.016zm0 0" fill="#474747"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,6 +1,7 @@
desktop_files = [
'org.gnome.Shell.desktop',
'org.gnome.Shell.Extensions.desktop',
'org.gnome.Shell.CalendarServer.desktop',
'org.gnome.Extensions.desktop',
]
service_files = []
@@ -13,6 +14,7 @@ desktopconf = configuration_data()
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
desktopconf.set('bindir', bindir)
desktopconf.set('libexecdir', libexecdir)
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files

View File

@@ -2,9 +2,8 @@
Type=Application
Name=Extensions
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=@app_id@
Icon=org.gnome.Extensions
Comment=Configure GNOME Shell Extensions
Exec=@bindir@/@prgname@
DBusActivatable=true
Categories=GNOME;GTK;Utility;
Exec=@bindir@/gnome-shell-extension-prefs %u
Categories=GNOME;GTK;
OnlyShowIn=GNOME;

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=Clock Applet
Icon=appointment-soon
Exec=@libexecdir@/gnome-shell-calendar-server
Terminal=false
Categories=
OnlyShowIn=GNOME
NoDisplay=true

View File

@@ -1,10 +0,0 @@
[Desktop Entry]
Type=Application
# Keep in sync with subprojects/extensions-app
Name=Extensions
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=org.gnome.Shell.Extensions
# Never launch this, just provide name+icon to portal dialog
Exec=false
OnlyShowIn=GNOME;
NoDisplay=true

View File

@@ -12,9 +12,7 @@
"w"
],
[
"e",
"é",
"ë"
"e"
],
[
"r"
@@ -23,58 +21,30 @@
"t"
],
[
"y",
"ý",
"ÿ"
"y"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
"u"
],
[
"i",
"í",
"ï"
"i"
],
[
"o",
"ó",
"ô",
"ò",
"õ",
"œ",
"ō"
"o"
],
[
"p"
],
[
"å"
]
],
[
[
"a",
"á",
"ä",
"à",
"â",
"ã",
"ā"
"a"
],
[
"s",
"ß",
"ś",
"š"
"s"
],
[
"d",
"ð"
"d"
],
[
"f"
@@ -92,16 +62,7 @@
"k"
],
[
"l",
"ł"
],
[
"ø",
"ö"
],
[
"æ",
"ä"
"l"
]
],
[
@@ -121,9 +82,7 @@
"b"
],
[
"n",
"ñ",
"ń"
"n"
],
[
"m"
@@ -162,9 +121,7 @@
"W"
],
[
"E",
"É",
"Ë"
"E"
],
[
"R"
@@ -173,58 +130,30 @@
"T"
],
[
"Y",
"Ý",
"Ÿ"
"Y"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
"U"
],
[
"I",
"Í",
"Ï"
"I"
],
[
"O",
"Ó",
"Ô",
"Ò",
"Õ",
"Œ",
"Ō"
"O"
],
[
"P"
],
[
"Å"
]
],
[
[
"A",
"Á",
"Ä",
"À",
"Â",
"Ã",
"Ā"
"A"
],
[
"S",
"SS",
"Ś",
"Š"
"S"
],
[
"D",
"Ð"
"D"
],
[
"F"
@@ -242,16 +171,7 @@
"K"
],
[
"L",
"Ł"
],
[
"Ø",
"Ö"
],
[
"Æ",
"Ä"
"L"
]
],
[
@@ -271,9 +191,7 @@
"B"
],
[
"N",
"Ñ",
"Ń"
"N"
],
[
"M"
@@ -359,10 +277,10 @@
"#"
],
[
"",
"$",
"¢",
"£",
"$",
"",
"¥",
"₱"
],
@@ -500,16 +418,15 @@
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
@@ -587,4 +504,4 @@
],
"locale": "nb",
"name": "Norwegian Bokmål"
}
}

View File

@@ -35,9 +35,9 @@ $app_grid_fg_color: #fff;
}
/* App Folders */
.app-well-app.app-folder {
background-color: transparentize($osd_bg_color, 0.8);
border-radius: $base_border_radius + 4px; // same as %icon_tile
.app-folder {
.overview-icon {
}
}
// expanded folder
@@ -60,7 +60,7 @@ $app_grid_fg_color: #fff;
& .folder-name-entry { width: 300px }
/* FIXME: this is to keep the label in sync with the entry */
& .folder-name-label { padding: 5px 7px; color: $osd_fg_color; }
& .folder-name-label { padding: 5px 7px }
& .edit-folder-button {
@extend %button;
@@ -73,6 +73,10 @@ $app_grid_fg_color: #fff;
& > StIcon { icon-size: 16px }
}
}
& StButton#vhandle,
& StButton#vhandle:hover,
& StButton#vhandle:active { background-color: transparent; }
}
.app-folder-dialog-container {
padding: 12px;

View File

@@ -153,11 +153,9 @@
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
font-weight: bold;
background-image: url("resource:///org/gnome/shell/theme/calendar-today.svg");
&.calendar-work-day {
color: lighten($fg_color,10%);
font-weight: bold;
}
}
.calendar-other-month-day {
@@ -204,7 +202,7 @@
.world-clocks-time {
font-weight: bold;
color: $fg_color;
font-feature-settings: "tnum";
font-feature-settings: "lnum";
@include fontsize($base_font_size);
text-align: right;
}

View File

@@ -15,11 +15,13 @@
border: 1px solid transparent;
&:outlined {
background-color: transparentize($osd_fg_color, 0.7);
border: 1px solid darken($borders_color,5%);
background-color: transparentize($osd_fg_color, 0.9);
box-shadow: inset 0 2px 2px 0 rgba(0,0,0,0.4);
}
&:selected {
background-color: transparentize($osd_fg_color, 0.7);
background-color: transparentize($osd_fg_color, 0.9);
color: $osd_fg_color;
}
}

View File

@@ -1,9 +1,10 @@
#!/bin/env bash
CLDR_LAYOUTS_TARBALL="http://www.unicode.org/Public/cldr/latest/keyboards.zip"
CLDR2JSON_GIT="git://repo.or.cz/cldr2json.git"
WORKDIR=".osk-layout-workbench"
CLDR2JSON="cldr2json/cldr2json.py"
CLDR2JSON="$WORKDIR/cldr2json/cldr2json.py"
SRCDIR="$WORKDIR/keyboards/android"
DESTDIR="osk-layouts"
GRESOURCE_FILE="gnome-shell-osk-layouts.gresource.xml"
@@ -19,6 +20,7 @@ mkdir -p "osk-layouts"
# Download stuff on the work dir
pushd $WORKDIR
gio copy $CLDR_LAYOUTS_TARBALL .
git clone $CLDR2JSON_GIT
unzip keyboards.zip
popd

View File

@@ -1,5 +0,0 @@
imports.package.start({
name: '@PACKAGE_NAME@',
prefix: '@prefix@',
libdir: '@libdir@',
});

View File

@@ -1,3 +0,0 @@
[D-BUS Service]
Name=@service@
Exec=@gjs@ @pkgdatadir@/@service@

View File

@@ -1,177 +0,0 @@
/* exported DBusService, ServiceImplementation */
const { Gio, GLib } = imports.gi;
const Signals = imports.signals;
const IDLE_SHUTDOWN_TIME = 2; // s
var ServiceImplementation = class {
constructor(info, objectPath) {
this._objectPath = objectPath;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(info, this);
this._injectTracking('return_dbus_error');
this._injectTracking('return_error_literal');
this._injectTracking('return_gerror');
this._injectTracking('return_value');
this._injectTracking('return_value_with_unix_fd_list');
this._senders = new Map();
this._holdCount = 0;
this._hasSignals = this._dbusImpl.get_info().signals.length > 0;
this._shutdownTimeoutId = 0;
// subclasses may override this to disable automatic shutdown
this._autoShutdown = true;
}
// subclasses may override this to own additional names
register() {
}
export() {
this._dbusImpl.export(Gio.DBus.session, this._objectPath);
}
unexport() {
this._dbusImpl.unexport();
}
hold() {
this._holdCount++;
}
release() {
if (this._holdCount === 0) {
logError(new Error('Unmatched call to release()'));
return;
}
this._holdCount--;
if (this._holdCount === 0)
this._queueShutdownCheck();
}
/**
* _handleError:
* @param {Gio.DBusMethodInvocation}
* @param {Error}
*
* Complete @invocation with an appropriate error if @error is set;
* useful for implementing early returns from method implementations.
*
* @returns {bool} - true if @invocation was completed
*/
_handleError(invocation, error) {
if (error === null)
return false;
if (error instanceof GLib.Error) {
invocation.return_gerror(error);
} else {
let name = error.name;
if (!name.includes('.')) // likely a normal JS error
name = `org.gnome.gjs.JSError.${name}`;
invocation.return_dbus_error(name, error.message);
}
return true;
}
_maybeShutdown() {
if (!this._autoShutdown)
return;
if (this._holdCount > 0)
return;
this.emit('shutdown');
}
_queueShutdownCheck() {
if (this._shutdownTimeoutId)
GLib.source_remove(this._shutdownTimeoutId);
this._shutdownTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT, IDLE_SHUTDOWN_TIME,
() => {
this._shutdownTimeoutId = 0;
this._maybeShutdown();
return GLib.SOURCE_REMOVE;
});
}
_trackSender(sender) {
if (this._senders.has(sender))
return;
this.hold();
this._senders.set(sender,
this._dbusImpl.get_connection().watch_name(
sender,
Gio.BusNameWatcherFlags.NONE,
null,
() => this._untrackSender(sender)));
}
_untrackSender(sender) {
const id = this._senders.get(sender);
if (id)
this._dbusImpl.get_connection().unwatch_name(id);
if (this._senders.delete(sender))
this.release();
}
_injectTracking(methodName) {
const { prototype } = Gio.DBusMethodInvocation;
const origMethod = prototype[methodName];
const that = this;
prototype[methodName] = function (...args) {
origMethod.apply(this, args);
if (that._hasSignals)
that._trackSender(this.get_sender());
that._queueShutdownCheck();
};
}
};
Signals.addSignalMethods(ServiceImplementation.prototype);
var DBusService = class {
constructor(name, service) {
this._name = name;
this._service = service;
this._loop = new GLib.MainLoop(null, false);
this._service.connect('shutdown', () => this._loop.quit());
}
run() {
// Bail out when not running under gnome-shell
Gio.DBus.watch_name(Gio.BusType.SESSION,
'org.gnome.Shell',
Gio.BusNameWatcherFlags.NONE,
null,
() => this._loop.quit());
this._service.register();
Gio.DBus.own_name(Gio.BusType.SESSION,
this._name,
Gio.BusNameOwnerFlags.REPLACE,
() => this._service.export(),
null,
() => this._loop.quit());
this._loop.run();
}
};

View File

@@ -1,2 +0,0 @@
.expander-frame > * { border-top-width: 0; }
.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; }

View File

@@ -1,274 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionsService */
const { Gdk, Gio, GLib, GObject, Gtk, Shew } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ServiceImplementation } = imports.dbusService;
const ExtensionsIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const ExtensionsProxy = Gio.DBusProxy.makeProxyWrapper(ExtensionsIface);
var ExtensionsService = class extends ServiceImplementation {
constructor() {
super(ExtensionsIface, '/org/gnome/Shell/Extensions');
this._proxy = new ExtensionsProxy(Gio.DBus.session,
'org.gnome.Shell', '/org/gnome/Shell');
this._proxy.connectSignal('ExtensionStateChanged',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('ExtensionStateChanged',
new GLib.Variant('(sa{sv})', params));
});
this._proxy.connect('g-properties-changed', () => {
this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
new GLib.Variant('b', this._proxy.UserExtensionsEnabled));
});
}
get ShellVersion() {
return this._proxy.ShellVersion;
}
get UserExtensionsEnabled() {
return this._proxy.UserExtensionsEnabled;
}
set UserExtensionsEnabled(enable) {
this._proxy.UserExtensionsEnabled = enable;
}
ListExtensionsAsync(params, invocation) {
this._proxy.ListExtensionsRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(a{sa{sv}})', res));
});
}
GetExtensionInfoAsync(params, invocation) {
this._proxy.GetExtensionInfoRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(a{sv})', res));
});
}
GetExtensionErrorsAsync(params, invocation) {
this._proxy.GetExtensionErrorsRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(as)', res));
});
}
InstallRemoteExtensionAsync(params, invocation) {
this._proxy.InstallRemoteExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(s)', res));
});
}
UninstallExtensionAsync(params, invocation) {
this._proxy.UninstallExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
EnableExtensionAsync(params, invocation) {
this._proxy.EnableExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
DisableExtensionAsync(params, invocation) {
this._proxy.DisableExtensionRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(b)', res));
});
}
LaunchExtensionPrefsAsync([uuid], invocation) {
this.OpenExtensionPrefsAsync([uuid, '', {}], invocation);
}
OpenExtensionPrefsAsync(params, invocation) {
const [uuid, parentWindow, options] = params;
this._proxy.GetExtensionInfoRemote(uuid, (res, error) => {
if (this._handleError(invocation, error))
return;
const [serialized] = res;
const extension = ExtensionUtils.deserializeExtension(serialized);
const window = new ExtensionPrefsDialog(extension);
window.realize();
let externalWindow = null;
if (parentWindow)
externalWindow = Shew.ExternalWindow.new_from_handle(parentWindow);
if (externalWindow)
externalWindow.set_parent_of(window.window);
if (options.modal)
window.modal = options.modal.get_boolean();
window.connect('destroy', () => this.release());
this.hold();
window.show();
invocation.return_value(null);
});
}
CheckForUpdatesAsync(params, invocation) {
this._proxy.CheckForUpdatesRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(null);
});
}
};
var ExtensionPrefsDialog = GObject.registerClass({
GTypeName: 'ExtensionPrefsDialog',
Template: 'resource:///org/gnome/Shell/Extensions/ui/extension-prefs-dialog.ui',
InternalChildren: [
'headerBar',
'stack',
'expander',
'expanderArrow',
'revealer',
'errorView',
],
}, class ExtensionPrefsDialog extends Gtk.Window {
_init(extension) {
super._init();
this._uuid = extension.uuid;
this._url = extension.metadata.url || '';
this._headerBar.title = extension.metadata.name;
this._actionGroup = new Gio.SimpleActionGroup();
this.insert_action_group('win', this._actionGroup);
this._initActions();
this._addCustomStylesheet();
this._gesture = new Gtk.GestureMultiPress({
widget: this._expander,
button: 0,
exclusive: true,
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress === 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
this._expanderArrow.icon_name = this._revealer.reveal_child
? 'pan-down-symbolic'
: 'pan-end-symbolic';
});
try {
ExtensionUtils.installImporter(extension);
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => extension;
const prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
const widget = prefsModule.buildPrefsWidget();
this._stack.add(widget);
this._stack.visible_child = widget;
} catch (e) {
this._setError(e);
}
}
_setError(exc) {
this._errorView.buffer.text = `${exc}\n\nStack trace:\n`;
// Indent stack trace.
this._errorView.buffer.text +=
exc.stack.split('\n').map(line => ` ${line}`).join('\n');
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${this._uuid} had an error:`,
'```',
`${exc}`,
'```',
'',
'Stack trace:',
'```',
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```',
'',
];
this._errorMarkdown = lines.join('\n');
this._actionGroup.lookup('copy-error').enabled = true;
}
_initActions() {
let action;
action = new Gio.SimpleAction({
name: 'copy-error',
enabled: false,
});
action.connect('activate', () => {
const clipboard = Gtk.Clipboard.get_default(this.get_display());
clipboard.set_text(this._errorMarkdown, -1);
});
this._actionGroup.add_action(action);
action = new Gio.SimpleAction({
name: 'show-url',
enabled: this._url !== '',
});
action.connect('activate', () => {
Gio.AppInfo.launch_default_for_uri(this._url,
this.get_display().get_app_launch_context());
});
this._actionGroup.add_action(action);
}
_addCustomStylesheet() {
let provider = new Gtk.CssProvider();
let uri = 'resource:///org/gnome/Shell/Extensions/css/application.css';
try {
provider.load_from_file(Gio.File.new_for_uri(uri));
} catch (e) {
logError(e, 'Failed to add application style');
}
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
}
});

View File

@@ -1,20 +0,0 @@
/* exported main */
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const { Gtk } = imports.gi;
const pkg = imports.package;
const { DBusService } = imports.dbusService;
const { ExtensionsService } = imports.extensionsService;
function main() {
Gtk.init(null);
pkg.initFormat();
const service = new DBusService(
'org.gnome.Shell.Extensions',
new ExtensionsService());
service.run();
}

View File

@@ -1,197 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="ExtensionPrefsDialog" parent="GtkWindow">
<property name="default_width">600</property>
<property name="default_height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerBar">
<property name="visible">True</property>
<property name="show_close_button">True</property>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="hscrollbar_policy">never</property>
<property name="propagate_natural_height">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="margin">100</property>
<property name="margin_bottom">60</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Somethings gone wrong</property>
<attributes>
<attribute name="scale" value="1.44"/> <!-- x-large -->
</attributes>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors.</property>
<property name="justify">center</property>
<property name="wrap">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="margin_top">12</property>
<child>
<object class="GtkFrame" id="expander">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkEventBox">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="margin">12</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage" id="expanderArrow">
<property name="visible">True</property>
<property name="icon_name">pan-end-symbolic</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">Technical Details</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkRevealer" id="revealer">
<property name="visible">True</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="shadow_type">in</property>
<style>
<class name="expander-frame"/>
</style>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTextView" id="errorView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="monospace">True</property>
<property name="editable">False</property>
<property name="wrap_mode">word</property>
<property name="left_margin">12</property>
<property name="right_margin">12</property>
<property name="top_margin">12</property>
<property name="bottom_margin">12</property>
</object>
</child>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<style>
<class name="expander-toolbar"/>
</style>
<child>
<object class="GtkToolItem">
<property name="visible">True</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">win.copy-error</property>
<style>
<class name="flat"/>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon_name">edit-copy-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparatorToolItem">
<property name="visible">True</property>
<property name="draw">False</property>
</object>
<packing>
<property name="expand">True</property>
</packing>
</child>
<child>
<object class="GtkToolItem">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="homeButton">
<property name="visible"
bind-source="homeButton"
bind-property="sensitive"
bind-flags="sync-create"/>
<property name="label" translatable="yes">Homepage</property>
<property name="tooltip_text" translatable="yes">Visit extension homepage</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="action_name">win.show-url</property>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,42 +0,0 @@
launcherconf = configuration_data()
launcherconf.set('PACKAGE_NAME', meson.project_name())
launcherconf.set('prefix', prefix)
launcherconf.set('libdir', libdir)
dbus_services = {
'org.gnome.Shell.Extensions': 'extensions',
'org.gnome.Shell.Notifications': 'notifications',
}
config_dir = '@0@/..'.format(meson.current_build_dir())
foreach service, dir : dbus_services
configure_file(
input: 'dbus-service.in',
output: service,
configuration: launcherconf,
install_dir: pkgdatadir,
)
serviceconf = configuration_data()
serviceconf.set('service', service)
serviceconf.set('gjs', gjs.path())
serviceconf.set('pkgdatadir', pkgdatadir)
configure_file(
input: 'dbus-service.service.in',
output: service + '.service',
configuration: serviceconf,
install_dir: servicedir
)
gnome.compile_resources(
service + '.src',
service + '.src.gresource.xml',
dependencies: [config_js],
source_dir: ['.', '..', dir, config_dir],
gresource_bundle: true,
install: true,
install_dir: pkgdatadir
)
endforeach

View File

@@ -1,11 +0,0 @@
/* exported main */
const { DBusService } = imports.dbusService;
const { NotificationDaemon } = imports.notificationDaemon;
function main() {
const service = new DBusService(
'org.gnome.Shell.Notifications',
new NotificationDaemon());
service.run();
}

View File

@@ -1,105 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { Gio, GLib } = imports.gi;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ServiceImplementation } = imports.dbusService;
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
var NotificationDaemon = class extends ServiceImplementation {
constructor() {
super(NotificationsIface, '/org/freedesktop/Notifications');
this._autoShutdown = false;
this._proxy = new NotificationsProxy(Gio.DBus.session,
'org.gnome.Shell',
'/org/freedesktop/Notifications',
(proxy, error) => {
if (error)
log(error.message);
});
this._proxy.connectSignal('ActionInvoked',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('ActionInvoked',
new GLib.Variant('(us)', params));
});
this._proxy.connectSignal('NotificationClosed',
(proxy, sender, params) => {
this._dbusImpl.emit_signal('NotificationClosed',
new GLib.Variant('(uu)', params));
});
}
register() {
Gio.DBus.session.own_name(
'org.freedesktop.Notifications',
Gio.BusNameOwnerFlags.REPLACE,
null, null);
}
async NotifyAsync(params, invocation) {
const pid = await this._getSenderPid(invocation.get_sender());
const hints = params[6];
params[6] = {
...hints,
'sender-pid': new GLib.Variant('u', pid),
};
this._proxy.NotifyRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(u)', res));
});
}
CloseNotificationAsync(params, invocation) {
this._proxy.CloseNotificationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(null);
});
}
GetCapabilitiesAsync(params, invocation) {
this._proxy.GetCapabilitiesRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(as)', res));
});
}
GetServerInformationAsync(params, invocation) {
this._proxy.GetServerInformationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(ssss)', res));
});
}
async _getSenderPid(sender) {
const res = await Gio.DBus.session.call(
'org.freedesktop.DBus',
'/',
'org.freedesktop.DBus',
'GetConnectionUnixProcessID',
new GLib.Variant('(s)', [sender]),
new GLib.VariantType('(u)'),
Gio.DBusCallFlags.NONE,
-1,
null);
const [pid] = res.deepUnpack();
return pid;
}
};

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Shell/Extensions/js">
<file>main.js</file>
<file>extensionsService.js</file>
<file>dbusService.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource>
<gresource prefix="/org/gnome/Shell/Extensions">
<file>css/application.css</file>
<file>ui/extension-prefs-dialog.ui</file>
</gresource>
</gresources>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Shell/Notifications/js">
<file>main.js</file>
<file>notificationDaemon.js</file>
<file>dbusService.js</file>
<file>misc/config.js</file>
<file>misc/fileUtils.js</file>
</gresource>
</gresources>

View File

@@ -3,44 +3,34 @@ imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext;
const Package = imports.package;
const { Gdk, GLib, Gio, GObject, Gtk, Shew } = imports.gi;
const { Gdk, GLib, Gio, GObject, Gtk } = imports.gi;
const Format = imports.format;
Package.initFormat();
const _ = Gettext.gettext;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState, ExtensionType } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
Gio._promisify(Shew.WindowExporter.prototype, 'export', 'export_finish');
function loadInterfaceXML(iface) {
const uri = 'resource:///org/gnome/Extensions/dbus-interfaces/%s.xml'.format(iface);
const f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
return imports.byteArray.toString(bytes);
} catch (e) {
log('Failed to load D-Bus interface %s'.format(iface));
}
return null;
}
function toggleState(action) {
let state = action.get_state();
action.change_state(new GLib.Variant('b', !state.get_boolean()));
function stripPrefix(string, prefix) {
if (string.slice(0, prefix.length) == prefix)
return string.slice(prefix.length);
return string;
}
var Application = GObject.registerClass(
class Application extends Gtk.Application {
_init() {
GLib.set_prgname('gnome-extensions-app');
super._init({ application_id: 'org.gnome.Extensions' });
GLib.set_prgname('gnome-shell-extension-prefs');
super._init({
application_id: 'org.gnome.Extensions',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
});
}
get shellProxy() {
@@ -56,7 +46,7 @@ class Application extends Gtk.Application {
super.vfunc_startup();
let provider = new Gtk.CssProvider();
let uri = 'resource:///org/gnome/Extensions/css/application.css';
let uri = 'resource:///org/gnome/shell/css/application.css';
try {
provider.load_from_file(Gio.File.new_for_uri(uri));
} catch (e) {
@@ -66,19 +56,34 @@ class Application extends Gtk.Application {
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session,
'org.gnome.Shell.Extensions', '/org/gnome/Shell/Extensions');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._window = new ExtensionsWindow({ application: this });
}
vfunc_command_line(commandLine) {
let args = commandLine.get_arguments();
if (args.length) {
let uuid = args[0];
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, 'extension:///');
this._window.openPrefs(uuid);
} else {
this.activate();
}
return 0;
}
});
var ExtensionsWindow = GObject.registerClass({
GTypeName: 'ExtensionsWindow',
Template: 'resource:///org/gnome/Extensions/ui/extensions-window.ui',
Template: 'resource:///org/gnome/shell/ui/extensions-window.ui',
InternalChildren: [
'userList',
'systemList',
'killSwitch',
'mainBox',
'mainStack',
'scrolledWindow',
@@ -89,11 +94,11 @@ var ExtensionsWindow = GObject.registerClass({
_init(params) {
super._init(params);
this._startupUuid = null;
this._loaded = false;
this._prefsDialog = null;
this._updatesCheckId = 0;
this._exporter = new Shew.WindowExporter({ window: this });
this._exportedHandle = '';
this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment);
let action;
@@ -105,15 +110,10 @@ var ExtensionsWindow = GObject.registerClass({
action.connect('activate', this._logout.bind(this));
this.add_action(action);
action = new Gio.SimpleAction({
name: 'user-extensions-enabled',
state: new GLib.Variant('b', false),
});
action.connect('activate', toggleState);
action.connect('change-state', (a, state) => {
this._shellProxy.UserExtensionsEnabled = state.get_boolean();
});
this.add_action(action);
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.bind('disable-user-extensions',
this._killSwitch, 'active',
Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._userList.set_sort_func(this._sortList.bind(this));
this._userList.set_header_func(this._updateHeader.bind(this));
@@ -124,10 +124,6 @@ var ExtensionsWindow = GObject.registerClass({
this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this));
this._shellProxy.connect('g-properties-changed',
this._onUserExtensionsEnabledChanged.bind(this));
this._onUserExtensionsEnabledChanged();
this._scanExtensions();
}
@@ -157,18 +153,58 @@ var ExtensionsWindow = GObject.registerClass({
dialog.present();
}
async openPrefs(uuid) {
if (!this._exportedHandle) {
try {
this._exportedHandle = await this._exporter.export();
} catch (e) {
log('Failed to export window: %s'.format(e.message));
}
openPrefs(uuid) {
if (!this._loaded)
this._startupUuid = uuid;
else if (!this._showPrefs(uuid))
this.present();
}
_showPrefs(uuid) {
if (this._prefsDialog)
return false;
let row = this._findExtensionRow(uuid);
if (!row || !row.hasPrefs)
return false;
let widget;
try {
widget = row.prefsModule.buildPrefsWidget();
} catch (e) {
widget = this._buildErrorUI(row, e);
}
this._shellProxy.OpenExtensionPrefsRemote(uuid,
this._exportedHandle,
{ modal: new GLib.Variant('b', true) });
this._prefsDialog = new Gtk.Window({
application: this.application,
default_width: 600,
default_height: 400,
modal: this.visible,
type_hint: Gdk.WindowTypeHint.DIALOG,
window_position: Gtk.WindowPosition.CENTER,
});
this._prefsDialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true,
}));
if (this.visible)
this._prefsDialog.transient_for = this;
this._prefsDialog.connect('destroy', () => {
this._prefsDialog = null;
if (!this.visible)
this.destroy();
});
this._prefsDialog.add(widget);
this._prefsDialog.show();
return true;
}
_showAbout() {
@@ -183,7 +219,7 @@ var ExtensionsWindow = GObject.registerClass({
comments: _('Manage your GNOME Extensions'),
license_type: Gtk.License.GPL_2_0,
logo_icon_name: 'org.gnome.Extensions',
version: imports.package.version,
version: Config.PACKAGE_VERSION,
transient_for: this,
modal: true,
@@ -207,6 +243,121 @@ var ExtensionsWindow = GObject.registerClass({
});
}
_buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true,
});
let box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
});
scroll.add(box);
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(_("Somethings gone wrong")),
use_markup: true,
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
box.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors."),
justify: Gtk.Justification.CENTER,
wrap: true,
});
box.add(label);
let expander = new Expander({
label: _("Technical Details"),
margin_top: 12,
});
box.add(expander);
let errortext = '%s\n\nStack trace:\n'.format(exc);
// Indent stack trace.
errortext +=
exc.stack.split('\n').map(line => ' %s'.format(line)).join('\n');
let buffer = new Gtk.TextBuffer({ text: errortext });
let textview = new Gtk.TextView({
buffer,
wrap_mode: Gtk.WrapMode.WORD,
monospace: true,
editable: false,
top_margin: 12,
bottom_margin: 12,
left_margin: 12,
right_margin: 12,
});
let toolbar = new Gtk.Toolbar();
let provider = new Gtk.CssProvider();
provider.load_from_data(`* {
border: 0 solid @borders;
border-top-width: 1px;
}`);
toolbar.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
let copyButton = new Gtk.ToolButton({
icon_name: 'edit-copy-symbolic',
tooltip_text: _("Copy Error"),
});
toolbar.add(copyButton);
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues
let lines = [
'The settings of extension %s had an error:'.format(row.uuid),
'```', // '`' (xgettext throws up on odd number of backticks)
exc.toString(),
'```', // '`'
'',
'Stack trace:',
'```', // '`'
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```', // '`'
'',
];
clipboard.set_text(lines.join('\n'), -1);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
toolbar.add(spacing);
toolbar.child_set_property(spacing, "expand", true);
let urlButton = new Gtk.ToolButton({
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: row.url !== '',
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(row.url, context);
});
let expandedBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
});
expandedBox.add(textview);
expandedBox.add(toolbar);
expander.add(expandedBox);
scroll.show_all();
return scroll;
}
_sortList(row1, row2) {
return row1.name.localeCompare(row2.name);
}
@@ -226,12 +377,6 @@ var ExtensionsWindow = GObject.registerClass({
].find(c => c.uuid === uuid);
}
_onUserExtensionsEnabledChanged() {
let action = this.lookup_action('user-extensions-enabled');
action.set_state(
new GLib.Variant('b', this._shellProxy.UserExtensionsEnabled));
}
_onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let extension = ExtensionUtils.deserializeExtension(newState);
let row = this._findExtensionRow(uuid);
@@ -249,11 +394,9 @@ var ExtensionsWindow = GObject.registerClass({
if (row) {
if (extension.state === ExtensionState.UNINSTALLED)
row.destroy();
} else {
this._addExtensionRow(extension);
return; // we only deal with new and deleted extensions here
}
this._syncListVisibility();
this._addExtensionRow(extension);
}
_scanExtensions() {
@@ -299,16 +442,6 @@ var ExtensionsWindow = GObject.registerClass({
});
}
_syncListVisibility() {
this._userList.visible = this._userList.get_children().length > 0;
this._systemList.visible = this._systemList.get_children().length > 0;
if (this._userList.visible || this._systemList.visible)
this._mainStack.visible_child_name = 'main';
else
this._mainStack.visible_child_name = 'placeholder';
}
_checkUpdates() {
let nUpdates = this._userList.get_children().filter(c => c.hasUpdate).length;
@@ -320,21 +453,131 @@ var ExtensionsWindow = GObject.registerClass({
}
_extensionsLoaded() {
this._syncListVisibility();
this._userList.visible = this._userList.get_children().length > 0;
this._systemList.visible = this._systemList.get_children().length > 0;
if (this._userList.visible || this._systemList.visible)
this._mainStack.visible_child_name = 'main';
else
this._mainStack.visible_child_name = 'placeholder';
this._checkUpdates();
if (this._startupUuid)
this._showPrefs(this._startupUuid);
this._startupUuid = null;
this._loaded = true;
}
});
var Expander = GObject.registerClass({
Properties: {
'label': GObject.ParamSpec.string(
'label', 'label', 'label',
GObject.ParamFlags.READWRITE,
null
),
},
}, class Expander extends Gtk.Box {
_init(params = {}) {
this._labelText = null;
super._init(Object.assign(params, {
orientation: Gtk.Orientation.VERTICAL,
spacing: 0,
}));
this._frame = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
hexpand: true,
});
let eventBox = new Gtk.EventBox();
this._frame.add(eventBox);
let hbox = new Gtk.Box({
spacing: 6,
margin: 12,
});
eventBox.add(hbox);
this._arrow = new Gtk.Image({
icon_name: 'pan-end-symbolic',
});
hbox.add(this._arrow);
this._label = new Gtk.Label({ label: this._labelText });
hbox.add(this._label);
this._revealer = new Gtk.Revealer();
this._childBin = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
});
this._revealer.add(this._childBin);
// Directly chain up to parent for internal children
super.add(this._frame);
super.add(this._revealer);
let provider = new Gtk.CssProvider();
provider.load_from_data('* { border-top-width: 0; }');
this._childBin.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
this._gesture = new Gtk.GestureMultiPress({
widget: this._frame,
button: 0,
exclusive: true,
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress == 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
if (this._revealer.reveal_child)
this._arrow.icon_name = 'pan-down-symbolic';
else
this._arrow.icon_name = 'pan-end-symbolic';
});
}
get label() {
return this._labelText;
}
set label(text) {
if (this._labelText == text)
return;
if (this._label)
this._label.label = text;
this._labelText = text;
this.notify('label');
}
add(child) {
// set expanded child
this._childBin.get_children().forEach(c => {
this._childBin.remove(c);
});
if (child)
this._childBin.add(child);
}
});
var ExtensionRow = GObject.registerClass({
GTypeName: 'ExtensionRow',
Template: 'resource:///org/gnome/Extensions/ui/extension-row.ui',
Template: 'resource:///org/gnome/shell/ui/extension-row.ui',
InternalChildren: [
'nameLabel',
'descriptionLabel',
'versionLabel',
'authorLabel',
'updatesIcon',
'switch',
'revealButton',
'revealer',
],
@@ -378,7 +621,10 @@ var ExtensionRow = GObject.registerClass({
name: 'enabled',
state: new GLib.Variant('b', false),
});
action.connect('activate', toggleState);
action.connect('activate', () => {
let state = action.get_state();
action.change_state(new GLib.Variant('b', !state.get_boolean()));
});
action.connect('change-state', (a, state) => {
if (state.get_boolean())
this._app.shellProxy.EnableExtensionRemote(this.uuid);
@@ -387,7 +633,8 @@ var ExtensionRow = GObject.registerClass({
});
this._actionGroup.add_action(action);
this._nameLabel.label = this.name;
let name = GLib.markup_escape_text(this.name, -1);
this._nameLabel.label = name;
let desc = this._extension.metadata.description.split('\n')[0];
this._descriptionLabel.label = desc;
@@ -454,9 +701,6 @@ var ExtensionRow = GObject.registerClass({
action.set_state(new GLib.Variant('b', state));
action.enabled = this._canToggle();
if (!action.enabled)
this._switch.active = state;
this._updatesIcon.visible = this.hasUpdate;
this._versionLabel.label = this.version.toString();
@@ -478,6 +722,20 @@ var ExtensionRow = GObject.registerClass({
_canToggle() {
return this._extension.canChange;
}
get prefsModule() {
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
return this._prefsModule;
}
});
function initEnvironment() {
@@ -494,11 +752,12 @@ function initEnvironment() {
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']),
};
String.prototype.format = Format.format;
}
function main(argv) {
initEnvironment();
Package.initGettext();
new Application().run(argv);
}

View File

@@ -54,7 +54,7 @@
</object>
</child>
<child>
<object class="GtkSwitch" id="switch">
<object class="GtkSwitch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="valign">center</property>

View File

@@ -90,10 +90,8 @@
</packing>
</child>
<child>
<object class="GtkSwitch">
<object class="GtkSwitch" id="killSwitch">
<property name="visible">True</property>
<property name="action-name">win.user-extensions-enabled</property>
<property name="valign">center</property>
</object>
<packing>
<property name="pack_type">end</property>
@@ -270,7 +268,7 @@
<object class="GtkLabel">
<property name="visible">True</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Extension Updates Ready</property>
<property name="label">Extension Updates Ready</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>

View File

@@ -120,7 +120,7 @@ var AuthPrompt = GObject.registerClass({
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
_initEntryRow() {
@@ -184,7 +184,7 @@ var AuthPrompt = GObject.registerClass({
});
this._defaultButtonWell.add_constraint(new Clutter.BindConstraint({
source: this.cancelButton,
coordinate: Clutter.BindCoordinate.WIDTH,
coordinate: Clutter.BindCoordinate.SIZE,
}));
this._mainBox.add_child(this._defaultButtonWell);
@@ -424,13 +424,8 @@ var AuthPrompt = GObject.registerClass({
}
updateSensitivity(sensitive) {
if (this._entry.reactive === sensitive)
return;
this._entry.reactive = sensitive;
if (sensitive)
this._entry.grab_key_focus();
this._entry.clutter_text.editable = sensitive;
}
vfunc_hide() {

View File

@@ -35,6 +35,7 @@ const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250;
const _SCROLL_ANIMATION_TIME = 500;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48;
var UserListItem = GObject.registerClass({
Signals: { 'activate': {} },
@@ -177,7 +178,6 @@ var UserList = GObject.registerClass({
}
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._moveFocusToItems();
}
@@ -813,7 +813,7 @@ var LoginDialog = GObject.registerClass({
if (this._logoFile && this._logoBin.resource_scale > 0) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, -1,
-1, _LOGO_ICON_HEIGHT,
scaleFactor,
this._logoBin.resource_scale));
}

View File

@@ -1,5 +1,4 @@
subdir('misc')
subdir('dbusServices')
js_resources = gnome.compile_resources(
'js-resources', 'js-resources.gresource.xml',
@@ -14,3 +13,10 @@ portal_resources = gnome.compile_resources(
c_name: 'portal_js_resources',
dependencies: [config_js]
)
prefs_resources = gnome.compile_resources(
'prefs-resources', 'prefs-resources.gresource.xml',
source_dir: ['.', meson.current_build_dir()],
c_name: 'prefs_js_resources',
dependencies: [config_js]
)

View File

@@ -15,5 +15,6 @@ var LOCALEDIR = '@datadir@/locale';
/* other standard directories */
var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
var VPNDIR = '@vpndir@';
/* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, openPrefs, isOutOfDate,
installImporter, serializeExtension, deserializeExtension */
getSettings, initTranslations, isOutOfDate, installImporter,
serializeExtension, deserializeExtension */
// Common utils for the extension system and the extension
// preferences tool
@@ -153,27 +153,6 @@ function getSettings(schema) {
return new Gio.Settings({ settings_schema: schemaObj });
}
/**
* openPrefs:
*
* Open the preference dialog of the current extension
*/
function openPrefs() {
const extension = getCurrentExtension();
if (!extension)
throw new Error('openPrefs() can only be called from extensions');
try {
const extensionManager = imports.ui.main.extensionManager;
extensionManager.openExtensionPrefs(extension.uuid, '', {});
} catch (e) {
if (e.name === 'ImportError')
throw new Error('openPrefs() cannot be called from preferences');
logError(e, 'Failed to open extension preferences');
}
}
/**
* versionCheck:
* @param {string[]} required - an array of versions we're compatible with

View File

@@ -76,15 +76,19 @@ function loadInterfaceXML(iface) {
_ifaceResource._register();
}
let xml = null;
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`;
let f = Gio.File.new_for_uri(uri);
try {
let [ok_, bytes] = f.load_contents(null);
return imports.byteArray.toString(bytes);
if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes);
else
xml = bytes.toString();
} catch (e) {
log(`Failed to load D-Bus interface ${iface}`);
}
return null;
return xml;
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus, Meta } = imports.gi;
const { Gio, GLib, IBus } = imports.gi;
const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@@ -55,7 +55,7 @@ var IBusManager = class {
this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn(Meta.is_wayland_compositor() ? [] : ['--xim']);
this._spawn();
}
_spawn(extraArgs = []) {
@@ -66,7 +66,7 @@ var IBusManager = class {
let display = GLib.getenv('GNOME_SETUP_DISPLAY');
if (display)
launcher.setenv('DISPLAY', display, true);
launcher.spawnv(cmdLine);
launcher.launch(cmdLine);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
}
@@ -127,55 +127,56 @@ var IBusManager = class {
}
_initPanelService(ibus, result) {
let success = false;
try {
this._ibus.request_name_async_finish(result);
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
this._clear();
}
return;
}
this._panelService = new IBus.PanelService({
connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL,
});
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
let cursorLocation = { x, y, width: w, height: h };
this.emit('set-cursor-location', cursorLocation);
});
this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
if (!engine)
return;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
let cursorLocation = { x, y, width: w, height: h };
this.emit('set-cursor-location', cursorLocation);
});
this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in');
});
this._panelService.connect('focus-out', () => this.emit('focus-out'));
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
// switching input focus that temporarily lose purpose
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
this._engineChanged(this._ibus, engine.get_name());
});
this._updateReadiness();
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(res);
if (!engine)
return;
} catch (e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
});
this._updateReadiness();
} else {
this._clear();
}
}
_updateReadiness() {

View File

@@ -97,13 +97,8 @@ class InputMethod extends Clutter.InputMethod {
this.commit(text.get_text());
}
_onDeleteSurroundingText(_context, offset, nchars) {
try {
this.delete_surrounding(offset, nchars);
} catch (e) {
// We may get out of bounds for negative offset on older mutter
this.delete_surrounding(0, nchars + offset);
}
_onDeleteSurroundingText() {
this.delete_surrounding();
}
_onUpdatePreeditText(_context, text, pos, visible) {

View File

@@ -7,6 +7,7 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file(
input: 'config.js.in',

View File

@@ -223,7 +223,7 @@ var BroadbandModem = GObject.registerClass({
}, class BroadbandModem extends ModemBase {
_init(path, capabilities) {
super._init({ capabilities });
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
@@ -249,7 +249,7 @@ var BroadbandModem = GObject.registerClass({
}
_reloadSignalQuality() {
let [quality, recent_] = this._proxy.SignalQuality;
let [quality, recent_] = this.SignalQuality;
this._setSignalQuality(quality);
}

View File

@@ -83,17 +83,13 @@ const SystemActions = GObject.registerClass({
this._canHavePowerOff = true;
this._canHaveSuspend = true;
function tokenizeKeywords(keywords) {
return keywords.split(';').map(keyword => GLib.str_tokenize_and_fold(keyword, null)).flat(2);
}
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID, {
// Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: tokenizeKeywords(_('power off;shutdown;reboot;restart;halt;stop')),
keywords: _('power off;shutdown;reboot;restart;halt;stop').split(/[; ]/),
available: false,
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
@@ -101,15 +97,15 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: tokenizeKeywords(_('lock screen')),
keywords: _("lock screen").split(/[; ]/),
available: false,
});
this._actions.set(LOGOUT_ACTION_ID, {
// Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'system-log-out-symbolic',
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: tokenizeKeywords(_('logout;log out;sign off')),
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false,
});
this._actions.set(SUSPEND_ACTION_ID, {
@@ -117,7 +113,7 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: tokenizeKeywords(_('suspend;sleep')),
keywords: _("suspend;sleep").split(/[; ]/),
available: false,
});
this._actions.set(SWITCH_USER_ACTION_ID, {
@@ -125,14 +121,14 @@ const SystemActions = GObject.registerClass({
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: tokenizeKeywords(_('switch user')),
keywords: _("switch user").split(/[; ]/),
available: false,
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
name: '',
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: tokenizeKeywords(_('lock orientation;unlock orientation;screen;rotation')),
keywords: _("lock orientation;unlock orientation;screen;rotation").split(/[; ]/),
available: false,
});
@@ -281,7 +277,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map(term => GLib.str_tokenize_and_fold(term, null)[0]);
terms = terms.map(term => term.toLowerCase());
let results = [];

View File

@@ -5,5 +5,6 @@
<file>misc/config.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
<file alias="css/application.css">extensionPrefs/css/application.css</file>
<file alias="ui/extension-row.ui">extensionPrefs/ui/extension-row.ui</file>
<file alias="ui/extensions-window.ui">extensionPrefs/ui/extensions-window.ui</file>
</gresource>
</gresources>

View File

@@ -853,9 +853,6 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
if (index === -1)
return;
this._arrows[index].destroy();
this._arrows.splice(index, 1);
this.icons.splice(index, 1);
this.removeItem(index);
}
@@ -1063,25 +1060,25 @@ class WindowSwitcher extends SwitcherPopup.SwitcherList {
vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node();
let contentBox = themeNode.get_content_box(box);
const labelHeight = this._label.height;
const totalLabelHeight =
labelHeight + themeNode.get_padding(St.Side.BOTTOM);
box.y2 -= totalLabelHeight;
super.vfunc_allocate(box, flags);
let childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;
childBox.y2 = box.y2 - totalLabelHeight;
super.vfunc_allocate(childBox, flags);
// Hooking up the parent vfunc will call this.set_allocation() with
// the height without the label height, so call it again with the
// correct size here.
box.y2 += totalLabelHeight;
this.set_allocation(box, flags);
const childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x2;
childBox.y2 = contentBox.y2;
childBox.y1 = childBox.y2 - labelHeight;
this._label.allocate(childBox, flags);
}
highlight(index, justOutline) {

View File

@@ -15,7 +15,8 @@ class Animation extends St.Bin {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
super._init({
style: `width: ${width}px; height: ${height}px;`,
width: width * themeContext.scale_factor,
height: height * themeContext.scale_factor,
});
this.connect('destroy', this._onDestroy.bind(this));

View File

@@ -36,7 +36,6 @@ var VIEWS_SWITCH_TIME = 400;
var VIEWS_SWITCH_ANIMATION_DELAY = 100;
var PAGE_SWITCH_TIME = 250;
var SCROLL_TIMEOUT_TIME = 150;
var APP_ICON_SCALE_IN_TIME = 500;
var APP_ICON_SCALE_IN_DELAY = 700;
@@ -72,9 +71,15 @@ function _getFolderName(folder) {
let name = folder.get_string('name');
if (folder.get_boolean('translate')) {
let translated = Shell.util_get_translated_folder_name(name);
if (translated !== null)
return translated;
let keyfile = new GLib.KeyFile();
let path = 'desktop-directories/%s'.format(name);
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch (e) {
return name;
}
}
return name;
@@ -115,10 +120,15 @@ function _findBestFolderName(apps) {
}, commonCategories);
for (let category of commonCategories) {
const directory = '%s.directory'.format(category);
const translated = Shell.util_get_translated_folder_name(directory);
if (translated !== null)
return translated;
let keyfile = new GLib.KeyFile();
let path = 'desktop-directories/%s.directory'.format(category);
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
return keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch (e) {
continue;
}
}
return null;
@@ -159,10 +169,6 @@ var BaseAppView = GObject.registerClass({
this._items = new Map();
this._orderedItems = [];
this._animateLaterId = 0;
this._viewLoadedHandlerId = 0;
this._viewIsReady = false;
}
_childFocused(_actor) {
@@ -198,7 +204,6 @@ var BaseAppView = GObject.registerClass({
this._items.set(icon.id, icon);
});
this._viewIsReady = true;
this.emit('view-loaded');
}
@@ -248,18 +253,6 @@ var BaseAppView = GObject.registerClass({
Main.overview.dash.showAppsButton);
}
_clearAnimateLater() {
if (this._animateLaterId) {
Meta.later_remove(this._animateLaterId);
this._animateLaterId = 0;
}
if (this._viewLoadedHandlerId) {
this.disconnect(this._viewLoadedHandlerId);
this._viewLoadedHandlerId = 0;
}
this._grid.opacity = 255;
}
animate(animationDirection, onComplete) {
if (onComplete) {
let animationDoneId = this._grid.connect('animation-done', () => {
@@ -268,38 +261,16 @@ var BaseAppView = GObject.registerClass({
});
}
this._clearAnimateLater();
if (animationDirection == IconGrid.AnimationDirection.IN) {
const doSpringAnimationLater = laterType => {
this._animateLaterId = Meta.later_add(laterType,
() => {
this._animateLaterId = 0;
this._doSpringAnimation(animationDirection);
return GLib.SOURCE_REMOVE;
});
};
if (this._viewIsReady) {
this._grid.opacity = 0;
doSpringAnimationLater(Meta.LaterType.IDLE);
} else {
this._viewLoadedHandlerId = this.connect('view-loaded',
() => {
this._clearAnimateLater();
doSpringAnimationLater(Meta.LaterType.BEFORE_REDRAW);
});
}
let id = this._grid.connect('paint', () => {
this._grid.disconnect(id);
this._doSpringAnimation(animationDirection);
});
} else {
this._doSpringAnimation(animationDirection);
}
}
vfunc_unmap() {
this._clearAnimateLater();
super.vfunc_unmap();
}
animateSwitch(animationDirection) {
this.remove_all_transitions();
this._grid.remove_all_transitions();
@@ -421,12 +392,10 @@ var AllView = GObject.registerClass({
this._redisplayWorkId = Main.initializeDeferredWork(this, this._redisplay.bind(this));
Shell.AppSystem.get_default().connect('installed-changed', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId);
});
this._folderSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
this._folderSettings.connect('changed::folder-children', () => {
this._viewIsReady = false;
Main.queueDeferredWork(this._redisplayWorkId);
});
@@ -462,10 +431,6 @@ var AllView = GObject.registerClass({
_redisplay() {
super._redisplay();
this._folderIcons.forEach(icon => {
icon.view._redisplay();
});
this._refilterApps();
}
@@ -653,7 +618,7 @@ var AllView = GObject.registerClass({
this._canScroll = false;
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
SCROLL_TIMEOUT_TIME, () => {
PAGE_SWITCH_TIME, () => {
this._canScroll = true;
this._scrollTimeoutId = 0;
return GLib.SOURCE_REMOVE;
@@ -734,6 +699,8 @@ var AllView = GObject.registerClass({
// Toggle search entry
Main.overview.searchEntry.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.reactive = !isOpen;
Main.overview.searchEntry.clutter_text.editable = !isOpen;
this._displayingPopup = isOpen;
});
@@ -1292,8 +1259,8 @@ var AppSearchProvider = class AppSearchProvider {
let results = [];
groups.forEach(group => {
group = group.filter(appID => {
const app = this._appSys.lookup_app(appID);
return app && app.app_info.should_show();
let app = Gio.DesktopAppInfo.new(appID);
return app && app.should_show();
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)
@@ -1341,7 +1308,7 @@ class FolderView extends BaseAppView {
x_expand: true,
y_expand: true,
});
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC);
this.add_actor(this._scrollView);
let scrollableContainer = new St.BoxLayout({
@@ -1357,6 +1324,7 @@ class FolderView extends BaseAppView {
action.connect('pan', this._onPan.bind(this));
this._scrollView.add_action(action);
this._folder.connect('changed', this._redisplay.bind(this));
this._redisplay();
}
@@ -1378,12 +1346,12 @@ class FolderView extends BaseAppView {
});
layout.hookup_style(icon);
let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let numItems = this._orderedItems.length;
let rtl = icon.get_text_direction() == Clutter.TextDirection.RTL;
for (let i = 0; i < 4; i++) {
const style = 'width: %dpx; height: %dpx;'.format(subSize, subSize);
let bin = new St.Bin({ style });
let bin = new St.Bin({ width: subSize * scale, height: subSize * scale });
if (i < numItems)
bin.child = this._orderedItems[i].app.create_icon_texture(subSize);
layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1);
@@ -1461,22 +1429,6 @@ class FolderView extends BaseAppView {
return apps;
}
addApp(app) {
let folderApps = this._folder.get_strv('apps');
folderApps.push(app.id);
this._folder.set_strv('apps', folderApps);
// Also remove from 'excluded-apps' if the app id is listed
// there. This is only possible on categories-based folders.
let excludedApps = this._folder.get_strv('excluded-apps');
let index = excludedApps.indexOf(app.id);
if (index >= 0) {
excludedApps.splice(index, 1);
this._folder.set_strv('excluded-apps', excludedApps);
}
}
removeApp(app) {
let folderApps = this._folder.get_strv('apps');
let index = folderApps.indexOf(app.id);
@@ -1507,6 +1459,8 @@ class FolderView extends BaseAppView {
} else {
this._folder.set_strv('apps', folderApps);
}
return true;
}
});
@@ -1540,26 +1494,26 @@ var FolderIcon = GObject.registerClass({
this.view = new FolderView(this._folder, id, parentView);
this._iconIsHovering = false;
this._itemDragBeginId = Main.overview.connect(
'item-drag-begin', this._onDragBegin.bind(this));
this._itemDragEndId = Main.overview.connect(
'item-drag-end', this._onDragEnd.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this._folderChangedId = this._folder.connect(
'changed', this._sync.bind(this));
this._sync();
this._folder.connect('changed', this._redisplay.bind(this));
this._redisplay();
}
_onDestroy() {
if (this._dragMonitor) {
DND.removeDragMonitor(this._dragMonitor);
this._dragMonitor = null;
}
Main.overview.disconnect(this._itemDragBeginId);
Main.overview.disconnect(this._itemDragEndId);
this.view.destroy();
if (this._folderChangedId) {
this._folder.disconnect(this._folderChangedId);
delete this._folderChangedId;
if (this._spaceReadySignalId) {
this._parentView.disconnect(this._spaceReadySignalId);
this._spaceReadySignalId = 0;
}
if (this._dialog)
@@ -1587,32 +1541,29 @@ var FolderIcon = GObject.registerClass({
return this.view.getAllItems().map(item => item.id);
}
_setHoveringByDnd(hovering) {
if (this._iconIsHovering == hovering)
return;
this._iconIsHovering = hovering;
if (hovering) {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
this.add_style_pseudo_class('drop');
} else {
DND.removeDragMonitor(this._dragMonitor);
this.remove_style_pseudo_class('drop');
}
_onDragBegin() {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
}
_onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor) ||
!this._canAccept(dragEvent.source))
this._setHoveringByDnd(false);
let target = dragEvent.targetActor;
if (!this.contains(target) || !this._canAccept(dragEvent.source))
this.remove_style_pseudo_class('drop');
else
this.add_style_pseudo_class('drop');
return DND.DragMotionResult.CONTINUE;
}
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
_canAccept(source) {
if (!(source instanceof AppIcon))
return false;
@@ -1631,18 +1582,27 @@ var FolderIcon = GObject.registerClass({
if (!this._canAccept(source))
return DND.DragMotionResult.NO_DROP;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP;
}
acceptDrop(source) {
this._setHoveringByDnd(false);
if (!this._canAccept(source))
return false;
this.view.addApp(source.app);
let app = source.app;
let folderApps = this._folder.get_strv('apps');
folderApps.push(app.id);
this._folder.set_strv('apps', folderApps);
// Also remove from 'excluded-apps' if the app id is listed
// there. This is only possible on categories-based folders.
let excludedApps = this._folder.get_strv('excluded-apps');
let index = excludedApps.indexOf(app.id);
if (index >= 0) {
excludedApps.splice(index, 1);
this._folder.set_strv('excluded-apps', excludedApps);
}
return true;
}
@@ -1657,11 +1617,11 @@ var FolderIcon = GObject.registerClass({
this.emit('name-changed');
}
_sync() {
this.emit('apps-changed');
_redisplay() {
this._updateName();
this.visible = this.view.getAllItems().length > 0;
this.icon.update();
this.emit('apps-changed');
}
_createIcon(iconSize) {
@@ -1942,7 +1902,6 @@ var AppFolderDialog = GObject.registerClass({
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
contentBox = this._viewBox.get_theme_node().get_content_box(contentBox);
let [, entryBoxHeight] = this._entryBox.get_size();
let spacing = this._viewBox.layout_manager.spacing;
@@ -1951,8 +1910,6 @@ var AppFolderDialog = GObject.registerClass({
contentBox.get_width(),
contentBox.get_height() - entryBoxHeight - spacing);
this._view._grid.topPadding = 0;
super.vfunc_allocate(box, flags);
// We can only start zooming after receiving an allocation
@@ -2068,6 +2025,7 @@ var AppIcon = GObject.registerClass({
this._delegate = this;
this._hasDndHover = false;
this._folderPreviewId = 0;
// Get the isDraggable property without passing it on to the BaseIcon:
@@ -2116,7 +2074,11 @@ var AppIcon = GObject.registerClass({
});
}
this._otherIconIsHovering = false;
this._dragMonitor = null;
this._itemDragBeginId = Main.overview.connect(
'item-drag-begin', this._onDragBegin.bind(this));
this._itemDragEndId = Main.overview.connect(
'item-drag-end', this._onDragEnd.bind(this));
this._menuTimeoutId = 0;
this._stateChangedId = this.app.connect('notify::state', () => {
@@ -2128,6 +2090,9 @@ var AppIcon = GObject.registerClass({
}
_onDestroy() {
Main.overview.disconnect(this._itemDragBeginId);
Main.overview.disconnect(this._itemDragEndId);
if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0;
@@ -2374,17 +2339,7 @@ var AppIcon = GObject.registerClass({
}
_setHoveringByDnd(hovering) {
if (this._otherIconIsHovering == hovering)
return;
this._otherIconIsHovering = hovering;
if (hovering) {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0)
return;
@@ -2396,8 +2351,6 @@ var AppIcon = GObject.registerClass({
return GLib.SOURCE_REMOVE;
});
} else {
DND.removeDragMonitor(this._dragMonitor);
if (this._folderPreviewId > 0) {
GLib.source_remove(this._folderPreviewId);
this._folderPreviewId = 0;
@@ -2407,13 +2360,32 @@ var AppIcon = GObject.registerClass({
}
}
_onDragBegin() {
this._dragMonitor = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
}
_onDragMotion(dragEvent) {
if (!this.contains(dragEvent.targetActor))
this._setHoveringByDnd(false);
let target = dragEvent.targetActor;
let isHovering = target == this || this.contains(target);
let canDrop = this._canAccept(dragEvent.source);
let hasDndHover = isHovering && canDrop;
if (this._hasDndHover != hasDndHover) {
this._setHoveringByDnd(hasDndHover);
this._hasDndHover = hasDndHover;
}
return DND.DragMotionResult.CONTINUE;
}
_onDragEnd() {
this.remove_style_pseudo_class('drop');
DND.removeDragMonitor(this._dragMonitor);
}
handleDragOver(source) {
if (source == this)
return DND.DragMotionResult.NO_DROP;
@@ -2421,8 +2393,6 @@ var AppIcon = GObject.registerClass({
if (!this._canAccept(source))
return DND.DragMotionResult.CONTINUE;
this._setHoveringByDnd(true);
return DND.DragMotionResult.MOVE_DROP;
}
@@ -2467,7 +2437,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
Main.uiGroup.add_actor(this.actor);
}
_rebuildMenu() {
_redisplay() {
this.removeAll();
let windows = this._source.app.get_windows().filter(
@@ -2563,7 +2533,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
null, 0, -1, null, null);
Main.overview.hide();
});
});
@@ -2584,7 +2554,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
}
popup(_activatingButton) {
this._rebuildMenu();
this._redisplay();
this.open();
}
};

View File

@@ -12,7 +12,6 @@ const RENAMED_DESKTOP_IDS = {
'cheese.desktop': 'org.gnome.Cheese.desktop',
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'empathy.desktop': 'org.gnome.Empathy.desktop',
'eog.desktop': 'org.gnome.eog.desktop',
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',

View File

@@ -197,11 +197,6 @@ var BoxPointer = GObject.registerClass({
}
vfunc_allocate(box, flags) {
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
}
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
@@ -235,6 +230,12 @@ var BoxPointer = GObject.registerClass({
break;
}
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box);
this._updateFlip(box);
this.set_allocation(box, flags);
}
}
_drawBorder(area) {

View File

@@ -220,12 +220,9 @@ class DBusEventSource extends EventSourceBase {
}
}
this._dbusProxy.connectSignal('EventsAddedOrUpdated',
this._onEventsAddedOrUpdated.bind(this));
this._dbusProxy.connectSignal('EventsRemoved',
this._onEventsRemoved.bind(this));
this._dbusProxy.connectSignal('ClientDisappeared',
this._onClientDisappeared.bind(this));
this._dbusProxy.connectSignal('EventsAdded', this._onEventsAdded.bind(this));
this._dbusProxy.connectSignal('EventsRemoved', this._onEventsRemoved.bind(this));
this._dbusProxy.connectSignal('ClientDisappeared', this._onClientDisappeared.bind(this));
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
@@ -278,14 +275,17 @@ class DBusEventSource extends EventSourceBase {
this.emit('changed');
}
_onEventsAddedOrUpdated(dbusProxy, nameOwner, argArray) {
const [appointments = []] = argArray;
_onEventsAdded(dbusProxy, nameOwner, argArray) {
let appointments = argArray[0] || [];
let changed = false;
for (let n = 0; n < appointments.length; n++) {
const [id, summary, allDay, startTime, endTime] = appointments[n];
const date = new Date(startTime * 1000);
const end = new Date(endTime * 1000);
let a = appointments[n];
let id = a[0];
let summary = a[1];
let allDay = a[2];
let date = new Date(a[3] * 1000);
let end = new Date(a[4] * 1000);
let event = new CalendarEvent(id, date, end, summary, allDay);
this._events.set(event.id, event);
@@ -297,24 +297,33 @@ class DBusEventSource extends EventSourceBase {
}
_onEventsRemoved(dbusProxy, nameOwner, argArray) {
const [ids = []] = argArray;
let ids = argArray[0] || [];
let changed = false;
for (const id of ids)
changed |= this._events.delete(id);
for (let n = 0; n < ids.length; n++) {
let id = ids[n];
if (this._events.delete(id))
changed = true;
}
if (changed)
this.emit('changed');
}
_onClientDisappeared(dbusProxy, nameOwner, argArray) {
let [sourceUid = ''] = argArray;
let sourceUid = argArray[0] || "";
let changed = false;
let idsIter = this._events.keys();
sourceUid += '\n';
let changed = false;
for (const id of this._events.keys()) {
if (id.startsWith(sourceUid))
changed |= this._events.delete(id);
for (let item = idsIter.next(); !item.done; item = idsIter.next()) {
let id = item.value;
if (id.startsWith(sourceUid) &&
this._events.delete(id))
changed = true;
}
if (changed)
@@ -331,11 +340,10 @@ class DBusEventSource extends EventSourceBase {
this._events.clear();
this.emit('changed');
}
this._dbusProxy.SetTimeRangeRemote(
this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Gio.DBusCallFlags.NONE);
this._dbusProxy.SetTimeRangeRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Gio.DBusCallFlags.NONE);
}
}
@@ -349,16 +357,20 @@ class DBusEventSource extends EventSourceBase {
}
}
*_getFilteredEvents(begin, end) {
for (const event of this._events.values()) {
if (_dateIntervalsOverlap(event.date, event.end, begin, end))
yield event;
getEvents(begin, end, onlyCheckExistence) {
let result = [];
let eventsIter = this._events.values();
for (let item = eventsIter.next(); !item.done; item = eventsIter.next()) {
let event = item.value;
if (_dateIntervalsOverlap(event.date, event.end, begin, end)) {
result.push(event);
if (onlyCheckExistence)
return result;
}
}
}
getEvents(begin, end) {
let result = [...this._getFilteredEvents(begin, end)];
result.sort((event1, event2) => {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
@@ -372,8 +384,12 @@ class DBusEventSource extends EventSourceBase {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
const { done } = this._getFilteredEvents(dayBegin, dayEnd).next();
return !done;
let events = this.getEvents(dayBegin, dayEnd, true);
if (events.length == 0)
return false;
return true;
}
});
@@ -725,11 +741,12 @@ var Calendar = GObject.registerClass({
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', '');
super._init('', event.summary);
this._event = event;
this._date = date;
this.update(event);
this.setTitle(this._formatEventTime());
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
@@ -741,13 +758,6 @@ class EventMessage extends MessageList.Message {
super.vfunc_style_changed();
}
update(event) {
this._event = event;
this.setTitle(this._formatEventTime());
this.setBody(event.summary);
}
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
@@ -868,9 +878,8 @@ class EventsSection extends MessageList.MessageListSection {
this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
this._appSys = Shell.AppSystem.get_default();
this._appSys.connect('installed-changed',
this._appInstalledChanged.bind(this));
Shell.AppSystem.get_default().connect('installed-changed',
this._appInstalledChanged.bind(this));
this._appInstalledChanged();
}
@@ -914,10 +923,7 @@ class EventsSection extends MessageList.MessageListSection {
let periodEnd = _getEndOfDay(this._date);
let events = this._eventSource.getEvents(periodBegin, periodEnd);
let ids = events.map(e => e.id);
this._messageById.forEach((message, id) => {
if (ids.includes(id))
return;
this._messageById.delete(id);
this.removeMessage(message);
});
@@ -931,7 +937,6 @@ class EventsSection extends MessageList.MessageListSection {
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
message.update(event);
this.moveMessage(message, i, false);
}
}
@@ -964,13 +969,10 @@ class EventsSection extends MessageList.MessageListSection {
Main.overview.hide();
Main.panel.closeCalendar();
let appInfo = this._getCalendarApp();
if (appInfo.get_id() === 'org.gnome.Evolution.desktop') {
let app = this._appSys.lookup_app('evolution-calendar.desktop');
if (app)
appInfo = app.app_info;
}
appInfo.launch([], global.create_app_launch_context(0, -1));
let app = this._getCalendarApp();
if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1));
}
setDate(date) {
@@ -1185,22 +1187,17 @@ class CalendarMessageList extends St.Widget {
let hbox = new St.BoxLayout({ style_class: 'message-list-controls' });
box.add_child(hbox);
const dndLabel = new St.Label({
hbox.add_child(new St.Label({
text: _('Do Not Disturb'),
y_align: Clutter.ActorAlign.CENTER,
});
hbox.add_child(dndLabel);
}));
this._dndSwitch = new DoNotDisturbSwitch();
this._dndButton = new St.Button({
can_focus: true,
toggle_mode: true,
child: this._dndSwitch,
label_actor: dndLabel,
});
this._dndSwitch.bind_property('state',
this._dndButton, 'checked',
GObject.BindingFlags.BIDIRECTIONAL | GObject.BindingFlags.SYNC_CREATE);
this._dndButton.connect('clicked', () => this._dndSwitch.toggle());
hbox.add_child(this._dndButton);
this._clearButton = new St.Button({

View File

@@ -1,5 +1,5 @@
/* exported CheckBox */
const { Atk, Clutter, GObject, Pango, St } = imports.gi;
const { Clutter, GObject, Pango, St } = imports.gi;
var CheckBox = GObject.registerClass(
class CheckBox extends St.Button {
@@ -15,7 +15,6 @@ class CheckBox extends St.Button {
toggle_mode: true,
can_focus: true,
});
this.set_accessible_role(Atk.Role.CHECK_BOX);
this._box = new St.Bin({ y_align: Clutter.ActorAlign.START });
container.add_actor(this._box);
@@ -23,7 +22,6 @@ class CheckBox extends St.Button {
this._label = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._label.clutter_text.set_line_wrap(true);
this._label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this.set_label_actor(this._label);
container.add_actor(this._label);
if (label)

View File

@@ -188,8 +188,6 @@ var CloseDialog = GObject.registerClass({
global.stage.disconnect(this._keyFocusChangedId);
this._keyFocusChangedId = 0;
this._dialog._dialog.remove_all_transitions();
let dialog = this._dialog;
this._dialog = null;
this._removeWindowEffect();

View File

@@ -111,11 +111,15 @@ class KeyringDialog extends ModalDialog.ModalDialog {
}
_updateSensitivity(sensitive) {
if (this._passwordEntry)
if (this._passwordEntry) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
}
if (this._confirmEntry)
if (this._confirmEntry) {
this._confirmEntry.reactive = sensitive;
this._confirmEntry.clutter_text.editable = sensitive;
}
this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive;

View File

@@ -4,15 +4,13 @@
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = GObject.registerClass(
@@ -617,6 +615,14 @@ var NetworkAgent = class {
this._vpnRequests = { };
this._notifications = { };
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => (this._vpnCacheBuilt = false));
} catch (e) {
log('Failed to create monitor for VPN plugin dir: %s'.format(e.message));
}
this._native.connect('new-request', this._newRequest.bind(this));
this._native.connect('cancel-request', this._cancelRequest.bind(this));
@@ -760,11 +766,13 @@ var NetworkAgent = class {
}
}
async _vpnRequest(requestId, connection, hints, flags) {
_vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn();
let serviceType = vpnSetting.service_type;
let binary = await this._findAuthBinary(serviceType);
this._buildVPNServiceCache();
let binary = this._vpnBinaries[serviceType];
if (!binary) {
log('Invalid VPN service type (cannot find authentication binary)');
@@ -780,30 +788,36 @@ var NetworkAgent = class {
this._vpnRequests[requestId] = vpnRequest;
}
async _findAuthBinary(serviceType) {
let plugin;
_buildVPNServiceCache() {
if (this._vpnCacheBuilt)
return;
try {
plugin = await this._native.search_vpn_plugin(serviceType);
} catch (e) {
logError(e);
return null;
}
this._vpnCacheBuilt = true;
this._vpnBinaries = { };
const fileName = plugin.get_auth_dialog();
if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
log('VPN plugin at %s is not executable'.format(fileName));
return null;
}
NM.VpnPluginInfo.list_load().forEach(plugin => {
let service = plugin.get_service();
let fileName = plugin.get_auth_dialog();
let supportsHints = plugin.supports_hints();
let externalUIMode = false;
const prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
const trimmedProp = prop ? prop.trim().toLowerCase() : '';
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
if (prop) {
prop = prop.trim().toLowerCase();
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
}
return {
fileName,
supportsHints: plugin.supports_hints(),
externalUIMode: ['true', 'yes', 'on', '1'].includes(trimmedProp),
};
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
let binary = { fileName, externalUIMode, supportsHints };
this._vpnBinaries[service] = binary;
plugin.get_aliases().forEach(alias => {
this._vpnBinaries[alias] = binary;
});
} else {
log('VPN plugin at %s is not executable'.format(fileName));
}
});
}
};
var Component = NetworkAgent;

View File

@@ -327,8 +327,6 @@ var AuthenticationDialog = GObject.registerClass({
}
let resetDialog = () => {
this._sessionRequestTimeoutId = 0;
if (this.state != ModalDialog.State.OPENED)
return;

View File

@@ -2,6 +2,7 @@
/* exported Component */
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
var Tpl = null;
var Tp = null;
@@ -39,59 +40,36 @@ var NotificationDirection = {
RECEIVED: 'chat-received',
};
const ChatMessage = HAVE_TP ? GObject.registerClass({
Properties: {
'message-type': GObject.ParamSpec.int(
'message-type', 'message-type', 'message-type',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
Math.min(...Object.values(Tp.ChannelTextMessageType)),
Math.max(...Object.values(Tp.ChannelTextMessageType)),
Tp.ChannelTextMessageType.NORMAL),
'text': GObject.ParamSpec.string(
'text', 'text', 'text',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'sender': GObject.ParamSpec.string(
'sender', 'sender', 'sender',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'timestamp': GObject.ParamSpec.int64(
'timestamp', 'timestamp', 'timestamp',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
0, Number.MAX_SAFE_INTEGER, 0),
'direction': GObject.ParamSpec.string(
'direction', 'direction', 'direction',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null),
},
}, class ChatMessageClass extends GObject.Object {
static newFromTpMessage(tpMessage, direction) {
return new ChatMessage({
'message-type': tpMessage.get_message_type(),
'text': tpMessage.to_text()[0],
'sender': tpMessage.sender.alias,
'timestamp': direction === NotificationDirection.RECEIVED
? tpMessage.get_received_timestamp() : tpMessage.get_sent_timestamp(),
direction,
});
}
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags_] = tpMessage.to_text();
static newFromTplTextEvent(tplTextEvent) {
let direction =
tplTextEvent.get_sender().get_entity_type() === Tpl.EntityType.SELF
? NotificationDirection.SENT : NotificationDirection.RECEIVED;
let timestamp = tpMessage.get_sent_timestamp();
if (timestamp == 0)
timestamp = tpMessage.get_received_timestamp();
return new ChatMessage({
'message-type': tplTextEvent.get_message_type(),
'text': tplTextEvent.get_message(),
'sender': tplTextEvent.get_sender().get_alias(),
'timestamp': tplTextEvent.get_timestamp(),
direction,
});
}
}) : null;
return {
messageType: tpMessage.get_message_type(),
text,
sender: tpMessage.sender.alias,
timestamp,
direction,
};
}
function makeMessageFromTplEvent(event) {
let sent = event.get_sender().get_entity_type() == Tpl.EntityType.SELF;
let direction = sent ? NotificationDirection.SENT : NotificationDirection.RECEIVED;
return {
messageType: event.get_message_type(),
text: event.get_message(),
sender: event.get_sender().get_alias(),
timestamp: event.get_timestamp(),
direction,
};
}
var TelepathyComponent = class {
constructor() {
this._client = null;
@@ -292,12 +270,12 @@ class TelepathyClient extends Tp.BaseClient {
var ChatSource = HAVE_TP ? GObject.registerClass(
class ChatSource extends MessageTray.Source {
_init(account, conn, channel, contact, client) {
super._init(contact.get_alias());
this._account = account;
this._contact = contact;
this._client = client;
super._init(contact.get_alias());
this.isChat = true;
this._pendingMessages = [];
@@ -453,7 +431,7 @@ class ChatSource extends MessageTray.Source {
_displayPendingMessages(logManager, result) {
let [success_, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(e => ChatMessage.newFromTplTextEvent(e));
let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification();
let pendingTpMessages = this._channel.get_pending_messages();
@@ -465,8 +443,7 @@ class ChatSource extends MessageTray.Source {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
continue;
pendingMessages.push(ChatMessage.newFromTpMessage(message,
NotificationDirection.RECEIVED));
pendingMessages.push(makeMessageFromTpMessage(message, NotificationDirection.RECEIVED));
this._pendingMessages.push(message);
}
@@ -564,8 +541,7 @@ class ChatSource extends MessageTray.Source {
this._pendingMessages.push(message);
this.countUpdated();
message = ChatMessage.newFromTpMessage(message,
NotificationDirection.RECEIVED);
message = makeMessageFromTpMessage(message, NotificationDirection.RECEIVED);
this._notification.appendMessage(message);
// Wait a bit before notifying for the received message, a handler
@@ -590,8 +566,7 @@ class ChatSource extends MessageTray.Source {
// our client and other clients as well.
_messageSent(channel, message, _flags, _token) {
this._ensureNotification();
message = ChatMessage.newFromTpMessage(message,
NotificationDirection.SENT);
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
}
@@ -655,19 +630,11 @@ class ChatSource extends MessageTray.Source {
}
}) : null;
const ChatNotificationMessage = HAVE_TP ? GObject.registerClass(
class ChatNotificationMessage extends GObject.Object {
_init(props = {}) {
super._init();
this.set(props);
}
}) : null;
var ChatNotification = HAVE_TP ? GObject.registerClass({
Signals: {
'message-removed': { param_types: [ChatNotificationMessage.$gtype] },
'message-added': { param_types: [ChatNotificationMessage.$gtype] },
'timestamp-changed': { param_types: [ChatNotificationMessage.$gtype] },
'message-removed': { param_types: [Tp.Message.$gtype] },
'message-added': { param_types: [Tp.Message.$gtype] },
'timestamp-changed': { param_types: [Tp.Message.$gtype] },
},
}, class ChatNotification extends MessageTray.Notification {
_init(source) {
@@ -768,24 +735,21 @@ var ChatNotification = HAVE_TP ? GObject.registerClass({
styles: [],
timestamp: currentTime,
noTimestamp: false });
const { noTimestamp } = props;
delete props.noTimestamp;
// Reset the old message timeout
if (this._timestampTimeoutId)
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
let message = new ChatNotificationMessage({
realMessage: props.group !== 'meta',
showTimestamp: false,
...props,
});
let message = { realMessage: props.group != 'meta',
showTimestamp: false };
Lang.copyProperties(props, message);
delete message.noTimestamp;
this.messages.unshift(message);
this.emit('message-added', message);
if (!noTimestamp) {
if (!props.noTimestamp) {
let timestamp = props.timestamp;
if (timestamp < currentTime - SCROLLBACK_IMMEDIATE_TIME) {
this.appendTimestamp();

View File

@@ -94,7 +94,6 @@ class WorldClocksSection extends St.Button {
});
this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0;
this._tzNotifyId = 0;
this._locations = [];
@@ -167,6 +166,8 @@ class WorldClocksSection extends St.Button {
layout.attach(header, 0, 0, 2, 1);
this.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
@@ -179,14 +180,14 @@ class WorldClocksSection extends St.Button {
let time = new St.Label({ style_class: 'world-clocks-time' });
const tz = new St.Label({
style_class: 'world-clocks-timezone',
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
time.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
tz.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let fmt = Math.trunc(offset) == offset ? '%s%.0f' : '%s%.1f';
let prefix = offset >= 0 ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
text: fmt.format(prefix, Math.abs(offset)),
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER });
if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(tz, 0, i + 1, 1, 1);
@@ -198,65 +199,32 @@ class WorldClocksSection extends St.Button {
layout.attach(tz, 2, i + 1, 1, 1);
}
this._locations[i].timeLabel = time;
this._locations[i].tzLabel = tz;
this._locations[i].actor = time;
}
if (this._grid.get_n_children() > 1) {
if (!this._clockNotifyId) {
this._clockNotifyId =
this._clock.connect('notify::clock', this._updateTimeLabels.bind(this));
this._clock.connect('notify::clock', this._updateLabels.bind(this));
}
if (!this._tzNotifyId) {
this._tzNotifyId =
this._clock.connect('notify::timezone', this._updateTimezoneLabels.bind(this));
}
this._updateTimeLabels();
this._updateTimezoneLabels();
this._updateLabels();
} else {
if (this._clockNotifyId)
this._clock.disconnect(this._clockNotifyId);
this._clockNotifyId = 0;
if (this._tzNotifyId)
this._clock.disconnect(this._tzNotifyId);
this._tzNotifyId = 0;
}
}
_getTimezoneOffsetAtLocation(location) {
const localOffset = GLib.DateTime.new_now_local().get_utc_offset();
const utcOffset = this._getTimeAtLocation(location).get_utc_offset();
const offsetCurrentTz = utcOffset - localOffset;
const offsetHours = Math.abs(offsetCurrentTz) / GLib.TIME_SPAN_HOUR;
const offsetMinutes =
(Math.abs(offsetCurrentTz) % GLib.TIME_SPAN_HOUR) /
GLib.TIME_SPAN_MINUTE;
const prefix = offsetCurrentTz >= 0 ? '+' : '-';
const text = offsetMinutes === 0
? '%s%d'.format(prefix, offsetHours)
: '%s%d\u2236%d'.format(prefix, offsetHours, offsetMinutes);
return text;
}
_getTimeAtLocation(location) {
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
return GLib.DateTime.new_now(tz);
}
_updateTimeLabels() {
_updateLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let now = this._getTimeAtLocation(l.location);
l.timeLabel.text = Util.formatTime(now, { timeOnly: true });
}
}
_updateTimezoneLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
l.tzLabel.text = this._getTimezoneOffsetAtLocation(l.location);
l.actor.text = Util.formatTime(now, { timeOnly: true });
}
}
@@ -416,20 +384,6 @@ class WeatherSection extends St.Button {
layout.attach(label, 0, 0, 1, 1);
}
_findBestLocationName(loc) {
const locName = loc.get_name();
if (loc.get_level() === GWeather.LocationLevel.CITY ||
!loc.has_coords())
return locName;
const world = GWeather.Location.get_world();
const city = world.find_nearest_city(...loc.get_coords());
const cityName = city.get_name();
return locName.includes(cityName) ? cityName : locName;
}
_updateForecasts() {
this._forecastGrid.destroy_all_children();
@@ -438,8 +392,13 @@ class WeatherSection extends St.Button {
return;
}
const { info } = this._weatherClient;
this._titleLocation.text = this._findBestLocationName(info.location);
let info = this._weatherClient.info;
let loc = info.get_location();
if (loc.get_level() !== GWeather.LocationLevel.CITY && loc.has_coords()) {
let world = GWeather.Location.get_world();
loc = world.find_nearest_city(...loc.get_coords());
}
this._titleLocation.text = loc.get_name();
if (this._weatherClient.loading) {
this._setStatusLabel(_("Loading…"));
@@ -481,6 +440,7 @@ class MessagesIndicator extends St.Icon {
this._sources = [];
this._count = 0;
this._doNotDisturb = false;
this._settings = new Gio.Settings({
schema_id: 'org.gnome.desktop.notifications',
@@ -594,7 +554,6 @@ class DateMenuButton extends PanelMenu.Button {
this._clockDisplay = new St.Label({ style_class: 'clock' });
this._clockDisplay.clutter_text.y_align = Clutter.ActorAlign.CENTER;
this._clockDisplay.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._indicator = new MessagesIndicator();

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent, ListSection, ListSectionItem */
const { Clutter, GLib, GObject, Meta, Pango, St } = imports.gi;
const { Clutter, GObject, Meta, Pango, St } = imports.gi;
function _setLabel(label, value) {
label.set({
@@ -221,16 +221,13 @@ var MessageDialogContent = GObject.registerClass({
this._updateTitleStyleLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._updateTitleStyleLater = 0;
this._title.add_style_class_name('leightweight');
return GLib.SOURCE_REMOVE;
return false;
});
}
}
set title(title) {
if (this._title.text === title)
return;
_setLabel(this._title, title);
this._title.remove_style_class_name('leightweight');
@@ -240,9 +237,6 @@ var MessageDialogContent = GObject.registerClass({
}
set description(description) {
if (this._description.text === description)
return;
_setLabel(this._description, description);
this.notify('description');
}

View File

@@ -346,8 +346,10 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
// Use a different description when we are installing a system upgrade
// if the PackageKit proxy is available (i.e. PackageKit is available).
if (dialogContent.upgradeDescription) {
const { name, version } = this._updateInfo.PreparedUpgrade;
if (this._pkOfflineProxy && dialogContent.upgradeDescription) {
let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
if (name != null && version != null)
description = dialogContent.upgradeDescription(name, version);
}
@@ -606,46 +608,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
});
}
async _getUpdateInfo() {
const connection = this._pkOfflineProxy.get_connection();
const reply = await connection.call(
this._pkOfflineProxy.g_name,
this._pkOfflineProxy.g_object_path,
'org.freedesktop.DBus.Properties',
'GetAll',
new GLib.Variant('(s)', [this._pkOfflineProxy.g_interface_name]),
null,
Gio.DBusCallFlags.NONE,
-1,
null);
const [info] = reply.recursiveUnpack();
return info;
}
async OpenAsync(parameters, invocation) {
OpenAsync(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type;
try {
this._updateInfo = await this._getUpdateInfo();
} catch (e) {
if (this._pkOfflineProxy !== null)
log('Failed to get update info from PackageKit: %s'.format(e.message));
this._updateInfo = {
UpdateTriggered: false,
UpdatePrepared: false,
UpgradeTriggered: false,
PreparedUpgrade: {},
};
}
// Only consider updates and upgrades if PackageKit is available.
if (this._pkOfflineProxy && this._type == DialogType.RESTART) {
if (this._updateInfo.UpdateTriggered)
if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART;
else if (this._updateInfo.UpgradeTriggered)
else if (this._pkOfflineProxy.UpgradeTriggered)
this._type = DialogType.UPGRADE_RESTART;
}
@@ -674,8 +646,9 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
if (dialogContent.showOtherSessions)
this._loadSessions();
let updateTriggered = this._updateInfo.UpdateTriggered;
let updatePrepared = this._updateInfo.UpdatePrepared;
// Only consider updates and upgrades if PackageKit is available.
let updateTriggered = this._pkOfflineProxy ? this._pkOfflineProxy.UpdateTriggered : false;
let updatePrepared = this._pkOfflineProxy ? this._pkOfflineProxy.UpdatePrepared : false;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');

View File

@@ -10,12 +10,10 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
const System = imports.system;
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
let _localTimeZone = null;
// We can't import shell JS modules yet, because they may have
@@ -290,13 +288,6 @@ function init() {
},
});
Gio._LocalFilePrototype.touch_async = function (callback) {
Shell.util_touch_file_async(this, callback);
};
Gio._LocalFilePrototype.touch_finish = function (result) {
return Shell.util_touch_file_finish(this, result);
};
St.set_slow_down_factor = function (factor) {
let { stack } = new Error();
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);

View File

@@ -56,15 +56,6 @@ function uninstallExtension(uuid) {
return false;
FileUtils.recursivelyDeleteDir(extension.dir, true);
try {
const updatesDir = Gio.File.new_for_path(GLib.build_filenamev(
[global.userdatadir, 'extension-updates', extension.uuid]));
FileUtils.recursivelyDeleteDir(updatesDir, true);
} catch (e) {
// not an error
}
return true;
}
@@ -108,9 +99,6 @@ function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
}
function downloadExtensionUpdate(uuid) {
if (!Main.extensionManager.updatesSupported)
return;
let dir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extension-updates', uuid]));
@@ -129,9 +117,6 @@ function downloadExtensionUpdate(uuid) {
}
function checkForUpdates() {
if (!Main.extensionManager.updatesSupported)
return;
let metadatas = {};
Main.extensionManager.getUuids().forEach(uuid => {
let extension = Main.extensionManager.lookup(uuid);
@@ -142,9 +127,6 @@ function checkForUpdates() {
metadatas[uuid] = extension.metadata;
});
if (Object.keys(metadatas).length === 0)
return; // nothing to update
let versionCheck = global.settings.get_boolean(
'disable-extension-version-validation');
let params = {
@@ -162,7 +144,9 @@ function checkForUpdates() {
let operations = JSON.parse(message.response_body.data);
for (let uuid in operations) {
let operation = operations[uuid];
if (operation === 'upgrade' || operation === 'downgrade')
if (operation == 'blacklist')
uninstallExtension(uuid);
else if (operation == 'upgrade' || operation == 'downgrade')
downloadExtensionUpdate(uuid);
}
});
@@ -238,7 +222,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
});
function init() {
_httpSession = new Soup.Session({ ssl_use_system_ca_file: true });
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
// _httpSession.add_feature(new Soup.ProxyResolverDefault());

View File

@@ -26,7 +26,6 @@ var ExtensionManager = class {
this._updateNotified = false;
this._extensions = new Map();
this._unloadedExtensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
@@ -61,11 +60,6 @@ var ExtensionManager = class {
ExtensionDownloader.checkForUpdates();
}
get updatesSupported() {
const appSys = Shell.AppSystem.get_default();
return appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
}
lookup(uuid) {
return this._extensions.get(uuid);
}
@@ -103,18 +97,18 @@ var ExtensionManager = class {
}
}
try {
extension.stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
try {
extension.stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
for (let i = 0; i < order.length; i++) {
let otherUuid = order[i];
try {
@@ -216,25 +210,6 @@ var ExtensionManager = class {
return true;
}
openExtensionPrefs(uuid, parentWindow, options) {
const extension = this.lookup(uuid);
if (!extension || !extension.hasPrefs)
return false;
Gio.DBus.session.call(
'org.gnome.Shell.Extensions',
'/org/gnome/Shell/Extensions',
'org.gnome.Shell.Extensions',
'OpenExtensionPrefs',
new GLib.Variant('(ssa{sv})', [uuid, parentWindow, options]),
null,
Gio.DBusCallFlags.NONE,
-1,
null,
(conn, res) => conn.call_finish(res));
return true;
}
notifyExtensionUpdate(uuid) {
let extension = this.lookup(uuid);
if (!extension)
@@ -270,7 +245,6 @@ var ExtensionManager = class {
extension.errors.push(message);
logError(error, 'Extension %s'.format(uuid));
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
@@ -320,14 +294,6 @@ var ExtensionManager = class {
return extension;
}
_canLoad(extension) {
if (!this._unloadedExtensions.has(extension.uuid))
return true;
const version = this._unloadedExtensions.get(extension.uuid);
return extension.metadata.version === version;
}
loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
@@ -336,9 +302,6 @@ var ExtensionManager = class {
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else if (!this._canLoad(extension)) {
this.logExtensionError(extension.uuid, new Error(
'A different version was loaded previously. You need to log out for changes to take effect.'));
} else {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
@@ -349,8 +312,6 @@ var ExtensionManager = class {
} else {
extension.state = ExtensionState.INITIALIZED;
}
this._unloadedExtensions.delete(extension.uuid);
}
this._updateCanChange(extension);
@@ -358,22 +319,15 @@ var ExtensionManager = class {
}
unloadExtension(extension) {
const { uuid, type } = extension;
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
this._callExtensionDisable(uuid);
this._callExtensionDisable(extension.uuid);
extension.state = ExtensionState.UNINSTALLED;
this.emit('extension-state-changed', extension);
// If we did install an importer, it is now cached and it's
// impossible to load a different version
if (type === ExtensionType.PER_USER && extension.imports)
this._unloadedExtensions.set(uuid, extension.metadata.version);
this._extensions.delete(uuid);
this._extensions.delete(extension.uuid);
return true;
}
@@ -527,9 +481,6 @@ var ExtensionManager = class {
}
_installExtensionUpdates() {
if (!this.updatesSupported)
return;
FileUtils.collectFromDatadirs('extension-updates', true, (dir, info) => {
let fileType = info.get_file_type();
if (fileType !== Gio.FileType.DIRECTORY)
@@ -538,14 +489,9 @@ var ExtensionManager = class {
let extensionDir = Gio.File.new_for_path(
GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
try {
FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(dir, extensionDir);
} catch (e) {
log('Failed to install extension updates for %s'.format(uuid));
} finally {
FileUtils.recursivelyDeleteDir(dir, true);
}
FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(dir, extensionDir);
FileUtils.recursivelyDeleteDir(dir, true);
});
}

View File

@@ -1,5 +1,5 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Pango, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
@@ -90,8 +90,6 @@ var InhibitShortcutsDialog = GObject.registerClass({
text: _('You can restore shortcuts by pressing %s.').format(restoreAccel),
style_class: 'message-dialog-description',
});
restoreLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
restoreLabel.clutter_text.line_wrap = true;
content.add_child(restoreLabel);
}

View File

@@ -61,24 +61,6 @@ class AspectContainer extends St.Widget {
this.queue_relayout();
}
vfunc_get_preferred_width(forHeight) {
let [min, nat] = super.vfunc_get_preferred_width(forHeight);
if (forHeight > 0)
nat = forHeight * this._ratio;
return [min, nat];
}
vfunc_get_preferred_height(forWidth) {
let [min, nat] = super.vfunc_get_preferred_height(forWidth);
if (forWidth > 0)
nat = forWidth / this._ratio;
return [min, nat];
}
vfunc_allocate(box, flags) {
if (box.get_width() > 0 && box.get_height() > 0) {
let sizeRatio = box.get_width() / box.get_height();
@@ -516,7 +498,7 @@ var Key = GObject.registerClass({
var KeyboardModel = class {
constructor(groupName) {
let names = [groupName];
if (groupName.includes('+'))
if (names.includes('+'))
names.push(groupName.replace(/\+.*/, ''));
names.push('us');
@@ -1138,11 +1120,10 @@ var KeyboardManager = class KeyBoardManager {
this._lastDevice = null;
Meta.get_backend().connect('last-device-changed', (backend, device) => {
if (device.device_type === Clutter.InputDeviceType.KEYBOARD_DEVICE)
return;
this._lastDevice = device;
this._syncEnabled();
if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDevice = device;
this._syncEnabled();
}
});
this._syncEnabled();
}
@@ -1167,9 +1148,9 @@ var KeyboardManager = class KeyBoardManager {
this._keyboard = new Keyboard();
} else if (!enabled && this._keyboard) {
this._keyboard.setCursorLocation(null);
Main.layoutManager.hideKeyboard(true);
this._keyboard.destroy();
this._keyboard = null;
Main.layoutManager.hideKeyboard(true);
}
}
@@ -1275,10 +1256,6 @@ class Keyboard extends St.BoxLayout {
return this._keyboardVisible && super.visible;
}
set visible(visible) {
super.visible = visible;
}
_onFocusPositionChanged(focusTracker) {
let rect = focusTracker.getCurrentRect();
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
@@ -1627,9 +1604,7 @@ class Keyboard extends St.BoxLayout {
* we allow the OSK being smaller than 1/3rd of the monitor height
* there.
*/
const forWidth = this.get_theme_node().adjust_for_width(monitor.width);
const [, natHeight] = this.get_preferred_height(forWidth);
this.height = Math.min(maxHeight, natHeight);
this.height = Math.min(maxHeight, this.get_preferred_height(monitor.width));
}
}
@@ -1893,10 +1868,6 @@ var KeyboardController = class {
Main.inputMethod.disconnect(this._notifyContentPurposeId);
Main.inputMethod.disconnect(this._notifyContentHintsId);
Main.inputMethod.disconnect(this._notifyInputPanelStateId);
// Make sure any buttons pressed by the virtual device are released
// immediately instead of waiting for the next GC cycle
this._virtualDevice.run_dispose();
}
_onSourcesModified() {

View File

@@ -612,20 +612,10 @@ var LayoutManager = GObject.registerClass({
let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId);
this._systemBackground.show();
global.stage.show();
// We're mostly prepared for the startup animation
// now, but since a lot is going on asynchronously
// during startup, let's defer the startup animation
// until the event loop is uncontended and idle.
// This helps to prevent us from running the animation
// when the system is bogged down
const id = GLib.idle_add(GLib.PRIORITY_LOW, () => {
this._systemBackground.show();
global.stage.show();
this._prepareStartupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] Startup Animation');
this._prepareStartupAnimation();
});
}
@@ -682,7 +672,17 @@ var LayoutManager = GObject.registerClass({
this.emit('startup-prepared');
this._startupAnimation();
// We're mostly prepared for the startup animation
// now, but since a lot is going on asynchronously
// during startup, let's defer the startup animation
// until the event loop is uncontended and idle.
// This helps to prevent us from running the animation
// when the system is bogged down
let id = GLib.idle_add(GLib.PRIORITY_LOW, () => {
this._startupAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._startupAnimation');
}
_startupAnimation() {
@@ -765,7 +765,7 @@ var LayoutManager = GObject.registerClass({
this._keyboardHeightNotifyId = 0;
}
this.keyboardBox.ease({
translation_y: 0,
translation_y: this.keyboardBox.height,
opacity: 0,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,

View File

@@ -1127,7 +1127,7 @@ class LookingGlass extends St.BoxLayout {
else if (symbol == Clutter.KEY_Page_Down)
this._notebook.nextTab();
}
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
open() {

View File

@@ -93,9 +93,6 @@ let _a11ySettings = null;
let _themeResource = null;
let _oskResource = null;
Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
function _sessionUpdated() {
if (sessionMode.isPrimary)
_loadDefaultStylesheet();
@@ -132,9 +129,7 @@ function start() {
notifyError(msg, detail);
});
let currentDesktop = GLib.getenv('XDG_CURRENT_DESKTOP');
if (!currentDesktop || !currentDesktop.split(':').includes('GNOME'))
Gio.DesktopAppInfo.set_desktop_env('GNOME');
Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode();
sessionMode.connect('updated', _sessionUpdated);
@@ -147,11 +142,6 @@ function start() {
shellDBusService = new ShellDBus.GnomeShell();
shellMountOpDBusService = new ShellMountOperation.GnomeShellMountOpHandler();
const watchId = Gio.DBus.session.watch_name('org.gnome.Shell.Notifications',
Gio.BusNameWatcherFlags.AUTO_START,
bus => bus.unwatch_name(watchId),
bus => bus.unwatch_name(watchId));
_sessionUpdated();
}
@@ -281,8 +271,11 @@ function _initializeUI() {
}
if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup')
_handleLockScreenWarning();
sessionMode.currentMode !== 'initial-setup' &&
screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM();
@@ -295,32 +288,6 @@ function _initializeUI() {
});
}
async function _handleLockScreenWarning() {
const path = '%s/lock-warning-shown'.format(global.userdatadir);
const file = Gio.File.new_for_path(path);
const hasLockScreen = screenShield !== null;
if (hasLockScreen) {
try {
await file.delete_async(0, null);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
logError(e);
}
} else {
try {
if (!await file.touch_async())
return;
} catch (e) {
logError(e);
}
notify(
_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
}
function _getStylesheet(name) {
let stylesheet;
@@ -394,8 +361,7 @@ function reloadThemeResource() {
if (_themeResource)
_themeResource._unregister();
_themeResource = Gio.Resource.load('%s/%s'.format(global.datadir,
sessionMode.themeResourceName));
_themeResource = Gio.Resource.load('%s/gnome-shell-theme.gresource'.format(global.datadir));
_themeResource._register();
}
@@ -521,9 +487,7 @@ function pushModal(actor, params) {
let prevFocusDestroyId;
if (prevFocus != null) {
prevFocusDestroyId = prevFocus.connect('destroy', () => {
const index = modalActorFocusStack.findIndex(
record => record.prevFocus === prevFocus);
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack[index].prevFocus = null;
});

View File

@@ -530,7 +530,7 @@ var Message = GObject.registerClass({
this.close();
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyEvent);
return Clutter.EVENT_PROPAGATE;
}
});

View File

@@ -136,22 +136,29 @@ var FocusGrabber = class FocusGrabber {
var NotificationPolicy = GObject.registerClass({
Properties: {
'enable': GObject.ParamSpec.boolean(
'enable', 'enable', 'enable', GObject.ParamFlags.READABLE, true),
'enable', 'enable', 'enable',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'enable-sound': GObject.ParamSpec.boolean(
'enable-sound', 'enable-sound', 'enable-sound',
GObject.ParamFlags.READABLE, true),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'show-banners': GObject.ParamSpec.boolean(
'show-banners', 'show-banners', 'show-banners',
GObject.ParamFlags.READABLE, true),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
true),
'force-expanded': GObject.ParamSpec.boolean(
'force-expanded', 'force-expanded', 'force-expanded',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'show-in-lock-screen': GObject.ParamSpec.boolean(
'show-in-lock-screen', 'show-in-lock-screen', 'show-in-lock-screen',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'details-in-lock-screen': GObject.ParamSpec.boolean(
'details-in-lock-screen', 'details-in-lock-screen', 'details-in-lock-screen',
GObject.ParamFlags.READABLE, false),
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
false),
},
}, class NotificationPolicy extends GObject.Object {
// Do nothing for the default policy. These methods are only useful for the
@@ -162,28 +169,24 @@ var NotificationPolicy = GObject.registerClass({
this.run_dispose();
}
get enable() {
return true;
}
get enableSound() {
return true;
return this.enable_sound;
}
get showBanners() {
return true;
return this.show_banners;
}
get forceExpanded() {
return false;
return this.force_expanded;
}
get showInLockScreen() {
return false;
return this.show_in_lock_screen;
}
get detailsInLockScreen() {
return false;
return this.details_in_lock_screen;
}
});
@@ -759,10 +762,12 @@ var Source = GObject.registerClass({
this.notifications = [];
this._policy = this._createPolicy();
this._policy = null;
}
get policy() {
if (!this._policy)
this._policy = this._createPolicy();
return this._policy;
}
@@ -875,6 +880,8 @@ var Source = GObject.registerClass({
}
destroy(reason) {
this.policy.destroy();
let notifications = this.notifications;
this.notifications = [];
@@ -883,7 +890,6 @@ var Source = GObject.registerClass({
this.emit('destroy', reason);
this.policy.destroy();
this.run_dispose();
}

View File

@@ -173,11 +173,6 @@ var MprisPlayer = class MprisPlayer {
if (!this._mprisProxy.g_name_owner)
this._close();
});
// It is possible for the bus to disappear before the previous signal
// is connected, so we must ensure that the bus still exists at this
// point.
if (!this._mprisProxy.g_name_owner)
this._close();
}
_onPlayerProxyReady() {

View File

@@ -10,6 +10,13 @@ const Params = imports.misc.params;
const { loadInterfaceXML } = imports.misc.fileUtils;
// Should really be defined in Gio.js
const BusIface = loadInterfaceXML('org.freedesktop.DBus');
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
var NotificationClosedReason = {
@@ -42,7 +49,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = [];
this._senderToPid = {};
this._notifications = {};
this._busProxy = new Bus();
this._nextNotificationId = 1;
@@ -107,9 +116,12 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
//
// If no existing source is found, a new source is created as long as
// pid is provided.
//
// Either a pid or ndata.notification is needed to retrieve or
// create a source.
_getSource(title, pid, ndata, sender) {
if (!pid && !(ndata && ndata.notification))
throw new Error('Either a pid or ndata.notification is needed');
return null;
// We use notification's source for the notifications we still have
// around that are getting replaced because we don't keep sources
@@ -206,10 +218,42 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
this._notifications[id] = ndata;
let sender = invocation.get_sender();
let pid = hints['sender-pid'];
let pid = this._senderToPid[sender];
let source = this._getSource(appName, pid, ndata, sender, null);
this._notifyForSource(source, ndata);
if (source) {
this._notifyForSource(source, ndata);
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
if (replacesId) {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
if (excp) {
logError(excp, 'Call to GetConnectionUnixProcessID failed');
return;
}
[pid] = result;
source = this._getSource(appName, pid, ndata, sender, null);
this._senderToPid[sender] = pid;
source.connect('destroy', () => {
delete this._senderToPid[sender];
});
this._notifyForSource(source, ndata);
});
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
@@ -372,11 +416,12 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
_init(title, pid, sender, appId) {
super._init(title);
this.pid = pid;
this.initialTitle = title;
this.app = this._getApp(appId);
super._init(title);
this.initialTitle = title;
if (this.app)
this.title = this.app.get_name();
@@ -425,20 +470,19 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
}
_getApp(appId) {
const appSys = Shell.AppSystem.get_default();
let app;
app = Shell.WindowTracker.get_default().get_app_from_pid(this.pid);
if (app != null)
return app;
if (appId)
app = appSys.lookup_app('%s.desktop'.format(appId));
if (appId) {
app = Shell.AppSystem.get_default().lookup_app('%s.desktop'.format(appId));
if (app != null)
return app;
}
if (!app)
app = appSys.lookup_app('%s.desktop'.format(this.initialTitle));
return app;
return null;
}
setTitle(title) {
@@ -587,12 +631,12 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!app)
throw new InvalidAppError();
super._init(app.get_name());
this._appId = appId;
this._app = app;
this._objectPath = objectPath;
super._init(app.get_name());
this._notifications = {};
this._notificationPending = false;
}

View File

@@ -4,10 +4,6 @@
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
// Time for initial animation going into Overview mode;
// this is defined here to make it available in imports.
var ANIMATION_TIME = 250;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
const LayoutManager = imports.ui.layout;
@@ -18,6 +14,9 @@ const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
// Time for initial animation going into Overview mode
var ANIMATION_TIME = 250;
// Must be less than ANIMATION_TIME, since we switch to
// or from the overview completely after ANIMATION_TIME,
// and don't want the shading animation to get cut off

View File

@@ -8,9 +8,8 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const ViewSelector = imports.ui.viewSelector;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
const Overview = imports.ui.overview;
var SIDE_CONTROLS_ANIMATION_TIME = Overview.ANIMATION_TIME;
var SIDE_CONTROLS_ANIMATION_TIME = 160;
function getRtlSlideDirection(direction, actor) {
let rtl = actor.text_direction == Clutter.TextDirection.RTL;
@@ -474,7 +473,6 @@ class ControlsManager extends St.Widget {
// A workspace might have been inserted or removed before the active
// one, causing the adjustment to go out of sync, so update the value
this._workspaceAdjustment.remove_transition('value');
this._workspaceAdjustment.value = activeIndex;
}

View File

@@ -2,7 +2,7 @@
/* exported PadOsd, PadOsdService */
const { Atk, Clutter, GDesktopEnums, Gio,
GLib, GObject, Gtk, Meta, Pango, Rsvg, St } = imports.gi;
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -89,7 +89,7 @@ var PadChooser = GObject.registerClass({
});
var KeybindingEntry = GObject.registerClass({
Signals: { 'keybinding-edited': { param_types: [GObject.TYPE_STRING] } },
Signals: { 'keybinding-edited': {} },
}, class KeybindingEntry extends St.Entry {
_init() {
super._init({ hint_text: _("New shortcut…"), style: 'width: 10em' });
@@ -329,7 +329,6 @@ var PadDiagram = GObject.registerClass({
this._imagePath = imagePath;
this._handle = this._composeStyledDiagram();
this._initLabels();
}
// eslint-disable-next-line camelcase
@@ -344,26 +343,6 @@ var PadDiagram = GObject.registerClass({
this.add_actor(actor);
}
_initLabels() {
let i = 0;
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.BUTTON, i))
break;
}
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.RING, i, CW) ||
!this._addLabel(Meta.PadActionType.RING, i, CCW))
break;
}
for (i = 0; ; i++) {
if (!this._addLabel(Meta.PadActionType.STRIP, i, UP) ||
!this._addLabel(Meta.PadActionType.STRIP, i, DOWN))
break;
}
}
_wrappingSvgHeader() {
return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
@@ -383,8 +362,10 @@ var PadDiagram = GObject.registerClass({
for (let i = 0; i < this._activeButtons.length; i++) {
let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
css += '.%s.Leader { stroke: %s !important; }'.format(ch, ACTIVE_COLOR);
css += '.%s.Button { stroke: %s !important; fill: %s !important; }'.format(ch, ACTIVE_COLOR, ACTIVE_COLOR);
css += '.%s {'.format(ch);
css += ' stroke: %s !important;'.format(ACTIVE_COLOR);
css += ' fill: %s !important;'.format(ACTIVE_COLOR);
css += '}';
}
return css;
@@ -409,6 +390,9 @@ var PadDiagram = GObject.registerClass({
}
_updateDiagramScale() {
if (this._handle == null)
return;
[this._actorWidth, this._actorHeight] = this.get_size();
let dimensions = this._handle.get_dimensions();
let scaleX = this._actorWidth / dimensions.width;
@@ -421,11 +405,6 @@ var PadDiagram = GObject.registerClass({
let [, natWidth] = child.get_preferred_width(natHeight);
let childBox = new Clutter.ActorBox();
// I miss Cairo.Matrix
let dimensions = this._handle.get_dimensions();
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
if (direction == LTR) {
childBox.x1 = x;
childBox.x2 = x + natWidth;
@@ -441,18 +420,17 @@ var PadDiagram = GObject.registerClass({
vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags);
if (this._handle === null)
return;
this._updateDiagramScale();
for (let i = 0; i < this._labels.length; i++) {
const { label, x, y, arrangement } = this._labels[i];
let [label, action, idx, dir] = this._labels[i];
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(label, x, y, arrangement);
}
if (this._editorActor && this._curEdited) {
const { x, y, arrangement } = this._curEdited;
let [label_, action, idx, dir] = this._curEdited;
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(this._editorActor, x, y, arrangement);
}
}
@@ -479,6 +457,17 @@ var PadDiagram = GObject.registerClass({
cr.$dispose();
}
_transformPoint(x, y) {
if (this._handle == null || this._scale == null)
return [x, y];
// I miss Cairo.Matrix
let dimensions = this._handle.get_dimensions();
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
return [Math.round(x), Math.round(y)];
}
_getItemLabelCoords(labelName, leaderName) {
if (this._handle == null)
return [false];
@@ -506,39 +495,44 @@ var PadDiagram = GObject.registerClass({
pos.y = this._imageHeight - pos.y;
}
return [true, pos.x, pos.y, direction];
let [x, y] = this._transformPoint(pos.x, pos.y);
return [true, x, y, direction];
}
_getButtonLabels(button) {
getButtonLabelCoords(button) {
let ch = String.fromCharCode('A'.charCodeAt() + button);
let labelName = 'Label%s'.format(ch);
let leaderName = 'Leader%s'.format(ch);
return [labelName, leaderName];
return this._getItemLabelCoords(labelName, leaderName);
}
_getRingLabels(number, dir) {
getRingLabelCoords(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == CW ? 'CW' : 'CCW';
let labelName = 'LabelRing%s%s'.format(numStr, dirStr);
let leaderName = 'LeaderRing%s%s'.format(numStr, dirStr);
return [labelName, leaderName];
return this._getItemLabelCoords(labelName, leaderName);
}
_getStripLabels(number, dir) {
getStripLabelCoords(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == UP ? 'Up' : 'Down';
let labelName = 'LabelStrip%s%s'.format(numStr, dirStr);
let leaderName = 'LeaderStrip%s%s'.format(numStr, dirStr);
return [labelName, leaderName];
return this._getItemLabelCoords(labelName, leaderName);
}
_getLabelCoords(action, idx, dir) {
getLabelCoords(action, idx, dir) {
if (action == Meta.PadActionType.BUTTON)
return this._getItemLabelCoords(...this._getButtonLabels(idx));
return this.getButtonLabelCoords(idx);
else if (action == Meta.PadActionType.RING)
return this._getItemLabelCoords(...this._getRingLabels(idx, dir));
return this.getRingLabelCoords(idx, dir);
else if (action == Meta.PadActionType.STRIP)
return this._getItemLabelCoords(...this._getStripLabels(idx, dir));
return this.getStripLabelCoords(idx, dir);
return [false];
}
@@ -563,30 +557,26 @@ var PadDiagram = GObject.registerClass({
this._invalidateSvg();
}
_addLabel(action, idx, dir) {
let [found, x, y, arrangement] = this._getLabelCoords(action, idx, dir);
if (!found)
return false;
let label = new St.Label();
this._labels.push({ label, action, idx, dir, x, y, arrangement });
addLabel(label, type, idx, dir) {
this._labels.push([label, type, idx, dir]);
this.add_actor(label);
return true;
}
updateLabels(getText) {
for (let i = 0; i < this._labels.length; i++) {
const { label, action, idx, dir } = this._labels[i];
let [label, action, idx, dir] = this._labels[i];
let str = getText(action, idx, dir);
label.set_text(str);
}
this.queue_relayout();
}
_applyLabel(label, action, idx, dir, str) {
if (str !== null)
if (str != null) {
label.set_text(str);
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(label, x, y, arrangement);
}
label.show();
}
@@ -594,20 +584,18 @@ var PadDiagram = GObject.registerClass({
this._editorActor.hide();
if (this._prevEdited) {
const { label, action, idx, dir } = this._prevEdited;
let [label, action, idx, dir] = this._prevEdited;
this._applyLabel(label, action, idx, dir, str);
this._prevEdited = null;
}
if (this._curEdited) {
const { label, action, idx, dir } = this._curEdited;
let [label, action, idx, dir] = this._curEdited;
this._applyLabel(label, action, idx, dir, str);
if (continues)
this._prevEdited = this._curEdited;
this._curEdited = null;
}
this.queue_relayout();
}
startEdition(action, idx, dir) {
@@ -617,19 +605,21 @@ var PadDiagram = GObject.registerClass({
return;
for (let i = 0; i < this._labels.length; i++) {
if (action == this._labels[i].action &&
idx == this._labels[i].idx && dir == this._labels[i].dir) {
let [label, itemAction, itemIdx, itemDir] = this._labels[i];
if (action == itemAction && idx == itemIdx && dir == itemDir) {
this._curEdited = this._labels[i];
editedLabel = this._curEdited.label;
editedLabel = label;
break;
}
}
if (this._curEdited == null)
return;
let [found] = this.getLabelCoords(action, idx, dir);
if (!found)
return;
this._editorActor.show();
editedLabel.hide();
this.queue_relayout();
}
});
@@ -703,7 +693,6 @@ var PadOsd = GObject.registerClass({
this._titleLabel = new St.Label({ style: 'font-side: larger; font-weight: bold;',
x_align: Clutter.ActorAlign.CENTER });
this._titleLabel.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this._titleLabel.clutter_text.set_text(padDevice.get_device_name());
labelBox.add_actor(this._titleLabel);
@@ -721,7 +710,31 @@ var PadOsd = GObject.registerClass({
x_expand: true,
y_expand: true });
this.add_actor(this._padDiagram);
this._updateActionLabels();
// FIXME: Fix num buttons.
let i = 0;
for (i = 0; i < 50; i++) {
let [found] = this._padDiagram.getButtonLabelCoords(i);
if (!found)
break;
this._createLabel(Meta.PadActionType.BUTTON, i);
}
for (i = 0; i < padDevice.get_n_rings(); i++) {
let [found] = this._padDiagram.getRingLabelCoords(i, CW);
if (!found)
break;
this._createLabel(Meta.PadActionType.RING, i, CW);
this._createLabel(Meta.PadActionType.RING, i, CCW);
}
for (i = 0; i < padDevice.get_n_strips(); i++) {
let [found] = this._padDiagram.getStripLabelCoords(i, UP);
if (!found)
break;
this._createLabel(Meta.PadActionType.STRIP, i, UP);
this._createLabel(Meta.PadActionType.STRIP, i, DOWN);
}
let buttonBox = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand: true,
@@ -774,6 +787,11 @@ var PadOsd = GObject.registerClass({
return str ? str : _("None");
}
_createLabel(type, number, dir) {
let label = new St.Label({ text: this._getActionText(type, number) });
this._padDiagram.addLabel(label, type, number, dir);
}
_updateActionLabels() {
this._padDiagram.updateLabels(this._getActionText.bind(this));
}
@@ -849,7 +867,8 @@ var PadOsd = GObject.registerClass({
this._tipLabel.set_text(_("Press any key to exit"));
}
this._titleLabel.set_text(title);
this._titleLabel.clutter_text.set_markup(
'<span size="larger"><b>%s</b></span>'.format(title));
}
_isEditedAction(type, number, dir) {

View File

@@ -100,7 +100,7 @@ class AppMenu extends PopupMenu.PopupMenu {
'org.gtk.Actions', 'Activate',
GLib.Variant.new('(sava{sv})',
['details', [args], null]),
null, 0, -1, null);
null, 0, -1, null, null);
});
});
@@ -216,10 +216,7 @@ var AppMenuButton = GObject.registerClass({
this._onIconThemeChanged.bind(this));
let iconEffect = new Clutter.DesaturateEffect();
this._iconBox = new St.Bin({
style_class: 'app-menu-icon',
y_align: Clutter.ActorAlign.CENTER,
});
this._iconBox = new St.Bin({ style_class: 'app-menu-icon' });
this._iconBox.add_effect(iconEffect);
this._container.add_actor(this._iconBox);
@@ -967,7 +964,7 @@ class Panel extends St.Widget {
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyEvent);
return Clutter.EVENT_PROPAGATE;
}
_toggleMenu(indicator) {

View File

@@ -247,7 +247,7 @@ var RemoteSearchProvider = class {
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
log('Received error from D-Bus search provider %s: %s'.format(this.id, String(error)));
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
callback([]);
return;
}
@@ -274,7 +274,7 @@ var RemoteSearchProvider = class {
_getResultMetasFinished(results, error, callback) {
if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from D-Bus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
log('Received error from DBus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
callback([]);
return;
}

View File

@@ -498,8 +498,6 @@ var ScreenShield = class {
if (Main.sessionMode.currentMode == 'unlock-dialog')
Main.sessionMode.popMode('unlock-dialog');
this.emit('wake-up-screen');
if (this._isGreeter) {
// We don't want to "deactivate" any more than
// this. In particular, we don't want to drop
@@ -521,9 +519,6 @@ var ScreenShield = class {
this._isModal = false;
}
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
this._lockDialogGroup.ease({
translation_y: -global.screen_height,
duration: Overview.ANIMATION_TIME,
@@ -538,6 +533,8 @@ var ScreenShield = class {
this._dialog = null;
}
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
this.actor.hide();
if (this._becameActiveId != 0) {

View File

@@ -30,9 +30,7 @@ var ScreenshotService = class {
let sender = invocation.get_sender();
if (this._screenShooter.has(sender) || lockedDown) {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.BUSY,
'There is an ongoing operation for this sender');
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return null;
}
@@ -86,7 +84,7 @@ var ScreenshotService = class {
}
}
_createStream(filename, invocation) {
_createStream(filename) {
if (filename == '')
return [Gio.MemoryOutputStream.new_resizable(), null];
@@ -96,7 +94,6 @@ var ScreenshotService = class {
let stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
return [stream, file];
} catch (e) {
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return [null, null];
}
}
@@ -107,22 +104,23 @@ var ScreenshotService = class {
return [stream, file];
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.EXISTS))
break;
return [null, null];
}
}
invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return [null, null];
}
_onScreenshotComplete(area, stream, file, flash, invocation) {
if (flash) {
let flashspot = new Flashspot(area);
flashspot.fire(() => {
_onScreenshotComplete(result, area, stream, file, flash, invocation) {
if (result) {
if (flash) {
let flashspot = new Flashspot(area);
flashspot.fire(() => {
this._removeShooterForSender(invocation.get_sender());
});
} else {
this._removeShooterForSender(invocation.get_sender());
});
} else {
this._removeShooterForSender(invocation.get_sender());
}
}
stream.close(null);
@@ -136,7 +134,7 @@ var ScreenshotService = class {
clipboard.set_content(St.ClipboardType.CLIPBOARD, 'image/png', bytes);
}
let retval = GLib.Variant.new('(bs)', [true, filenameUsed]);
let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
invocation.return_value(retval);
}
@@ -171,20 +169,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_area(x, y, width, height, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}
@@ -195,20 +190,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot_window(includeFrame, includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}
@@ -219,20 +211,17 @@ var ScreenshotService = class {
if (!screenshot)
return;
let [stream, file] = this._createStream(filename, invocation);
if (!stream)
return;
let [stream, file] = this._createStream(filename);
screenshot.screenshot(includeCursor, stream,
(o, res) => {
try {
let [success_, area] =
let [result, area] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(
area, stream, file, flash, invocation);
result, area, stream, file, flash, invocation);
} catch (e) {
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(new GLib.Variant('(bs)', [false, '']));
invocation.return_gerror(e);
}
});
}
@@ -292,8 +281,6 @@ var ScreenshotService = class {
invocation.return_error_literal(
Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
'Operation was cancelled');
} finally {
this._removeShooterForSender(invocation.get_sender());
}
}
};

View File

@@ -15,7 +15,6 @@ const _modes = {
'restrictive': {
parentMode: null,
stylesheetName: 'gnome-shell.css',
themeResourceName: 'gnome-shell-theme.gresource',
hasOverview: false,
showCalendarEvents: false,
allowSettings: false,

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GnomeShell, ScreenSaverDBus */
const { Gio, GLib, Meta } = imports.gi;
const { Gio, GLib, Meta, Shell } = imports.gi;
const Config = imports.misc.config;
const ExtensionDownloader = imports.ui.extensionDownloader;
@@ -255,17 +255,6 @@ var GnomeShellExtensions = class {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
this._userExtensionsEnabled = this.UserExtensionsEnabled;
global.settings.connect('changed::disable-user-extensions', () => {
if (this._userExtensionsEnabled === this.UserExtensionsEnabled)
return;
this._userExtensionsEnabled = this.UserExtensionsEnabled;
this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
new GLib.Variant('b', this._userExtensionsEnabled));
});
Main.extensionManager.connect('extension-state-changed',
this._extensionStateChanged.bind(this));
}
@@ -312,18 +301,20 @@ var GnomeShellExtensions = class {
}
LaunchExtensionPrefs(uuid) {
this.OpenExtensionPrefs(uuid, '', {});
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.Extensions.desktop');
let info = app.get_app_info();
let timestamp = global.display.get_current_time_roundtrip();
info.launch_uris([`extension:///${uuid}`],
global.create_app_launch_context(timestamp, -1));
}
OpenExtensionPrefs(uuid, parentWindow, options) {
Main.extensionManager.openExtensionPrefs(uuid, parentWindow, options);
}
ReloadExtension(uuid) {
let extension = Main.extensionManager.lookup(uuid);
if (!extension)
return;
ReloadExtensionAsync(params, invocation) {
invocation.return_error_literal(
Gio.DBusError,
Gio.DBusError.NOT_SUPPORTED,
'ReloadExtension is deprecated and does not work');
Main.extensionManager.reloadExtension(extension);
}
CheckForUpdates() {
@@ -334,14 +325,6 @@ var GnomeShellExtensions = class {
return Config.PACKAGE_VERSION;
}
get UserExtensionsEnabled() {
return !global.settings.get_boolean('disable-user-extensions');
}
set UserExtensionsEnabled(enable) {
global.settings.set_boolean('disable-user-extensions', !enable);
}
_extensionStateChanged(_, newState) {
let state = ExtensionUtils.serializeExtension(newState);
this._dbusImpl.emit_signal('ExtensionStateChanged',

View File

@@ -447,8 +447,12 @@ var ShellMountPasswordDialog = GObject.registerClass({
let useKeyfiles = this._keyfilesCheckbox.checked;
this._passwordEntry.reactive = !useKeyfiles;
this._passwordEntry.can_focus = !useKeyfiles;
this._passwordEntry.clutter_text.editable = !useKeyfiles;
this._passwordEntry.clutter_text.selectable = !useKeyfiles;
this._pimEntry.reactive = !useKeyfiles;
this._pimEntry.can_focus = !useKeyfiles;
this._pimEntry.clutter_text.editable = !useKeyfiles;
this._pimEntry.clutter_text.selectable = !useKeyfiles;
this._rememberChoice.reactive = !useKeyfiles;
this._rememberChoice.can_focus = !useKeyfiles;
this._keyfilesLabel.visible = useKeyfiles;

View File

@@ -43,10 +43,10 @@ var Slider = GObject.registerClass({
let [hasHandleColor, handleBorderColor] =
themeNode.lookup_color('-slider-handle-border-color', false);
const ceiledHandleRadius = Math.ceil(handleRadius + handleBorderWidth);
const handleX = ceiledHandleRadius +
(width - 2 * ceiledHandleRadius) * this._value / this._maxValue;
const handleY = height / 2;
let wholeHandleRadius = Math.ceil(handleRadius);
let handleX = wholeHandleRadius +
(width - 2 * wholeHandleRadius) * this._value / this._maxValue;
let handleY = height / 2;
let color = themeNode.get_foreground_color();
Clutter.cairo_set_source_color(cr, color);
@@ -186,7 +186,7 @@ var Slider = GObject.registerClass({
this.value = Math.max(0, Math.min(this._value + delta, this._maxValue));
return Clutter.EVENT_STOP;
}
return super.vfunc_key_press_event(keyPressEvent);
return Clutter.EVENT_PROPAGATE;
}
_moveHandle(absX, _absY) {

View File

@@ -139,14 +139,14 @@ class ATIndicator extends PanelMenu.Button {
interfaceSettings.is_writable(KEY_ICON_THEME),
enabled => {
if (enabled) {
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
} else if (!hasHC) {
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
} else {
interfaceSettings.reset(KEY_ICON_THEME);
interfaceSettings.reset(KEY_GTK_THEME);
interfaceSettings.reset(KEY_ICON_THEME);
}
});

View File

@@ -48,9 +48,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.connect('key-press-event', (actor, event) => {
return this._slider.emit('key-press-event', event);
});
this._item.connect('scroll-event', (actor, event) => {
return this._slider.emit('scroll-event', event);
});
}
_sliderChanged() {

View File

@@ -64,7 +64,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._item.label.text = _("Location Enabled");
this._onOffAction = this._item.menu.addAction(_("Disable"), this._onOnOffAction.bind(this));
this._item.menu.addSettingsAction(_('Privacy Settings'), 'gnome-location-panel.desktop');
this._item.menu.addSettingsAction(_("Privacy Settings"), 'gnome-privacy-panel.desktop');
this.menu.addMenuItem(this._item);

View File

@@ -112,12 +112,12 @@ class Indicator extends PanelMenu.SystemIndicator {
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
? '-charging' : '';
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
const charged =
this._proxy.State === UPower.DeviceState.FULLY_CHARGED ||
(this._proxy.State === UPower.DeviceState.CHARGING && fillLevel === 100);
const icon = charged
? 'battery-level-100-charged-symbolic'
: 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
let icon;
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED ||
fillLevel === 100)
icon = 'battery-level-100-charged-symbolic';
else
icon = 'battery-level-%d%s-symbolic'.format(fillLevel, chargingState);
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
// default fallbacks

View File

@@ -56,9 +56,6 @@ var StreamSlider = class {
this.item.connect('key-press-event', (actor, event) => {
return this._slider.emit('key-press-event', event);
});
this.item.connect('scroll-event', (actor, event) => {
return this._slider.emit('scroll-event', event);
});
this._stream = null;
this._volumeCancellable = null;
@@ -141,13 +138,12 @@ var StreamSlider = class {
}
_notifyVolumeChange() {
if (this._volumeCancellable)
this._volumeCancellable.cancel();
this._volumeCancellable = null;
if (this._stream.state === Gvc.MixerStreamState.RUNNING)
return; // feedback not necessary while playing
if (this._volumeCancellable)
this._volumeCancellable.cancel();
this._volumeCancellable = new Gio.Cancellable();
let player = global.display.get_sound_player();
player.play_from_theme('audio-volume-change',

View File

@@ -115,7 +115,7 @@ var NotificationsBox = GObject.registerClass({
box.add_child(textBox);
let title = new St.Label({
text: source.title.replace(/\n/g, ' '),
text: source.title,
style_class: 'unlock-dialog-notification-label',
});
textBox.add(title);
@@ -129,10 +129,9 @@ var NotificationsBox = GObject.registerClass({
let body = '';
if (n.bannerBodyText) {
const bodyText = n.bannerBodyText.replace(/\n/g, ' ');
body = n.bannerBodyMarkup
? bodyText
: GLib.markup_escape_text(bodyText, -1);
? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
}
let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' });
@@ -524,10 +523,6 @@ var UnlockDialog = GObject.registerClass({
this._bgManagers = [];
const themeContext = St.ThemeContext.get_for_stage(global.stage);
this._scaleChangedId = themeContext.connect('notify::scale-factor',
() => this._updateBackgroundEffects());
this._updateBackgrounds();
this._monitorsChangedId =
Main.layoutManager.connect('monitors-changed', this._updateBackgrounds.bind(this));
@@ -570,17 +565,9 @@ var UnlockDialog = GObject.registerClass({
this._otherUserButton.set_pivot_point(0.5, 0.5);
this._otherUserButton.connect('clicked', this._otherUserClicked.bind(this));
this._screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' });
this._userSwitchEnabledId = 0;
this._userSwitchEnabledId = this._screenSaverSettings.connect('changed::user-switch-enabled',
this._updateUserSwitchVisibility.bind(this));
this._userLoadedId = 0;
this._userLoadedId = this._user.connect('notify::is-loaded',
this._updateUserSwitchVisibility.bind(this));
this._updateUserSwitchVisibility();
let screenSaverSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.screensaver' });
screenSaverSettings.bind('user-switch-enabled',
this._otherUserButton, 'visible', Gio.SettingsBindFlags.GET);
// Main Box
let mainBox = new St.Widget();
@@ -617,7 +604,7 @@ var UnlockDialog = GObject.registerClass({
this._showPrompt();
if (GLib.unichar_isgraph(unichar))
this._authPrompt.addCharacter(unichar);
this.addCharacter(unichar);
return Clutter.EVENT_PROPAGATE;
}
@@ -630,7 +617,6 @@ var UnlockDialog = GObject.registerClass({
y: monitor.y,
width: monitor.width,
height: monitor.height,
effect: new Shell.BlurEffect({ name: 'blur' }),
});
let bgManager = new Background.BackgroundManager({
@@ -642,17 +628,19 @@ var UnlockDialog = GObject.registerClass({
this._bgManagers.push(bgManager);
this._backgroundGroup.add_child(widget);
}
_updateBackgroundEffects() {
const themeContext = St.ThemeContext.get_for_stage(global.stage);
for (const widget of this._backgroundGroup.get_children()) {
widget.get_effect('blur').set({
brightness: BLUR_BRIGHTNESS,
sigma: BLUR_SIGMA * themeContext.scale_factor,
});
}
let effect = new Shell.BlurEffect({
brightness: BLUR_BRIGHTNESS,
sigma: BLUR_SIGMA * themeContext.scale_factor,
});
this._scaleChangedId = themeContext.connect('notify::scale-factor', () => {
effect.sigma = BLUR_SIGMA * themeContext.scale_factor;
});
widget.add_effect(effect);
}
_updateBackgrounds() {
@@ -664,7 +652,6 @@ var UnlockDialog = GObject.registerClass({
for (let i = 0; i < Main.layoutManager.monitors.length; i++)
this._createBackground(i);
this._updateBackgroundEffects();
}
_ensureAuthPrompt() {
@@ -773,7 +760,7 @@ var UnlockDialog = GObject.registerClass({
}
_escape() {
if (this._authPrompt && this.allowCancel)
if (this.allowCancel)
this._authPrompt.cancel();
}
@@ -840,21 +827,6 @@ var UnlockDialog = GObject.registerClass({
this._gdmClient = null;
delete this._gdmClient;
}
if (this._userLoadedId) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userSwitchEnabledId) {
this._screenSaverSettings.disconnect(this._userSwitchEnabledId);
this._userSwitchEnabledId = 0;
}
}
_updateUserSwitchVisibility() {
this._otherUserButton.visible = this._userManager.can_switch() &&
this._screenSaverSettings.get_boolean('user-switch-enabled');
}
cancel() {
@@ -862,6 +834,11 @@ var UnlockDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(unichar) {
this._showPrompt();
this._authPrompt.addCharacter(unichar);
}
finish(onComplete) {
this._ensureAuthPrompt();
this._authPrompt.finish(onComplete);

View File

@@ -57,11 +57,11 @@ var WindowAttentionHandler = class {
var WindowAttentionSource = GObject.registerClass(
class WindowAttentionSource extends MessageTray.Source {
_init(app, window) {
super._init(app.get_name());
this._window = window;
this._app = app;
super._init(app.get_name());
this.signalIDs = [];
this.signalIDs.push(this._window.connect('notify::demands-attention',
this._sync.bind(this)));

View File

@@ -82,10 +82,8 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
_formatCountDown() {
const fmt = ngettext(
'Settings changes will revert in %d second',
'Settings changes will revert in %d seconds',
this._countDown);
let fmt = ngettext("Settings changes will revert in %d second",
"Settings changes will revert in %d seconds");
return fmt.format(this._countDown);
}
@@ -900,47 +898,32 @@ var WindowManager = class {
global.display.connect('init-xserver', (display, task) => {
IBusManager.getIBusManager().restartDaemon(['--xim']);
Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail');
try {
if (!Shell.util_start_systemd_unit('gsd-xsettings.target', 'fail'))
log('Not starting gsd-xsettings; waiting for gnome-session to do so');
/* Leave this watchdog timeout so don't block indefinitely here */
let timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, () => {
Gio.DBus.session.unwatch_name(watchId);
task.return_boolean(false);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
/* Leave this watchdog timeout so don't block indefinitely here */
let timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 5, () => {
/* When gsd-xsettings daemon is started, we are good to resume */
let watchId = Gio.DBus.session.watch_name(
'org.gnome.SettingsDaemon.XSettings',
Gio.BusNameWatcherFlags.NONE,
() => {
Gio.DBus.session.unwatch_name(watchId);
log('Warning: Failed to start gsd-xsettings');
task.return_boolean(true);
timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
/* When gsd-xsettings daemon is started, we are good to resume */
let watchId = Gio.DBus.session.watch_name(
'org.gnome.SettingsDaemon.XSettings',
Gio.BusNameWatcherFlags.NONE,
() => {
Gio.DBus.session.unwatch_name(watchId);
if (timeoutId > 0) {
task.return_boolean(true);
GLib.source_remove(timeoutId);
}
},
null);
} catch (e) {
log('Error starting gsd-xsettings: %s'.format(e.message));
task.return_boolean(true);
}
if (timeoutId > 0) {
task.return_boolean(true);
GLib.source_remove(timeoutId);
}
},
null);
return true;
});
global.display.connect('x11-display-closing', () => {
if (!Meta.is_wayland_compositor())
return;
try {
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
} catch (e) {
log('Error stopping gsd-xsettings: %s'.format(e.message));
}
Shell.util_stop_systemd_unit('gsd-xsettings.target', 'fail');
IBusManager.getIBusManager().restartDaemon();
});

View File

@@ -404,7 +404,7 @@ var WindowClone = GObject.registerClass({
return true;
}
return super.vfunc_key_press_event(keyEvent);
return false;
}
_onClicked() {

View File

@@ -8,7 +8,6 @@ const SwipeTracker = imports.ui.swipeTracker;
const Workspace = imports.ui.workspace;
var WORKSPACE_SWITCH_TIME = 250;
var SCROLL_TIMEOUT_TIME = 150;
var AnimationType = {
ZOOM: 0,
@@ -450,7 +449,6 @@ class WorkspacesDisplay extends St.Widget {
this._keyPressEventId = 0;
this._scrollTimeoutId = 0;
this._actualGeometry = null;
this._fullGeometry = null;
this._inWindowDrag = false;
@@ -611,16 +609,13 @@ class WorkspacesDisplay extends St.Widget {
show(fadeOnPrimary) {
this._updateWorkspacesViews();
if (this._actualGeometry && this._fullGeometry) {
for (let i = 0; i < this._workspacesViews.length; i++) {
let animationType;
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateToOverview(animationType);
}
for (let i = 0; i < this._workspacesViews.length; i++) {
let animationType;
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateToOverview(animationType);
}
this._restackedNotifyId =
@@ -694,10 +689,8 @@ class WorkspacesDisplay extends St.Widget {
this._workspacesViews.forEach(v => v.show());
if (this._fullGeometry)
this._syncWorkspacesFullGeometry();
if (this._actualGeometry)
this._syncWorkspacesActualGeometry();
this._updateWorkspacesFullGeometry();
this._updateWorkspacesActualGeometry();
}
_getMonitorIndexForEvent(event) {
@@ -749,10 +742,10 @@ class WorkspacesDisplay extends St.Widget {
// the sliding controls were never slid in at all.
setWorkspacesFullGeometry(geom) {
this._fullGeometry = geom;
this._syncWorkspacesFullGeometry();
this._updateWorkspacesFullGeometry();
}
_syncWorkspacesFullGeometry() {
_updateWorkspacesFullGeometry() {
if (!this._workspacesViews.length)
return;
@@ -764,21 +757,18 @@ class WorkspacesDisplay extends St.Widget {
}
_updateWorkspacesActualGeometry() {
const [x, y] = this.get_transformed_position();
const width = this.allocation.get_width();
const height = this.allocation.get_height();
this._actualGeometry = { x, y, width, height };
this._syncWorkspacesActualGeometry();
}
_syncWorkspacesActualGeometry() {
if (!this._workspacesViews.length)
return;
let [x, y] = this.get_transformed_position();
let allocation = this.allocation;
let width = allocation.x2 - allocation.x1;
let height = allocation.y2 - allocation.y1;
let primaryGeometry = { x, y, width, height };
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
let geometry = i === this._primaryIndex ? this._actualGeometry : monitors[i];
let geometry = i == this._primaryIndex ? primaryGeometry : monitors[i];
this._workspacesViews[i].setActualGeometry(geometry);
}
}
@@ -825,7 +815,7 @@ class WorkspacesDisplay extends St.Widget {
this._canScroll = false;
this._scrollTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
SCROLL_TIMEOUT_TIME, () => {
WORKSPACE_SWITCH_TIME, () => {
this._canScroll = true;
this._scrollTimeoutId = 0;
return GLib.SOURCE_REMOVE;

Some files were not shown because too many files have changed in this diff Show More