diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..64ffe4b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,76 @@
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+target/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+# Ignore self-extracted stuff
+config.yml
+restart.sh
diff --git a/.idea/artifacts/ScreenScalingFixer_jar.xml b/.idea/artifacts/ScreenScalingFixer_jar.xml
new file mode 100644
index 0000000..601f5a1
--- /dev/null
+++ b/.idea/artifacts/ScreenScalingFixer_jar.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/out/artifacts/ScreenScalingFixer_jar
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..77809bf
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/description.html b/.idea/description.html
new file mode 100644
index 0000000..db5f129
--- /dev/null
+++ b/.idea/description.html
@@ -0,0 +1 @@
+Simple Java application that includes a class with main()
method
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..78bf31c
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d2b574f
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..4e87bac
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/project-template.xml b/.idea/project-template.xml
new file mode 100644
index 0000000..1f08b88
--- /dev/null
+++ b/.idea/project-template.xml
@@ -0,0 +1,3 @@
+
+ IJ_BASE_PACKAGE
+
\ No newline at end of file
diff --git a/ScreenScalingFixer.iml b/ScreenScalingFixer.iml
new file mode 100644
index 0000000..e75f198
--- /dev/null
+++ b/ScreenScalingFixer.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/buildNumber.properties b/buildNumber.properties
new file mode 100644
index 0000000..14f379e
--- /dev/null
+++ b/buildNumber.properties
@@ -0,0 +1,3 @@
+#maven.buildNumber.plugin properties file
+#Sun Oct 18 16:52:03 CEST 2020
+buildNumber=43
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..345c7ad
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,100 @@
+
+
+ 4.0.0
+
+ groupId
+ ScreenScalingFixer
+ 1.0-SNAPSHOT
+
+ scm:svn:http://127.0.0.1/dummy
+ scm:svn:https://127.0.0.1/dummy
+ HEAD
+ http://127.0.0.1/dummy
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ src/main/resources/META-INF/MANIFEST.MF
+
+
+
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ 1.1
+
+
+ buildnumber
+ validate
+
+ create
+
+
+
+
+ {0,number}
+
+ - buildNumber
+
+ false
+ false
+ unknownbuild
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+
+ net.mindoverflow.tools.ssf.Main
+
+
+ false
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+ src/main/resources
+ true
+
+ *.yml
+ *.sh
+
+
+
+
+
+
+ 1.8
+ 1.8
+ UTF-8
+ ${project.version}
+
+
+
+ org.yaml
+ snakeyaml
+ 1.21
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/net/mindoverflow/tools/ssf/Main.java b/src/main/java/net/mindoverflow/tools/ssf/Main.java
new file mode 100644
index 0000000..ca5f823
--- /dev/null
+++ b/src/main/java/net/mindoverflow/tools/ssf/Main.java
@@ -0,0 +1,183 @@
+package net.mindoverflow.tools.ssf;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.yaml.snakeyaml.Yaml;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.*;
+import java.nio.file.Files;
+import java.util.Map;
+
+public class Main {
+
+ private static int restartDelay;
+ private static String monitorConnector;
+ private static double monitorScale;
+ private static boolean enable;
+
+ public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, TransformerException, InterruptedException {
+ File monitorConfig = new File(System.getProperty("user.home") + "/.config/monitors.xml");
+
+ if(!monitorConfig.exists())
+ {
+ System.out.println("File \"monitors.xml\" does not exist! Quitting...");
+ System.exit(1);
+ }
+
+ if(!loadConfig())
+ {
+ System.out.println("Error loading \"config.yml\"! Quitting...");
+ System.exit(1);
+ }
+
+ if(!enable)
+ {
+ System.out.println("Script disabled! Enable it by setting \"enabled: true\" in config.yml!");
+ System.exit(0);
+ }
+
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document doc = documentBuilder.parse(monitorConfig);
+
+ Element rootElement = doc.getDocumentElement();
+ System.out.println("Main element: " + rootElement.getNodeName());
+
+ NodeList rootNodes = rootElement.getElementsByTagName("configuration");
+ Node configuration = rootNodes.item(0);
+ System.out.println("1 - Current node: " + configuration.getNodeName());
+ NodeList logicalMonitors = configuration.getChildNodes();
+ for(int pos = 0; pos < logicalMonitors.getLength(); pos++)
+ {
+ Node logicalMonitor = logicalMonitors.item(pos);
+ if(!logicalMonitor.getNodeName().equalsIgnoreCase("logicalmonitor")) continue;
+ System.out.println(" 2 - Current node: " + logicalMonitor.getNodeName());
+ Node scale = getNodeByName("scale", logicalMonitor.getChildNodes());
+ System.out.println(" 3A - current node: " + scale.getNodeName());
+ System.out.println(" Current scale: " + scale.getTextContent());
+ Node monitor = getNodeByName("monitor", logicalMonitor.getChildNodes());
+ System.out.println(" 3B - current node: " + monitor.getNodeName());
+ Node monitorspec = getNodeByName("monitorspec", monitor.getChildNodes());
+ System.out.println(" 4 - current node: " + monitorspec.getNodeName());
+ Node connector = getNodeByName("connector", monitorspec.getChildNodes());
+ System.out.println(" 5 - current node: " + connector.getNodeName());
+ System.out.println(" Current connector: " + connector.getTextContent());
+
+ String connectorValue = connector.getTextContent();
+
+ if(connectorValue.equalsIgnoreCase(monitorConnector))
+ {
+ scale.setTextContent("1");
+ saveFile(doc, monitorConfig);
+ restartGnome();
+
+ Thread.sleep(restartDelay);
+ scale.setTextContent(monitorScale + "");
+ saveFile(doc, monitorConfig);
+ restartGnome();
+
+ return;
+ }
+
+ }
+ }
+
+ private static Node getNodeByName(String name, NodeList list)
+ {
+ for(int pos = 0; pos < list.getLength(); pos++)
+ {
+ Node current = list.item(pos);
+ if(current.getNodeName().equalsIgnoreCase(name)) return current;
+ }
+
+ return null;
+ }
+
+ private static void restartGnome() throws IOException, InterruptedException {
+ String s;
+
+ InputStream stream = Main.class.getResourceAsStream("/restart.sh");
+ File script = new File("restart.sh");
+ if(!script.exists())
+ {
+ System.out.println("Extracting restart script...");
+ Files.copy(stream, script.getAbsoluteFile().toPath());
+ System.out.println("Done!");
+ }
+
+ System.out.println("Restarting GNOME...");
+ script.setExecutable(true);
+ Process process = Runtime.getRuntime().exec(script.getAbsolutePath());
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
+
+ while((s = br.readLine()) != null)
+ {
+ System.out.println("line: " + s);
+ }
+
+ process.waitFor();
+ System.out.println ("exit: " + process.exitValue());
+ process.destroy();
+ }
+
+ private static void saveFile(Document doc, File file) throws TransformerException {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ transformer.transform(new DOMSource(doc), new StreamResult(file));
+ }
+
+ private static boolean loadConfig()
+ {
+ InputStream stream = Main.class.getResourceAsStream("/config.yml");
+ File config = new File("config.yml");
+ if(!config.exists())
+ {
+ System.out.println("Extracting config...");
+ try
+ {
+ Files.copy(stream, config.getAbsoluteFile().toPath());
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ System.out.println("Done!");
+ }
+
+ System.out.println("Loading config...");
+ Yaml configYaml = new Yaml();
+ Map contents;
+ try
+ {
+ contents = configYaml.load(new FileInputStream(config));
+ } catch (FileNotFoundException e)
+ {
+ e.printStackTrace();
+ return false;
+ }
+ enable = (boolean) contents.get("enable");
+ restartDelay = (int) contents.get("delay");
+ monitorScale = (double) contents.get("scale");
+ monitorConnector = (String) contents.get("monitor-connector");
+ System.out.println("Done!");
+ System.out.println("Enabled: " + enable);
+ System.out.println("Delay: " + restartDelay);
+ System.out.println("Monitor name: " + monitorConnector);
+ System.out.println("Monitor scale: " + monitorScale);
+ return true;
+ }
+}
diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..375f545
--- /dev/null
+++ b/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: net.mindoverflow.tools.ssf.Main
+