Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import dynamic_fps.impl.config.Config;
import dynamic_fps.impl.config.DynamicFPSConfig;
import dynamic_fps.impl.config.option.GraphicsState;
import dynamic_fps.impl.feature.state.ClickIgnoreHandler;
import dynamic_fps.impl.service.ModCompat;
import dynamic_fps.impl.feature.battery.BatteryToast;
import dynamic_fps.impl.feature.battery.BatteryTracker;
Expand Down Expand Up @@ -46,6 +47,7 @@ public class DynamicFPSMod {
private static final Minecraft minecraft = Minecraft.getInstance();

private static @Nullable WindowObserver window;
private static @Nullable ClickIgnoreHandler clickHandler;

private static long lastRender;

Expand Down Expand Up @@ -143,6 +145,8 @@ public static void toggleForceLowFPS() {
public static void setWindow(long address) {
IdleHandler.setWindow(address);
window = new WindowObserver(address);

initClickHandler();
}

public static boolean checkForRender() {
Expand Down Expand Up @@ -198,6 +202,7 @@ public static void onBatteryStatusChanged(State before, State after) {
// Internal logic

private static void doInit() {
initClickHandler();
SmoothVolumeHandler.init();

if (!BatteryTracker.isFeatureEnabled()) {
Expand All @@ -214,6 +219,16 @@ private static void doInit() {
}
}

private static void initClickHandler() {
if (window == null || clickHandler != null) {
return;
}


if (ClickIgnoreHandler.isFeatureActive()) {
clickHandler = new ClickIgnoreHandler(window.address());
}
}
private static void showNotification(String titleTranslationKey, String iconPath) {
if (!DynamicFPSConfig.INSTANCE.batteryTracker().notifications()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import dynamic_fps.impl.config.Config;
import dynamic_fps.impl.config.option.IdleCondition;
import dynamic_fps.impl.util.Components;
import dynamic_fps.impl.config.option.IgnoreInitialClick;
import dynamic_fps.impl.util.VariableStepTransformer;
import me.shedaniel.clothconfig2.api.ConfigBuilder;
import me.shedaniel.clothconfig2.api.ConfigCategory;
Expand Down Expand Up @@ -63,6 +64,19 @@ public static Screen genConfigScreen(Screen parent) {
.build()
);

misc.add(
entryBuilder.startEnumSelector(
Components.translatable("config", "ignore_initial_click"),
IgnoreInitialClick.class,
config.ignoreInitialClick()
)
.setDefaultValue(defaultConfig.ignoreInitialClick())
.setSaveConsumer(config::setIgnoreInitialClick)
.setEnumNameProvider(ClothConfig::ignoreInitialClickMessage)
.setTooltip(Components.translatable("config", "ignore_initial_click_tooltip"))
.build()
);

general.addEntry(misc.build());
SubCategoryBuilder idle = entryBuilder.startSubCategory(Components.translatable("config", "feature.idle"));

Expand Down Expand Up @@ -377,6 +391,10 @@ private static Component volumeMultiplierMessage(int value) {
return Components.literal(Integer.toString(value) + "%");
}

public static Component ignoreInitialClickMessage(Enum<IdleCondition> state) {
return Components.translatable("config", "ignore_initial_click_" + state.toString().toLowerCase(Locale.ROOT));
}

public static Component IdleConditionMessage(Enum<IdleCondition> state) {
return Components.translatable("config", "idle_condition_" + state.toString().toLowerCase(Locale.ROOT));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

import com.google.gson.annotations.SerializedName;
import dynamic_fps.impl.PowerState;
import dynamic_fps.impl.config.option.IgnoreInitialClick;

public final class DynamicFPSConfig {
private boolean enabled;
private boolean uncapMenuFrameRate;
private IgnoreInitialClick ignoreInitialClick;
private IdleConfig idle;
private BatteryTrackerConfig batteryTracker;
private VolumeTransitionConfig volumeTransitionSpeed;
Expand Down Expand Up @@ -65,6 +67,14 @@ public void setUncapMenuFrameRate(boolean value) {
this.uncapMenuFrameRate = value;
}

public IgnoreInitialClick ignoreInitialClick() {
return this.ignoreInitialClick;
}

public void setIgnoreInitialClick(IgnoreInitialClick value) {
this.ignoreInitialClick = value;
}

public boolean downloadNatives() {
return this.downloadNatives;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dynamic_fps.impl.config.option;

public enum IgnoreInitialClick {
DISABLED,
IN_WORLD,
CONSTANT;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dynamic_fps.impl.feature.state;

import dynamic_fps.impl.config.DynamicFPSConfig;
import dynamic_fps.impl.config.option.IgnoreInitialClick;
import net.minecraft.client.Minecraft;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWMouseButtonCallback;
import org.lwjgl.glfw.GLFWWindowFocusCallback;

import java.time.Instant;

public class ClickIgnoreHandler {
private final long address;
private long focusedAt;

private final GLFWWindowFocusCallback previousFocusCallback;
private final GLFWMouseButtonCallback previousClickCallback;

private static final Minecraft MINECRAFT = Minecraft.getInstance();

public ClickIgnoreHandler(long address) {
this.address = address;

this.previousFocusCallback = GLFW.glfwSetWindowFocusCallback(this.address, this::onFocusChanged);
this.previousClickCallback = GLFW.glfwSetMouseButtonCallback(this.address, this::onMouseClicked);
}

public static boolean isFeatureActive() {
return DynamicFPSConfig.INSTANCE.ignoreInitialClick() != IgnoreInitialClick.DISABLED;
}

private boolean shouldIgnoreClick() {
IgnoreInitialClick config = DynamicFPSConfig.INSTANCE.ignoreInitialClick();

if (config == IgnoreInitialClick.DISABLED) {
return false;
}

if (config == IgnoreInitialClick.IN_WORLD && MINECRAFT.screen != null) {
return false;
}

return this.focusedAt + 20 >= Instant.now().toEpochMilli();
}

private void onFocusChanged(long address, boolean focused) {
if (this.isCurrentWindow(address) && focused) {
this.focusedAt = Instant.now().toEpochMilli();
}

if (this.previousFocusCallback != null) {
this.previousFocusCallback.invoke(address, focused);
}
}

private void onMouseClicked(long window, int button, int action, int mods) {
if (this.isCurrentWindow(window) && shouldIgnoreClick()) {
return;
}

if (this.previousClickCallback != null) {
this.previousClickCallback.invoke(window, button, action, mods);
}
}

private boolean isCurrentWindow(long address) {
return address == this.address;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package dynamic_fps.impl.feature.state;

import dynamic_fps.impl.util.Logging;
import net.minecraft.client.Minecraft;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWCursorEnterCallback;
import org.lwjgl.glfw.GLFWMouseButtonCallback;
import org.lwjgl.glfw.GLFWWindowFocusCallback;
import org.lwjgl.glfw.GLFWWindowIconifyCallback;

import dynamic_fps.impl.DynamicFPSMod;

import java.time.Instant;

public class WindowObserver {
private final long address;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"enabled": true,
"uncap_menu_frame_rate": false,
"ignore_initial_click": "disabled",
"idle": {
"timeout": 300,
"condition": "vanilla"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
"config.dynamic_fps.uncap_menu_frame_rate": "Uncap Menu FPS",
"config.dynamic_fps.uncap_menu_frame_rate_tooltip": "Remove the 60 FPS limit in the main menu.",

"config.dynamic_fps.ignore_initial_click": "Ignore Initial Click",
"config.dynamic_fps.ignore_initial_click_tooltip": "Ignore accidental input when clicking on the unfocused game window.",

"config.dynamic_fps.ignore_initial_click_disabled": "Disabled",
"config.dynamic_fps.ignore_initial_click_in_world": "In World",
"config.dynamic_fps.ignore_initial_click_constant": "Constant",

"config.dynamic_fps.battery_tracker": "Battery Tracking",
"config.dynamic_fps.battery_tracker_tooltip": "Toggle all battery-related features on or off.",

Expand Down