Renamed Extension -> LegacyExtension. Extracted common Extension support methods.
This commit is contained in:
parent
901c591511
commit
17b3890688
@ -39,7 +39,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import dorkbox.systemTray.gnomeShell.DummyFile;
|
import dorkbox.systemTray.gnomeShell.DummyFile;
|
||||||
import dorkbox.systemTray.gnomeShell.Extension;
|
import dorkbox.systemTray.gnomeShell.LegacyExtension;
|
||||||
import dorkbox.systemTray.ui.awt._AwtTray;
|
import dorkbox.systemTray.ui.awt._AwtTray;
|
||||||
import dorkbox.systemTray.ui.gtk._AppIndicatorNativeTray;
|
import dorkbox.systemTray.ui.gtk._AppIndicatorNativeTray;
|
||||||
import dorkbox.systemTray.ui.gtk._GtkStatusIconNativeTray;
|
import dorkbox.systemTray.ui.gtk._GtkStatusIconNativeTray;
|
||||||
@ -283,8 +283,8 @@ class SystemTray {
|
|||||||
Extension.install();
|
Extension.install();
|
||||||
|
|
||||||
// this can be gnome3 on debian/kali
|
// this can be gnome3 on debian/kali
|
||||||
|
|
||||||
if (OSUtil.Linux.isKali()) {
|
if (OSUtil.Linux.isKali()) {
|
||||||
|
LegacyExtension.install();
|
||||||
return selectTypeQuietly(TrayType.GtkStatusIcon);
|
return selectTypeQuietly(TrayType.GtkStatusIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,8 +294,9 @@ class SystemTray {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
logger.debug("Disabling the extension install. It won't work.");
|
logger.debug("Disabling the extension install. It won't work.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Extension.ENABLE_EXTENSION_INSTALL = false;
|
else {
|
||||||
|
LegacyExtension.install();
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectTypeQuietly(TrayType.GtkStatusIcon);
|
return selectTypeQuietly(TrayType.GtkStatusIcon);
|
||||||
@ -322,12 +323,8 @@ class SystemTray {
|
|||||||
if (!DummyFile.isPresent()) {
|
if (!DummyFile.isPresent()) {
|
||||||
DummyFile.install();
|
DummyFile.install();
|
||||||
|
|
||||||
if (!Extension.ENABLE_EXTENSION_INSTALL) {
|
// just restarting the shell is enough to get the system tray to work
|
||||||
logger.warn("You must log out-in for the system tray to work.");
|
LegacyExtension.restartShell();
|
||||||
}
|
|
||||||
else {
|
|
||||||
Extension.restartShell();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,7 +916,7 @@ class SystemTray {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (isTrayType(trayType, TrayType.GtkStatusIcon)) {
|
} else if (isTrayType(trayType, TrayType.GtkStatusIcon)) {
|
||||||
if (!Extension.isInstalled()) {
|
if (!LegacyExtension.isInstalled()) {
|
||||||
// Automatically install the extension for everyone except Arch. They are bonkers.
|
// Automatically install the extension for everyone except Arch. They are bonkers.
|
||||||
Extension.ENABLE_EXTENSION_INSTALL = false;
|
Extension.ENABLE_EXTENSION_INSTALL = false;
|
||||||
SystemTray.logger.info("You may need a work-around for showing the SystemTray icon - we suggest installing the " +
|
SystemTray.logger.info("You may need a work-around for showing the SystemTray icon - we suggest installing the " +
|
||||||
|
@ -1,443 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 dorkbox, llc
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package dorkbox.systemTray.gnomeShell;
|
|
||||||
|
|
||||||
import static dorkbox.systemTray.SystemTray.logger;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import dorkbox.executor.ShellAsyncExecutor;
|
|
||||||
import dorkbox.executor.ShellExecutor;
|
|
||||||
import dorkbox.systemTray.SystemTray;
|
|
||||||
import dorkbox.util.IO;
|
|
||||||
import dorkbox.util.OSUtil;
|
|
||||||
import dorkbox.util.Property;
|
|
||||||
|
|
||||||
@SuppressWarnings({"DanglingJavadoc", "WeakerAccess"})
|
|
||||||
public
|
|
||||||
class Extension {
|
|
||||||
private static final String UID = "SystemTray@Dorkbox";
|
|
||||||
public static final String DEFAULT_NAME = "SystemTray";
|
|
||||||
|
|
||||||
@Property
|
|
||||||
/**
|
|
||||||
* Permit the StatusTray icon to be displayed next to the clock by installing an extension. By default, gnome places the icon in the
|
|
||||||
* "notification drawer", which is a collapsible menu at (usually) bottom left corner of the screen.
|
|
||||||
*/
|
|
||||||
public static boolean ENABLE_EXTENSION_INSTALL = true;
|
|
||||||
|
|
||||||
@Property
|
|
||||||
/** Permit the gnome-shell to be restarted when the extension is installed. */
|
|
||||||
public static boolean ENABLE_SHELL_RESTART = true;
|
|
||||||
|
|
||||||
@Property
|
|
||||||
/** Command to restart the gnome-shell. It is recommended to start it in the background (hence '&') */
|
|
||||||
public static String SHELL_RESTART_COMMAND = "gnome-shell --replace &";
|
|
||||||
|
|
||||||
public static
|
|
||||||
List<String> getEnabledExtensions() {
|
|
||||||
// gsettings get org.gnome.shell enabled-extensions
|
|
||||||
final ShellExecutor gsettings = new ShellExecutor();
|
|
||||||
gsettings.setExecutable("gsettings");
|
|
||||||
gsettings.addArgument("get");
|
|
||||||
gsettings.addArgument("org.gnome.shell");
|
|
||||||
gsettings.addArgument("enabled-extensions");
|
|
||||||
gsettings.start();
|
|
||||||
|
|
||||||
String output = gsettings.getOutput();
|
|
||||||
|
|
||||||
// now we have to enable us if we aren't already enabled
|
|
||||||
|
|
||||||
// gsettings get org.gnome.shell enabled-extensions
|
|
||||||
// defaults are:
|
|
||||||
// - fedora 23: ['background-logo@fedorahosted.org'] on
|
|
||||||
// - openSuse:
|
|
||||||
// - Ubuntu Gnome 16.04: @as []
|
|
||||||
|
|
||||||
final StringBuilder stringBuilder = new StringBuilder(output);
|
|
||||||
|
|
||||||
// have to remove the end first, otherwise we would have to re-index the location of the ]
|
|
||||||
|
|
||||||
// remove the last ]
|
|
||||||
int extensionIndex = output.indexOf("]");
|
|
||||||
if (extensionIndex > 0) {
|
|
||||||
stringBuilder.delete(extensionIndex, stringBuilder.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip off UP-TO plus the leading [
|
|
||||||
extensionIndex = output.indexOf("[");
|
|
||||||
if (extensionIndex >= 0) {
|
|
||||||
stringBuilder.delete(0, extensionIndex+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// should be 'background-logo@fedorahosted.org', 'zyx', 'abs'
|
|
||||||
// or nothing
|
|
||||||
|
|
||||||
String installedExtensions = stringBuilder.toString();
|
|
||||||
|
|
||||||
// now just split the extensions into a list so it is easier to manage
|
|
||||||
|
|
||||||
String[] split = installedExtensions
|
|
||||||
.split(", ");
|
|
||||||
for (int i = 0; i < split.length; i++) {
|
|
||||||
final String s = split[i];
|
|
||||||
|
|
||||||
int i1 = s.indexOf("'");
|
|
||||||
int i2 = s.lastIndexOf("'");
|
|
||||||
|
|
||||||
if (i1 == 0 && i2 == s.length() - 1) {
|
|
||||||
split[i] = s.substring(1, s.length() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<String> strings = new ArrayList<String>(Arrays.asList(split));
|
|
||||||
for (Iterator<String> iterator = strings.iterator(); iterator.hasNext(); ) {
|
|
||||||
final String string = iterator.next();
|
|
||||||
if (string.trim()
|
|
||||||
.isEmpty()) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.debug("Installed extensions are: {}", strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static
|
|
||||||
void setEnabledExtensions(List<String> extensions) {
|
|
||||||
StringBuilder stringBuilder = new StringBuilder("[");
|
|
||||||
|
|
||||||
for (int i = 0, extensionsSize = extensions.size(), limit = extensionsSize-1; i < extensionsSize; i++) {
|
|
||||||
final String extension = extensions.get(i);
|
|
||||||
if (extension.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
stringBuilder.append("'")
|
|
||||||
.append(extension)
|
|
||||||
.append("'");
|
|
||||||
|
|
||||||
if (i < limit) {
|
|
||||||
stringBuilder.append(",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stringBuilder.append("]");
|
|
||||||
|
|
||||||
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.debug("Setting installed extensions to: {}", stringBuilder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// gsettings set org.gnome.shell enabled-extensions "['SystemTray@Dorkbox']"
|
|
||||||
// gsettings set org.gnome.shell enabled-extensions "['background-logo@fedorahosted.org']"
|
|
||||||
// gsettings set org.gnome.shell enabled-extensions "['background-logo@fedorahosted.org', 'SystemTray@Dorkbox']"
|
|
||||||
final ShellExecutor setGsettings = new ShellExecutor();
|
|
||||||
setGsettings.setExecutable("gsettings");
|
|
||||||
setGsettings.addArgument("set");
|
|
||||||
setGsettings.addArgument("org.gnome.shell");
|
|
||||||
setGsettings.addArgument("enabled-extensions");
|
|
||||||
setGsettings.addArgument(stringBuilder.toString());
|
|
||||||
setGsettings.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static
|
|
||||||
void restartShell() {
|
|
||||||
// in some situations, you can no longer restart the shell in wayland. You must logout-login for shell modifications to apply
|
|
||||||
// https://mail.gnome.org/archives/commits-list/2015-March/msg01019.html
|
|
||||||
|
|
||||||
// HOWEVER, with wayland, shell-extensions that DO NO MODIFY THE GUI (we don't, we just add icons to it)
|
|
||||||
// are enabled without a shell restart.
|
|
||||||
|
|
||||||
// if there are still difficulties, you can use the following
|
|
||||||
// gnome-shell-extension-tool -e SystemTray@Dorkbox
|
|
||||||
|
|
||||||
if (OSUtil.DesktopEnv.isWayland()) {
|
|
||||||
int[] version = OSUtil.Linux.getUbuntuVersion();
|
|
||||||
if (version[0] == 17) {
|
|
||||||
// ubuntu 17.04 is NOT WAYLAND (it's MIR) and ubuntu 17.10 is WAYLAND (and it's broken...)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.warn("Trying to restart the shell with an unknown version of wayland. Please create an issue with OS and debug information.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.warn("Trying to restart the shell with an unknown version of wayland. Please set `SystemTray.DEBUG=true;` then create an issue " +
|
|
||||||
"with OS and debug information.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (ENABLE_SHELL_RESTART) {
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.debug("DEBUG mode enabled. You need to log-out/in or manually restart the shell via '{}' to apply the changes.",
|
|
||||||
SHELL_RESTART_COMMAND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.debug("Restarting gnome-shell so tray notification changes can be applied.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we have to restart the gnome shell via bash in a background process
|
|
||||||
ShellAsyncExecutor.runShell(SHELL_RESTART_COMMAND);
|
|
||||||
|
|
||||||
// We don't care when the shell restarts, since WHEN IT DOES restart, our extension will show our icon.
|
|
||||||
// Until then however, there will be errors which can be ignored, because the shell-restart means everything works.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* topIcons will convert ALL icons to be at the top of the screen, so there is no reason to have both installed
|
|
||||||
*
|
|
||||||
* @return true if that extension is installed
|
|
||||||
*/
|
|
||||||
public static
|
|
||||||
boolean isInstalled() {
|
|
||||||
List<String> enabledExtensions = getEnabledExtensions();
|
|
||||||
return enabledExtensions.contains("topIcons@adel.gadllah@gmail.com") || enabledExtensions.contains(UID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only install a version that specifically moves only our icon next to the clock
|
|
||||||
*/
|
|
||||||
public static
|
|
||||||
void install() {
|
|
||||||
if (!ENABLE_EXTENSION_INSTALL) {
|
|
||||||
// note: Debian Gnome3 does NOT work! (tested on Debian 8.5 and 8.6 default installs).
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
SystemTray.logger.debug("Installing Gnome extension.");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean hasTopIcons;
|
|
||||||
boolean hasSystemTray;
|
|
||||||
|
|
||||||
// should just be 3.14.1 or 3.20 or similar
|
|
||||||
String gnomeVersion = OSUtil.DesktopEnv.getGnomeVersion();
|
|
||||||
if (gnomeVersion == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> enabledExtensions = getEnabledExtensions();
|
|
||||||
hasTopIcons = enabledExtensions.contains("topIcons@adel.gadllah@gmail.com");
|
|
||||||
hasSystemTray = enabledExtensions.contains(UID);
|
|
||||||
|
|
||||||
if (hasTopIcons) {
|
|
||||||
// topIcons will convert ALL icons to be at the top of the screen, so there is no reason to have both installed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// have to copy the extension over and enable it.
|
|
||||||
String userHome = System.getProperty("user.home");
|
|
||||||
|
|
||||||
// where the extension is saved
|
|
||||||
final File file = new File(userHome + "/.local/share/gnome-shell/extensions/" + UID);
|
|
||||||
final File metaDatafile = new File(file, "metadata.json");
|
|
||||||
final File extensionFile = new File(file, "extension.js");
|
|
||||||
|
|
||||||
|
|
||||||
// have to create the metadata.json file (and make it so that it's **always** current).
|
|
||||||
// we do this via getting the shell version
|
|
||||||
|
|
||||||
// We want "3.14" or "3.20" or whatever the latest version is (excluding the patch version info).
|
|
||||||
final int indexOf = gnomeVersion.indexOf('.');
|
|
||||||
final int nextIndexOf = gnomeVersion.indexOf('.', indexOf + 1);
|
|
||||||
if (indexOf < nextIndexOf) {
|
|
||||||
gnomeVersion = gnomeVersion.substring(0, nextIndexOf); // will be 3.14 (without the trailing '.1'), for example
|
|
||||||
}
|
|
||||||
|
|
||||||
String metadata = "{\n" +
|
|
||||||
" \"description\": \"Moves the java SystemTray icon from inside the notification drawer to alongside the " +
|
|
||||||
"clock.\",\n" +
|
|
||||||
" \"name\": \"Dorkbox SystemTray\",\n" +
|
|
||||||
" \"shell-version\": [\n" +
|
|
||||||
" \"" + gnomeVersion + "\"\n" +
|
|
||||||
" ],\n" +
|
|
||||||
" \"url\": \"https://github.com/dorkbox/SystemTray\",\n" +
|
|
||||||
" \"uuid\": \"" + UID + "\",\n" +
|
|
||||||
" \"version\": " + SystemTray.getVersion() + "\n" +
|
|
||||||
"}\n";
|
|
||||||
|
|
||||||
|
|
||||||
logger.debug("Checking the gnome-shell extension");
|
|
||||||
|
|
||||||
if (hasSystemTray) {
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.debug("Extension already installed, checking for upgrade");
|
|
||||||
}
|
|
||||||
// have to check to see if the version is correct as well (otherwise we have to reinstall it)
|
|
||||||
// compat for java 1.6
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder(256);
|
|
||||||
BufferedReader bin = null;
|
|
||||||
try {
|
|
||||||
bin = new BufferedReader(new FileReader(metaDatafile));
|
|
||||||
String line;
|
|
||||||
while ((line = bin.readLine()) != null) {
|
|
||||||
builder.append(line)
|
|
||||||
.append("\n");
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
} finally {
|
|
||||||
if (bin != null) {
|
|
||||||
try {
|
|
||||||
bin.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error closing: {}", bin, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// the metadata string we CHECK should equal the metadata string we PROVIDE
|
|
||||||
if (metadata.equals(builder.toString())) {
|
|
||||||
// this means that our version info, etc. is the same - there is no need to update anything
|
|
||||||
if (!SystemTray.DEBUG) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// if we are DEBUG, then we ALWAYS want to copy over our extension. We will have to manually restart the shell to see it
|
|
||||||
logger.debug("Always upgrading extension in DEBUG mode");
|
|
||||||
hasSystemTray = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// this means that we need to reinstall our extension, since either GNOME or US have changed versions since
|
|
||||||
// we last installed the extension.
|
|
||||||
logger.debug("Need to upgrade extension");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// we get here if we are NOT installed, or if we are installed and our metadata is NOT THE SAME. (so we need to reinstall)
|
|
||||||
logger.debug("Installing gnome-shell extension");
|
|
||||||
|
|
||||||
|
|
||||||
// need to make the extension location
|
|
||||||
if (!file.isDirectory()) {
|
|
||||||
final boolean mkdirs = file.mkdirs();
|
|
||||||
if (!mkdirs) {
|
|
||||||
final String msg = "Unable to create extension location: " + file;
|
|
||||||
logger.error(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// write out the metadata
|
|
||||||
BufferedWriter outputWriter = null;
|
|
||||||
try {
|
|
||||||
outputWriter = new BufferedWriter(new FileWriter(metaDatafile, false));
|
|
||||||
// FileWriter always assumes default encoding is OK
|
|
||||||
outputWriter.write(metadata);
|
|
||||||
outputWriter.flush();
|
|
||||||
outputWriter.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error installing extension metadata file", e);
|
|
||||||
} finally {
|
|
||||||
if (outputWriter != null) {
|
|
||||||
try {
|
|
||||||
outputWriter.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error closing: {}", outputWriter, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!hasSystemTray) {
|
|
||||||
// copies our provided extension.js file to the correct location on disk
|
|
||||||
InputStream reader = null;
|
|
||||||
FileOutputStream fileOutputStream = null;
|
|
||||||
try {
|
|
||||||
reader = Extension.class.getResourceAsStream("extension.js");
|
|
||||||
fileOutputStream = new FileOutputStream(extensionFile);
|
|
||||||
|
|
||||||
if (reader == null) {
|
|
||||||
logger.error("The GnomeShell extension.js file cannot be found. Something is severely wrong.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IO.copyStream(reader, fileOutputStream);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
logger.error("Cannot find gnome-shell extension", e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Unable to get gnome-shell extension", e);
|
|
||||||
} finally {
|
|
||||||
if (reader != null) {
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error closing: {}", reader, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fileOutputStream != null) {
|
|
||||||
try {
|
|
||||||
fileOutputStream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Error closing: {}", fileOutputStream, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("Enabling extension in gnome-shell");
|
|
||||||
|
|
||||||
|
|
||||||
if (!enabledExtensions.contains(UID)) {
|
|
||||||
enabledExtensions.add(UID);
|
|
||||||
}
|
|
||||||
setEnabledExtensions(enabledExtensions);
|
|
||||||
|
|
||||||
restartShell();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static
|
|
||||||
void unInstall() {
|
|
||||||
if (!ENABLE_EXTENSION_INSTALL || !OSUtil.DesktopEnv.isGnome()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> enabledExtensions = getEnabledExtensions();
|
|
||||||
if (enabledExtensions.contains(UID)) {
|
|
||||||
enabledExtensions.remove(UID);
|
|
||||||
|
|
||||||
setEnabledExtensions(enabledExtensions);
|
|
||||||
|
|
||||||
restartShell();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
432
src/dorkbox/systemTray/gnomeShell/ExtensionSupport.java
Normal file
432
src/dorkbox/systemTray/gnomeShell/ExtensionSupport.java
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.systemTray.gnomeShell;
|
||||||
|
|
||||||
|
import static dorkbox.systemTray.SystemTray.logger;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import dorkbox.executor.ShellAsyncExecutor;
|
||||||
|
import dorkbox.executor.ShellExecutor;
|
||||||
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
import dorkbox.util.IO;
|
||||||
|
import dorkbox.util.OSUtil;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DanglingJavadoc", "WeakerAccess"})
|
||||||
|
public
|
||||||
|
class ExtensionSupport {
|
||||||
|
public static
|
||||||
|
List<String> getEnabledExtensions() {
|
||||||
|
// gsettings get org.gnome.shell enabled-extensions
|
||||||
|
final ShellExecutor gsettings = new ShellExecutor();
|
||||||
|
gsettings.setExecutable("gsettings");
|
||||||
|
gsettings.addArgument("get");
|
||||||
|
gsettings.addArgument("org.gnome.shell");
|
||||||
|
gsettings.addArgument("enabled-extensions");
|
||||||
|
gsettings.start();
|
||||||
|
|
||||||
|
String output = gsettings.getOutput();
|
||||||
|
|
||||||
|
// now we have to enable us if we aren't already enabled
|
||||||
|
|
||||||
|
// gsettings get org.gnome.shell enabled-extensions
|
||||||
|
// defaults are:
|
||||||
|
// - fedora 23: ['background-logo@fedorahosted.org'] on
|
||||||
|
// - openSuse:
|
||||||
|
// - Ubuntu Gnome 16.04: @as []
|
||||||
|
|
||||||
|
final StringBuilder stringBuilder = new StringBuilder(output);
|
||||||
|
|
||||||
|
// have to remove the end first, otherwise we would have to re-index the location of the ]
|
||||||
|
|
||||||
|
// remove the last ]
|
||||||
|
int extensionIndex = output.indexOf("]");
|
||||||
|
if (extensionIndex > 0) {
|
||||||
|
stringBuilder.delete(extensionIndex, stringBuilder.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// strip off UP-TO plus the leading [
|
||||||
|
extensionIndex = output.indexOf("[");
|
||||||
|
if (extensionIndex >= 0) {
|
||||||
|
stringBuilder.delete(0, extensionIndex+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be 'background-logo@fedorahosted.org', 'zyx', 'abs'
|
||||||
|
// or nothing
|
||||||
|
|
||||||
|
String installedExtensions = stringBuilder.toString();
|
||||||
|
|
||||||
|
// now just split the extensions into a list so it is easier to manage
|
||||||
|
|
||||||
|
String[] split = installedExtensions
|
||||||
|
.split(", ");
|
||||||
|
for (int i = 0; i < split.length; i++) {
|
||||||
|
final String s = split[i];
|
||||||
|
|
||||||
|
int i1 = s.indexOf("'");
|
||||||
|
int i2 = s.lastIndexOf("'");
|
||||||
|
|
||||||
|
if (i1 == 0 && i2 == s.length() - 1) {
|
||||||
|
split[i] = s.substring(1, s.length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> strings = new ArrayList<String>(Arrays.asList(split));
|
||||||
|
for (Iterator<String> iterator = strings.iterator(); iterator.hasNext(); ) {
|
||||||
|
final String string = iterator.next();
|
||||||
|
if (string.trim()
|
||||||
|
.isEmpty()) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Installed extensions are: {}", strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void setEnabledExtensions(List<String> extensions) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("[");
|
||||||
|
|
||||||
|
for (int i = 0, extensionsSize = extensions.size(), limit = extensionsSize-1; i < extensionsSize; i++) {
|
||||||
|
final String extension = extensions.get(i);
|
||||||
|
if (extension.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stringBuilder.append("'")
|
||||||
|
.append(extension)
|
||||||
|
.append("'");
|
||||||
|
|
||||||
|
if (i < limit) {
|
||||||
|
stringBuilder.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stringBuilder.append("]");
|
||||||
|
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Setting installed extensions to: {}", stringBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// gsettings set org.gnome.shell enabled-extensions "['SystemTray@Dorkbox']"
|
||||||
|
// gsettings set org.gnome.shell enabled-extensions "['background-logo@fedorahosted.org']"
|
||||||
|
// gsettings set org.gnome.shell enabled-extensions "['background-logo@fedorahosted.org', 'SystemTray@Dorkbox']"
|
||||||
|
final ShellExecutor setGsettings = new ShellExecutor();
|
||||||
|
setGsettings.setExecutable("gsettings");
|
||||||
|
setGsettings.addArgument("set");
|
||||||
|
setGsettings.addArgument("org.gnome.shell");
|
||||||
|
setGsettings.addArgument("enabled-extensions");
|
||||||
|
setGsettings.addArgument(stringBuilder.toString());
|
||||||
|
setGsettings.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void unInstall(String UID, String restartCommand) {
|
||||||
|
List<String> enabledExtensions = getEnabledExtensions();
|
||||||
|
if (enabledExtensions.contains(UID)) {
|
||||||
|
enabledExtensions.remove(UID);
|
||||||
|
|
||||||
|
setEnabledExtensions(enabledExtensions);
|
||||||
|
|
||||||
|
restartShell(restartCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void restartShell(String restartCommand) {
|
||||||
|
// in some situations, you can no longer restart the shell in wayland. You must logout-login for shell modifications to apply
|
||||||
|
// https://mail.gnome.org/archives/commits-list/2015-March/msg01019.html
|
||||||
|
|
||||||
|
// HOWEVER, with wayland, shell-extensions that DO NO MODIFY THE GUI (we don't, we just add icons to it)
|
||||||
|
// are enabled without a shell restart.
|
||||||
|
|
||||||
|
// if there are still difficulties, you can use the following
|
||||||
|
// gnome-shell-extension-tool -e SystemTray@Dorkbox
|
||||||
|
|
||||||
|
logger.info("Restarting gnome-shell via '{}' so tray notification changes can be applied.", restartCommand);
|
||||||
|
|
||||||
|
// now we have to restart the gnome shell via bash in a background process
|
||||||
|
ShellAsyncExecutor.runShell(restartCommand);
|
||||||
|
|
||||||
|
// We don't care when the shell restarts, since WHEN IT DOES restart, our extension will show our icon.
|
||||||
|
// Until then however, there will be errors which can be ignored, because the shell-restart means everything works.
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static
|
||||||
|
String readFile(final File metaDatafile) {
|
||||||
|
StringBuilder builder = new StringBuilder(256);
|
||||||
|
BufferedReader bin = null;
|
||||||
|
try {
|
||||||
|
bin = new BufferedReader(new FileReader(metaDatafile));
|
||||||
|
String line;
|
||||||
|
while ((line = bin.readLine()) != null) {
|
||||||
|
builder.append(line)
|
||||||
|
.append("\n");
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
} finally {
|
||||||
|
if (bin != null) {
|
||||||
|
try {
|
||||||
|
bin.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", bin, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if successful, false if there was a failure
|
||||||
|
*/
|
||||||
|
protected static
|
||||||
|
boolean writeFile(final String metadata, final File metaDatafile) {
|
||||||
|
File file = metaDatafile.getParentFile();
|
||||||
|
|
||||||
|
// need to make the extension location
|
||||||
|
if (!file.isDirectory()) {
|
||||||
|
final boolean mkdirs = file.mkdirs();
|
||||||
|
if (!mkdirs) {
|
||||||
|
final String msg = "Unable to create extension location: " + file;
|
||||||
|
logger.error(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write out the metadata
|
||||||
|
BufferedWriter outputWriter = null;
|
||||||
|
try {
|
||||||
|
outputWriter = new BufferedWriter(new FileWriter(metaDatafile, false));
|
||||||
|
// FileWriter always assumes default encoding is OK
|
||||||
|
outputWriter.write(metadata);
|
||||||
|
outputWriter.flush();
|
||||||
|
outputWriter.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error installing extension metadata file", e);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
if (outputWriter != null) {
|
||||||
|
try {
|
||||||
|
outputWriter.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", outputWriter, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if successful, false if there was a failure
|
||||||
|
*/
|
||||||
|
protected static
|
||||||
|
boolean installFile(final String resourceName, final File targetDirectory) {
|
||||||
|
final File outputFile = new File(targetDirectory, resourceName);
|
||||||
|
|
||||||
|
InputStream reader = null;
|
||||||
|
FileOutputStream fileOutputStream = null;
|
||||||
|
try {
|
||||||
|
reader = ExtensionSupport.class.getResourceAsStream(resourceName);
|
||||||
|
fileOutputStream = new FileOutputStream(outputFile);
|
||||||
|
|
||||||
|
if (reader == null) {
|
||||||
|
logger.error("The {} file cannot be found. Something is severely wrong.", resourceName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IO.copyStream(reader, fileOutputStream);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
logger.error("Cannot find gnome-shell extension", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Unable to get gnome-shell extension", e);
|
||||||
|
} finally {
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", reader, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileOutputStream != null) {
|
||||||
|
try {
|
||||||
|
fileOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", fileOutputStream, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if successful, false if there was a failure
|
||||||
|
*/
|
||||||
|
protected static
|
||||||
|
boolean installZip(final String zipResourceName, final File targetDirectory) {
|
||||||
|
ZipInputStream inputStream = null;
|
||||||
|
FileOutputStream fileOutputStream = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
inputStream = new ZipInputStream(ExtensionSupport.class.getResourceAsStream(zipResourceName));
|
||||||
|
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = inputStream.getNextEntry()) != null) {
|
||||||
|
if (!entry.isDirectory()) {
|
||||||
|
String name = entry.getName();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!entry.isDirectory()) {
|
||||||
|
File specificOutput = new File(targetDirectory, name);
|
||||||
|
File parentFile = specificOutput.getParentFile();
|
||||||
|
|
||||||
|
if (!parentFile.exists()) {
|
||||||
|
boolean mkdirs = parentFile.mkdirs();
|
||||||
|
if (!mkdirs) {
|
||||||
|
SystemTray.logger.error("Error creating target directory '{}' for Zip support.", parentFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileOutputStream = new FileOutputStream(specificOutput);
|
||||||
|
|
||||||
|
IO.copyStream(inputStream, fileOutputStream);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
SystemTray.logger.error("Error extracting zip contents to {}", targetDirectory);
|
||||||
|
} finally {
|
||||||
|
if (fileOutputStream != null) {
|
||||||
|
IO.closeQuietly(fileOutputStream);
|
||||||
|
fileOutputStream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
logger.error("Cannot find gnome-shell extension", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Unable to get gnome-shell extension", e);
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", inputStream, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileOutputStream != null) {
|
||||||
|
try {
|
||||||
|
fileOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Error closing: {}", fileOutputStream, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected static
|
||||||
|
String createMetadata(final String uid, final String appVersion, final String gnomeVersion) {
|
||||||
|
return "{\n" +
|
||||||
|
" \"description\": \"Moves the java SystemTray icon from inside the notification drawer to alongside the clock.\",\n" +
|
||||||
|
" \"name\": \"Dorkbox SystemTray\",\n" +
|
||||||
|
" \"shell-version\": [\n" +
|
||||||
|
" \"" + gnomeVersion + "\"\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"url\": \"https://git.dorkbox.com/dorkbox/SystemTray\",\n" +
|
||||||
|
" \"uuid\": \"" + uid + "\",\n" +
|
||||||
|
" \"version\": " + appVersion + "\n" +
|
||||||
|
"}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static
|
||||||
|
String getGnomeVersion() {
|
||||||
|
String gnomeVersion = OSUtil.DesktopEnv.getGnomeVersion();
|
||||||
|
if (gnomeVersion == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want "3.14" or "3.20" or whatever the latest version is (excluding the patch version info).
|
||||||
|
final int indexOf = gnomeVersion.indexOf('.');
|
||||||
|
final int nextIndexOf = gnomeVersion.indexOf('.', indexOf + 1);
|
||||||
|
if (indexOf < nextIndexOf) {
|
||||||
|
return gnomeVersion.substring(0, nextIndexOf); // will be 3.14 (without the trailing '.1'), for example
|
||||||
|
}
|
||||||
|
|
||||||
|
return gnomeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if we need to upgrade/re-install the extension, false if we do not need to do anything
|
||||||
|
*/
|
||||||
|
protected static
|
||||||
|
boolean needsUpgrade(final String metadata, final File metaDatafile) {
|
||||||
|
String existingMetadata = ExtensionSupport.readFile(metaDatafile);
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Extension already installed, checking for upgrade");
|
||||||
|
}
|
||||||
|
|
||||||
|
// have to check to see if the version is correct as well (otherwise we have to reinstall it)
|
||||||
|
// compat for java 1.6
|
||||||
|
|
||||||
|
// the metadata string we CHECK should equal the metadata string we PROVIDE
|
||||||
|
if (metadata.equals(existingMetadata)) {
|
||||||
|
// this means that our version info, etc. is the same - there is no need to update anything
|
||||||
|
if (!SystemTray.DEBUG) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// if we are DEBUG, then we ALWAYS want to copy over our extension. We will have to manually restart the shell to see it
|
||||||
|
logger.debug("Always upgrading extension in DEBUG mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this means that we need to reinstall our extension, since either GNOME or US have changed versions since
|
||||||
|
// we last installed the extension.
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Need to upgrade extension");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
165
src/dorkbox/systemTray/gnomeShell/LegacyExtension.java
Normal file
165
src/dorkbox/systemTray/gnomeShell/LegacyExtension.java
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.systemTray.gnomeShell;
|
||||||
|
|
||||||
|
import static dorkbox.systemTray.SystemTray.logger;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
import dorkbox.util.OSUtil;
|
||||||
|
|
||||||
|
@SuppressWarnings({"DanglingJavadoc", "WeakerAccess"})
|
||||||
|
public
|
||||||
|
class LegacyExtension extends ExtensionSupport {
|
||||||
|
private static final String UID = "SystemTray@Dorkbox";
|
||||||
|
public static final String DEFAULT_NAME = "SystemTray";
|
||||||
|
|
||||||
|
/** Command to restart the gnome-shell. It is recommended to start it in the background (hence '&') */
|
||||||
|
private static final String SHELL_RESTART_COMMAND = "gnome-shell --replace &";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* topIcons will convert ALL icons to be at the top of the screen, so there is no reason to have both installed
|
||||||
|
*
|
||||||
|
* @return true if that extension is installed
|
||||||
|
*/
|
||||||
|
public static
|
||||||
|
boolean isInstalled() {
|
||||||
|
List<String> enabledExtensions = getEnabledExtensions();
|
||||||
|
return enabledExtensions.contains("topIcons@adel.gadllah@gmail.com") || enabledExtensions.contains(UID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only install a version that specifically moves only our icon next to the clock
|
||||||
|
*/
|
||||||
|
public static
|
||||||
|
void install() {
|
||||||
|
if (OSUtil.DesktopEnv.isWayland()) {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
SystemTray.logger.debug("Gnome-shell legacy extension not possible with wayland.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
SystemTray.logger.debug("Installing the legacy gnome-shell extension.");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasTopIcons;
|
||||||
|
boolean hasSystemTray;
|
||||||
|
|
||||||
|
// should just be 3.14.1 or 3.20 or similar
|
||||||
|
String gnomeVersion = ExtensionSupport.getGnomeVersion();
|
||||||
|
if (gnomeVersion == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> enabledExtensions = getEnabledExtensions();
|
||||||
|
hasTopIcons = enabledExtensions.contains("topIcons@adel.gadllah@gmail.com");
|
||||||
|
hasSystemTray = enabledExtensions.contains(UID);
|
||||||
|
|
||||||
|
if (hasTopIcons) {
|
||||||
|
// topIcons will convert ALL icons to be at the top of the screen, so there is no reason to have both installed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// have to copy the extension over and enable it.
|
||||||
|
String userHome = System.getProperty("user.home");
|
||||||
|
|
||||||
|
// where the extension is saved
|
||||||
|
final File directory = new File(userHome + "/.local/share/gnome-shell/extensions/" + UID);
|
||||||
|
final File metaDatafile = new File(directory, "metadata.json");
|
||||||
|
|
||||||
|
|
||||||
|
// have to create the metadata.json file (and make it so that it's **always** current).
|
||||||
|
// we do this via getting the shell version
|
||||||
|
|
||||||
|
String metadata = ExtensionSupport.createMetadata(UID, SystemTray.getVersion(), gnomeVersion);
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Checking the legacy gnome-shell extension");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSystemTray && !ExtensionSupport.needsUpgrade(metadata, metaDatafile)) {
|
||||||
|
// this means that our version info, etc. is the same - there is no need to update anything
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we get here if we are NOT installed, or if we are installed and our metadata is NOT THE SAME. (so we need to reinstall)
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Installing legacy gnome-shell extension");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean success = ExtensionSupport.writeFile(metadata, metaDatafile);
|
||||||
|
|
||||||
|
if (success && !hasSystemTray) {
|
||||||
|
// copies our provided extension files to the correct location on disk
|
||||||
|
ExtensionSupport.installFile("extension.js", directory);
|
||||||
|
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("Enabling legacy gnome-shell extension");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enabledExtensions.contains(UID)) {
|
||||||
|
enabledExtensions.add(UID);
|
||||||
|
}
|
||||||
|
setEnabledExtensions(enabledExtensions);
|
||||||
|
|
||||||
|
restartShell(SHELL_RESTART_COMMAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void unInstall() {
|
||||||
|
if (OSUtil.DesktopEnv.isWayland()) {
|
||||||
|
if (OSUtil.Linux.isUbuntu() && OSUtil.Linux.getUbuntuVersion()[0] == 17) {
|
||||||
|
// ubuntu 17.04 is NOT WAYLAND (it's MIR) and ubuntu 17.10 is WAYLAND (and doesn't support this)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (OSUtil.Linux.isFedora()) {
|
||||||
|
// fedora doesn't support this
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.warn("Trying to restart the shell with an unknown version of wayland. Please create an issue with OS and debug information.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.warn("Trying to restart the shell with an unknown version of wayland. Please set `SystemTray.DEBUG=true;` then create an issue " +
|
||||||
|
"with OS and debug information.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unInstall(UID, SHELL_RESTART_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void restartShell() {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
logger.debug("DEBUG mode enabled. You need to log-out/in or manually restart the shell via '{}' to apply the changes.", SHELL_RESTART_COMMAND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
restartShell(SHELL_RESTART_COMMAND);
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ import com.sun.jna.Pointer;
|
|||||||
import dorkbox.systemTray.MenuItem;
|
import dorkbox.systemTray.MenuItem;
|
||||||
import dorkbox.systemTray.SystemTray;
|
import dorkbox.systemTray.SystemTray;
|
||||||
import dorkbox.systemTray.Tray;
|
import dorkbox.systemTray.Tray;
|
||||||
import dorkbox.systemTray.gnomeShell.Extension;
|
import dorkbox.systemTray.gnomeShell.LegacyExtension;
|
||||||
import dorkbox.systemTray.util.ImageResizeUtil;
|
import dorkbox.systemTray.util.ImageResizeUtil;
|
||||||
import dorkbox.util.jna.linux.AppIndicator;
|
import dorkbox.util.jna.linux.AppIndicator;
|
||||||
import dorkbox.util.jna.linux.GObject;
|
import dorkbox.util.jna.linux.GObject;
|
||||||
@ -126,7 +126,7 @@ class _AppIndicatorNativeTray extends Tray {
|
|||||||
// in extension.js, so don't change it
|
// in extension.js, so don't change it
|
||||||
|
|
||||||
// additionally, this is required to be set HERE (not somewhere else)
|
// additionally, this is required to be set HERE (not somewhere else)
|
||||||
appIndicator.app_indicator_set_title(Extension.DEFAULT_NAME);
|
appIndicator.app_indicator_set_title(LegacyExtension.DEFAULT_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import com.sun.jna.Pointer;
|
|||||||
import dorkbox.systemTray.MenuItem;
|
import dorkbox.systemTray.MenuItem;
|
||||||
import dorkbox.systemTray.SystemTray;
|
import dorkbox.systemTray.SystemTray;
|
||||||
import dorkbox.systemTray.Tray;
|
import dorkbox.systemTray.Tray;
|
||||||
import dorkbox.systemTray.gnomeShell.Extension;
|
import dorkbox.systemTray.gnomeShell.LegacyExtension;
|
||||||
import dorkbox.util.JavaFX;
|
import dorkbox.util.JavaFX;
|
||||||
import dorkbox.util.jna.linux.GEventCallback;
|
import dorkbox.util.jna.linux.GEventCallback;
|
||||||
import dorkbox.util.jna.linux.GObject;
|
import dorkbox.util.jna.linux.GObject;
|
||||||
@ -205,7 +205,7 @@ class _GtkStatusIconNativeTray extends Tray {
|
|||||||
|
|
||||||
// necessary for gnome icon detection/placement because we move tray icons around by title. This is hardcoded
|
// necessary for gnome icon detection/placement because we move tray icons around by title. This is hardcoded
|
||||||
// in extension.js, so don't change it
|
// in extension.js, so don't change it
|
||||||
Gtk2.gtk_status_icon_set_title(trayIcon, Extension.DEFAULT_NAME);
|
Gtk2.gtk_status_icon_set_title(trayIcon, LegacyExtension.DEFAULT_NAME);
|
||||||
|
|
||||||
// can cause
|
// can cause
|
||||||
// Gdk-CRITICAL **: gdk_window_thaw_toplevel_updates: assertion 'window->update_and_descendants_freeze_count > 0' failed
|
// Gdk-CRITICAL **: gdk_window_thaw_toplevel_updates: assertion 'window->update_and_descendants_freeze_count > 0' failed
|
||||||
|
Loading…
Reference in New Issue
Block a user