Skip to content
Open
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<maven.compiler.target>21</maven.compiler.target>
<native.maven.plugin.version>0.9.28</native.maven.plugin.version>
<imageName>mousemaster</imageName>
<mainClass>mousemaster.MousemasterApplication</mainClass>
<mainClass>mousemaster.platform.windows.WindowsMain</mainClass>
<jna.version>5.13.0</jna.version> <!-- Check https://www.graalvm.org/latest/reference-manual/native-image/metadata/ -->
</properties>
<dependencies>
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/mousemaster/ApplicationOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package mousemaster;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Predicate;
import java.util.stream.Stream;

public record ApplicationOptions(String tempDirectory,
String logLevel,
boolean logToFile,
boolean pauseOnError,
boolean showVersion,
Path configurationPath,
boolean multipleInstancesAllowed,
boolean keyRegurgitationEnabled,
boolean graalvmAgentRun) {

public static ApplicationOptions parse(String[] args) {
return new ApplicationOptions(
stringArg(args, "--temp-directory=", null),
stringArg(args, "--log-level=", null),
booleanArg(args, "--log-to-file=", false),
booleanArg(args, "--pause-on-error=", true),
Stream.of(args).anyMatch(Predicate.isEqual("--version")),
Paths.get(stringArg(args, "--configuration-file=",
"mousemaster.properties")),
booleanArg(args, "--multiple-instances-allowed=", false),
booleanArg(args, "--key-regurgitation-enabled=", true),
Stream.of(args).anyMatch(Predicate.isEqual("--graalvm-agent-run"))
);
}

private static String stringArg(String[] args, String prefix, String defaultValue) {
return Stream.of(args)
.filter(arg -> arg.startsWith(prefix))
.map(arg -> arg.substring(prefix.length()))
.findFirst()
.orElse(defaultValue);
}

private static boolean booleanArg(String[] args, String prefix, boolean defaultValue) {
return Stream.of(args)
.filter(arg -> arg.startsWith(prefix))
.map(arg -> arg.substring(prefix.length()))
.findFirst()
.map(Boolean::parseBoolean)
.orElse(defaultValue);
}

}
1 change: 1 addition & 0 deletions src/main/java/mousemaster/ComboWatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mousemaster.ComboMove.WaitComboMove;
import mousemaster.ResolvedKeyComboMove.ResolvedPressComboMove;
import mousemaster.platform.ActiveAppFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
13 changes: 8 additions & 5 deletions src/main/java/mousemaster/GridManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mousemaster;

import mousemaster.Grid.GridBuilder;
import mousemaster.platform.Overlay;

