Skip to content

Commit f684883

Browse files
committed
kdotool is very cool
1 parent 32987a6 commit f684883

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

CHANGES.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
changes:
2-
- fix auto gui scaling looking broken with weird window sizes
3-
- make the .desktop file not show up in the applications menu (specifically on GNOME)
4-
- [Pull Request by Eggmanplant](https://github.com/not-coded/WayFix/pull/18)
2+
- if you're on kde plasma, minecraft will fullscreen correctly without using the fullscreen config options (basically like x11)
3+
- only if **[kdotool](https://github.com/jinliu/kdotool)** is installed!!!!!

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Fixes multiple issues regarding Wayland compatibility for Minecraft.
1414
**Recommended to be used with [glfw-wayland](https://github.com/BoyOrigin/glfw-wayland).**
1515
<br>
1616
**With the [Cursor Fix](https://www.reddit.com/r/kde/comments/13ddktm/mouse_cursor_changing_when_over_some_apps_when/).**
17+
<br>
18+
**And [kdotool](https://github.com/jinliu/kdotool)** ***(only if on KDE Plasma)***.
1719

1820
</div>
1921

@@ -33,6 +35,7 @@ Fixes multiple issues regarding Wayland compatibility for Minecraft.
3335

3436
> [!NOTE]
3537
> By default Minecraft sometimes full-screens on the wrong monitor due to Wayland window limitations (unable to get X and Y position).
38+
> This is automatically **fixed only on KDE Plasma** without specifying the monitor by installing **[kdotool](https://github.com/jinliu/kdotool)**.
3639
3740
## Building
3841
- Clone the repository

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
33
org.gradle.parallel=true
44

55
# Mod Information
6-
mod.version=1.0.3
6+
mod.version=1.0.4
77
mod.name=wayfix
88
mod.maven_group=net.notcoded
99

src/main/java/net/notcoded/wayfix/WayFix.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import me.shedaniel.autoconfig.serializer.GsonConfigSerializer;
55
import net.fabricmc.api.ClientModInitializer;
66
import net.notcoded.wayfix.config.ModConfig;
7+
import net.notcoded.wayfix.util.WindowHelper;
78
import org.apache.logging.log4j.LogManager;
89
import org.apache.logging.log4j.Logger;
910
import org.lwjgl.glfw.GLFW;
@@ -16,6 +17,14 @@ public class WayFix implements ClientModInitializer {
1617
public void onInitializeClient() {
1718
AutoConfig.register(ModConfig.class, GsonConfigSerializer::new);
1819
WayFix.config = AutoConfig.getConfigHolder(ModConfig.class).getConfig();
20+
21+
WindowHelper.checkIfCanUseWindowHelper();
22+
if(WindowHelper.canUseWindowHelper) {
23+
WayFix.config.fullscreen.monitorName = "";
24+
WayFix.config.fullscreen.useMonitorName = false;
25+
WayFix.config.fullscreen.monitorSelector.monitors.clear();
26+
WayFix.config.fullscreen.monitorSelector.monitors.add(new ModConfig.Monitors("You do not need to use this as it is automatically fixed.", 0)); // most users probably won't understand this, but I'll include it anyway
27+
}
1928
}
2029

2130
public static boolean isWayland() {

src/main/java/net/notcoded/wayfix/mixin/MonitorTrackerMixin.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import net.minecraft.client.util.MonitorTracker;
66
import net.notcoded.wayfix.WayFix;
77
import net.notcoded.wayfix.config.ModConfig;
8+
import net.notcoded.wayfix.util.WindowHelper;
89
import org.spongepowered.asm.mixin.Final;
910
import org.spongepowered.asm.mixin.Mixin;
1011
import org.spongepowered.asm.mixin.Shadow;
@@ -21,7 +22,7 @@ public class MonitorTrackerMixin {
2122

2223
@Inject(method = {"handleMonitorEvent", "<init>"}, at = @At("TAIL"))
2324
private void handleConfigAdditions(CallbackInfo ci) {
24-
this.refreshMonitors();
25+
if(!WindowHelper.canUseWindowHelper) this.refreshMonitors();
2526
}
2627

2728
@Unique

src/main/java/net/notcoded/wayfix/mixin/WindowMixin.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
import net.notcoded.wayfix.WayFix;
99
import net.notcoded.wayfix.config.ModConfig;
1010
import net.notcoded.wayfix.util.DesktopFileInjector;
11+
import net.notcoded.wayfix.util.WindowHelper;
1112
import org.lwjgl.glfw.GLFW;
13+
import org.spongepowered.asm.mixin.Final;
1214
import org.spongepowered.asm.mixin.Mixin;
15+
import org.spongepowered.asm.mixin.Shadow;
1316
import org.spongepowered.asm.mixin.Unique;
1417
import org.spongepowered.asm.mixin.injection.At;
1518
import org.spongepowered.asm.mixin.injection.Inject;
@@ -39,21 +42,24 @@
3942
*/
4043

4144
@Mixin(Window.class)
42-
public class WindowMixin {
45+
public abstract class WindowMixin {
46+
@Shadow protected abstract void onWindowPosChanged(long window, int x, int y);
47+
48+
@Shadow @Final private long handle;
49+
4350
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lorg/lwjgl/glfw/GLFW;glfwDefaultWindowHints()V", shift = At.Shift.AFTER, remap = false))
4451
private void onWindowHints(WindowEventHandler windowEventHandler, MonitorTracker monitorTracker, WindowSettings windowSettings, String string, String string2, CallbackInfo ci) {
4552
if (isWayland()) {
4653
GLFW.glfwWindowHint(GLFW.GLFW_FOCUS_ON_SHOW, GLFW.GLFW_FALSE);
4754

48-
if(!WayFix.config.injectIcon) return; // assuming that user wants wayland icon and not broken icon (mc launcher)
49-
DesktopFileInjector.inject();
55+
if(WayFix.config.injectIcon) DesktopFileInjector.inject();
5056
GLFW.glfwWindowHintString(GLFW.GLFW_WAYLAND_APP_ID, DesktopFileInjector.APP_ID);
5157
}
5258
}
5359

5460
@Redirect(method = "updateWindowRegion", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/MonitorTracker;getMonitor(Lnet/minecraft/client/util/Window;)Lnet/minecraft/client/util/Monitor;"))
5561
private Monitor fixWrongMonitor(MonitorTracker instance, Window window) {
56-
return WayFix.config.fullscreen.useMonitorName ? getMonitor(instance) : instance.getMonitor(window);
62+
return WayFix.config.fullscreen.useMonitorName && !WindowHelper.canUseWindowHelper ? getMonitor(instance) : instance.getMonitor(window);
5763
}
5864

5965
@Unique
@@ -69,6 +75,18 @@ private Monitor getMonitor(MonitorTracker instance) {
6975

7076
return instance.getMonitor(monitorID);
7177
}
78+
79+
80+
// KDE Plasma ONLY
81+
@Inject(method = "updateWindowRegion", at = @At("HEAD"))
82+
private void fixWrongMonitor(CallbackInfo ci) {
83+
if(!WindowHelper.canUseWindowHelper) return;
84+
85+
int[] pos = WindowHelper.getWindowPos();
86+
if(pos == null) return;
87+
88+
onWindowPosChanged(this.handle, pos[0], pos[1]);
89+
}
7290

7391
@Inject(method = "setIcon", at = @At("HEAD"), cancellable = true)
7492
//? if >=1.20 {
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package net.notcoded.wayfix.util;
2+
3+
import net.minecraft.client.MinecraftClient;
4+
import net.notcoded.wayfix.WayFix;
5+
6+
import java.io.IOException;
7+
import java.util.regex.Matcher;
8+
import java.util.regex.Pattern;
9+
10+
public class WindowHelper {
11+
12+
public static boolean canUseWindowHelper = false;
13+
14+
public static void checkIfCanUseWindowHelper() {
15+
if(!System.getenv("XDG_CURRENT_DESKTOP").contains("KDE")) return; // kdotool only works with KDE and I haven't found an alternative.
16+
17+
try {
18+
new ProcessBuilder("kdotool").start();
19+
canUseWindowHelper = true;
20+
} catch (IOException ignored) {
21+
WayFix.LOGGER.warn("WayFix recommends installing 'kdotool' to properly fix the minecraft full-screening functionality.");
22+
}
23+
}
24+
25+
private static String windowID = "";
26+
27+
public static int[] getWindowPos() {
28+
if(windowID.trim().isEmpty() && !setWindowID()) return null;
29+
30+
String[] command = new String[]{"kdotool", "getwindowgeometry", windowID};
31+
32+
ProcessBuilder builder = new ProcessBuilder(command);
33+
34+
try {
35+
Process process = builder.start();
36+
String result = new String(process.getInputStream().readAllBytes());
37+
Pattern pattern = Pattern.compile("Position:\\s*(\\d+),(\\d+)");
38+
Matcher matcher = pattern.matcher(result);
39+
if (matcher.find()) {
40+
return new int[]{Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2))};
41+
} else {
42+
return null;
43+
}
44+
} catch (IOException ignored) {
45+
return null;
46+
}
47+
}
48+
49+
public static boolean setWindowID() {
50+
if(!MinecraftClient.getInstance().isWindowFocused()) return false;
51+
String[] command = new String[]{"kdotool", "getactivewindow", "getwindowgeometry"};
52+
53+
ProcessBuilder builder = new ProcessBuilder(command);
54+
55+
try {
56+
Process process = builder.start();
57+
String result = new String(process.getInputStream().readAllBytes());
58+
Pattern pattern = Pattern.compile("Window \\{(\\w+-\\w+-\\w+-\\w+-\\w+)}");
59+
Matcher matcher = pattern.matcher(result);
60+
if (matcher.find()) {
61+
windowID = "{" + matcher.group(1) + "}"; // let's just hope this is the minecraft window 🙏
62+
return true;
63+
}
64+
return false;
65+
} catch (IOException ignored) {
66+
return false;
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)