/**
* Displays the grid and handles grid commands.
Expand All @@ -9,13 +10,16 @@ public class GridManager implements MousePositionListener, ModeListener {

private final ScreenManager screenManager;
private final MouseController mouseController;
private final Overlay overlay;
private Grid grid;
private int mouseX, mouseY;
private Mode currentMode;

public GridManager(ScreenManager screenManager, MouseController mouseController) {
public GridManager(ScreenManager screenManager, MouseController mouseController,
Overlay overlay) {
this.screenManager = screenManager;
this.mouseController = mouseController;
this.overlay = overlay;
}

public void shrinkGridUp() {
Expand Down Expand Up @@ -294,7 +298,7 @@ public void modeChanged(Mode newMode) {
.height(gridHeight);
}
case GridArea.ActiveWindowGridArea activeWindowGridArea -> {
Rectangle activeWindowRectangle = WindowsOverlay.activeWindowRectangle(
Rectangle activeWindowRectangle = overlay.activeWindowRectangle(
activeWindowGridArea.widthPercent(),
activeWindowGridArea.heightPercent(), scaledTopInset,
scaledBottomInset, scaledLeftInset, scaledRightInset);
Expand Down Expand Up @@ -325,9 +329,9 @@ private void gridChanged() {

private void setOverlay() {
if (grid.lineVisible())
WindowsOverlay.setGrid(grid);
overlay.setGrid(grid);
else
WindowsOverlay.hideGrid();
overlay.hideGrid();
}

@Override
Expand All @@ -336,4 +340,3 @@ public void modeTimedOut() {
}

}

2 changes: 1 addition & 1 deletion src/main/java/mousemaster/Hint.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
public record Hint(double centerX, double centerY, double cellWidth, double cellHeight,
List<Key> keySequence) {

boolean startsWith(List<Key> selectedHintKeySequence) {
public boolean startsWith(List<Key> selectedHintKeySequence) {
if (selectedHintKeySequence.isEmpty())
return true;
return keySequence.subList(0, selectedHintKeySequence.size())
Expand Down
44 changes: 26 additions & 18 deletions src/main/java/mousemaster/HintManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import mousemaster.HintGridArea.ActiveWindowHintGridArea;
import mousemaster.HintGridArea.AllScreensHintGridArea;
import mousemaster.HintMesh.HintMeshBuilder;
import mousemaster.platform.Overlay;
import mousemaster.platform.UiAutomation;
import mousemaster.platform.UiAutomation.UiElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -18,6 +21,8 @@ public class HintManager implements ModeListener, MousePositionListener {

private final ScreenManager screenManager;
private final MouseController mouseController;
private final Overlay overlay;
private final UiAutomation uiAutomation;
private ModeController modeController;
private HintMesh hintMesh;
private ViewportFilter screenFilter;
Expand All @@ -40,14 +45,14 @@ public class HintManager implements ModeListener, MousePositionListener {
private boolean lastHintCommandSupercedesOtherCommands;

private record PendingUiHintQuery(
Future<List<WindowsUiAutomation.UiElement>> future,
Future<List<UiElement>> future,
HintMeshConfiguration hintMeshConfiguration,
Zoom zoom,
ViewportFilter screenFilter) {
}

private PendingUiHintQuery pendingUiHintQuery;
private List<WindowsUiAutomation.UiElement> lastUiElements;
private List<UiElement> lastUiElements;

/**
* It would be better to have an instance of Zoom instead of ZoomConfiguration
Expand All @@ -69,10 +74,13 @@ private record HintMeshState(HintMesh hintMesh,
}

public HintManager(int maxPositionHistorySize, ScreenManager screenManager,
MouseController mouseController) {
MouseController mouseController, Overlay overlay,
UiAutomation uiAutomation) {
this.maxPositionHistorySize = maxPositionHistorySize;
this.screenManager = screenManager;
this.mouseController = mouseController;
this.overlay = overlay;
this.uiAutomation = uiAutomation;
}

public void setModeController(ModeController modeController) {
Expand Down Expand Up @@ -158,15 +166,15 @@ else if (hintMeshConfiguration.type() instanceof HintMeshType.HintGrid hintGrid
currentMode = newMode;
hintMeshStates.clear();
hintMesh = null;
WindowsOverlay.hideHintMesh();
overlay.hideHintMesh();
return;
}
if (!hintMeshConfiguration.visible()) {
// This makes the behavior of the hint different depending on whether it is visible.
// An alternative would be a setting like hint.reset-selected-key-sequence-history-after-selection=true.
hintMeshStates.clear();
hintMesh = null;
WindowsOverlay.hideHintMesh();
overlay.hideHintMesh();
}
Point zoomCenterPoint = newMode.zoom().center().centerPoint(
screenManager.activeScreen().rectangle(), mouseX, mouseY,
Expand All @@ -180,7 +188,7 @@ else if (hintMeshConfiguration.type() instanceof HintMeshType.HintGrid hintGrid
if (currentMode == null ||
!(currentMode.hintMesh().type() instanceof HintMeshType.UiHintMesh)) {
pendingUiHintQuery = new PendingUiHintQuery(
WindowsUiAutomation.startFindInteractiveUiElements(),
uiAutomation.startFindInteractiveUiElements(),
hintMeshConfiguration, newZoom, newScreenFilter);
currentMode = newMode;
currentZoom = newZoom;
Expand Down Expand Up @@ -229,7 +237,7 @@ private void activateHintMesh(Mode newMode, HintMesh newHintMesh,
newMode.zoom()),
new HintMeshState(newHintMesh, lastSelectedHintPoint));
hintMesh = newHintMesh;
WindowsOverlay.setHintMesh(hintMesh, newZoom);
overlay.setHintMesh(hintMesh, newZoom);
if (hintMeshConfiguration.mouseMovement() ==
HintMouseMovement.MOUSE_FOLLOWS_HINT_GRID_CENTER) {
moveMouse(hintMeshCenter(hintMesh.hints(), hintMesh.selectedKeySequence()));
Expand Down Expand Up @@ -287,7 +295,7 @@ public void completePendingUiHintQuery() {
return;
PendingUiHintQuery pending = pendingUiHintQuery;
pendingUiHintQuery = null;
List<WindowsUiAutomation.UiElement> uiElements;
List<UiElement> uiElements;
try {
uiElements = pending.future().get();
}
Expand Down Expand Up @@ -324,7 +332,7 @@ private ViewportFilter screenFilter(HintMeshConfiguration hintMeshConfiguration)
}
case ActiveWindowHintGridArea activeWindowHintGridArea -> {
Rectangle activeWindowRectangle =
WindowsOverlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
overlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
Point gridCenter = activeWindowRectangle.center();
Screen screen =
screenManager.nearestScreenContaining(gridCenter.x(),
Expand All @@ -335,7 +343,7 @@ private ViewportFilter screenFilter(HintMeshConfiguration hintMeshConfiguration)
}
else if (type instanceof HintMeshType.UiHintMesh) {
Rectangle activeWindowRectangle =
WindowsOverlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
overlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
Point center = activeWindowRectangle.center();
Screen screen = screenManager.nearestScreenContaining(center.x(), center.y());
return ViewportFilter.of(screen);
Expand All @@ -352,7 +360,7 @@ private HintMesh buildHintMesh(
HintMeshConfiguration hintMeshConfiguration,
ZoomConfiguration zoomConfiguration, Zoom zoom,
ViewportFilter screenFilter,
List<WindowsUiAutomation.UiElement> uiElements) {
List<UiElement> uiElements) {
HintMeshBuilder hintMesh = new HintMeshBuilder();
hintMesh.visible(hintMeshConfiguration.visible())
.styleByFilter(hintMeshConfiguration.styleByFilter());
Expand Down Expand Up @@ -403,7 +411,7 @@ else if (hintGrid.area() instanceof AllScreensHintGridArea allScreensHintGridAre
}
else if (hintGrid.area() instanceof ActiveWindowHintGridArea activeWindowHintGridArea) {
Rectangle activeWindowRectangle =
WindowsOverlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
overlay.activeWindowRectangle(1, 1, 0, 0, 0, 0);
Point gridCenter = activeWindowRectangle.center();
Screen screen =
screenManager.nearestScreenContaining(gridCenter.x(), gridCenter.y());
Expand Down Expand Up @@ -468,7 +476,7 @@ else if (type instanceof HintMeshType.UiHintMesh) {
.prefixLength(prefixLengths.size() == 1 ?
prefixLengths.iterator().next() : -1)
.backgroundArea(
WindowsOverlay.activeWindowRectangle(1, 1, 0, 0, 0, 0));
overlay.activeWindowRectangle(1, 1, 0, 0, 0, 0));
}
else {
int hintCount = positionHistory.size();
Expand Down Expand Up @@ -544,14 +552,14 @@ else if (type instanceof HintMeshType.UiHintMesh) {

private void buildUiHints(HintMeshConfiguration hintMeshConfiguration,
ViewportFilter screenFilter,
List<WindowsUiAutomation.UiElement> uiElements,
List<UiElement> uiElements,
Set<Integer> prefixLengths, List<Hint> hints) {
HintMeshKeys hintMeshKeys =
hintMeshConfiguration.keysByFilter().get(screenFilter);
List<Key> selectionKeys = hintMeshKeys.selectionKeys();
int rowKeyOffset = hintMeshKeys.rowKeyOffset();
for (int i = 0; i < uiElements.size(); i++) {
WindowsUiAutomation.UiElement element = uiElements.get(i);
UiElement element = uiElements.get(i);
List<Key> keySequence = hintKeySequence(
selectionKeys, rowKeyOffset, uiElements.size(),
0, -1, i,
Expand Down Expand Up @@ -911,7 +919,7 @@ public void unselectHintKey() {
hintMeshStates.get(hintMeshKey).previousModeSelectedHintPoint
)
);
WindowsOverlay.setHintMesh(hintMesh, currentZoom);
overlay.setHintMesh(hintMesh, currentZoom);
if (hintMeshConfiguration.mouseMovement() == HintMouseMovement.MOUSE_FOLLOWS_HINT_GRID_CENTER) {
moveMouse(hintMeshCenter(hintMesh.hints(),
hintMesh.selectedKeySequence()));
Expand Down Expand Up @@ -987,7 +995,7 @@ public void selectHintKey(Key key) {
hintMesh,
hintMeshStates.get(hintMeshKey).previousModeSelectedHintPoint
));
WindowsOverlay.setHintMesh(hintMesh, currentZoom);
overlay.setHintMesh(hintMesh, currentZoom);
if (hintMeshConfiguration.mouseMovement() == HintMouseMovement.MOUSE_FOLLOWS_HINT_GRID_CENTER) {
moveMouse(hintMeshCenter(hintMesh.hints(), newSelectedKeySequence));
}
Expand Down Expand Up @@ -1031,7 +1039,7 @@ private void finalizeHintSelection(Hint hint, List<Key> newSelectedKeySequence)
.map(Key::name)
.toList() +
" selected");
WindowsOverlay.animateHintMatch(hint);
overlay.animateHintMatch(hint);
hintMesh =
hintMesh.builder()
.selectedKeySequence(newSelectedKeySequence)
Expand Down
13 changes: 9 additions & 4 deletions src/main/java/mousemaster/IndicatorManager.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package mousemaster;

import mousemaster.platform.Overlay;

public class IndicatorManager implements ModeListener {

private final Overlay overlay;
private final MouseState mouseState;
private final KeyboardState keyboardState;
private Mode currentMode;

public IndicatorManager(MouseState mouseState, KeyboardState keyboardState) {
public IndicatorManager(Overlay overlay, MouseState mouseState,
KeyboardState keyboardState) {
this.overlay = overlay;
this.mouseState = mouseState;
this.keyboardState = keyboardState;
}
Expand All @@ -28,15 +33,15 @@ private void updateIndicator(boolean allowFade) {
if (currentMode.indicator().enabled()) {
Indicator indicator = activeIndicator();
if (indicator.hexColor() == null)
WindowsOverlay.hideIndicator(allowFade);
overlay.hideIndicator(allowFade);
else
WindowsOverlay.setIndicator(indicator,
overlay.setIndicator(indicator,
currentMode.indicator().fadeAnimationEnabled(),
currentMode.indicator().fadeAnimationDuration(),
allowFade);
}
else
WindowsOverlay.hideIndicator(allowFade);
overlay.hideIndicator(allowFade);
}

@Override
Expand Down
Loading