diff --git a/app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt b/app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt index 2c2cf65ce..9897aa91d 100644 --- a/app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt +++ b/app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt @@ -53,11 +53,13 @@ fun ControllerTabContent(state: ContainerConfigState, default: Boolean) { SettingsSwitch( colors = settingsTileColorsAlt(), title = { Text(text = stringResource(R.string.disable_mouse_input)) }, + subtitle = { Text(text = stringResource(R.string.disable_mouse_input_description)) }, state = config.disableMouseInput, onCheckedChange = { state.config.value = config.copy(disableMouseInput = it) }, ) SettingsSwitch( colors = settingsTileColorsAlt(), + enabled = !config.disableMouseInput, title = { Text(text = stringResource(R.string.touchscreen_mode)) }, subtitle = { Text(text = stringResource(R.string.touchscreen_mode_description)) }, state = config.touchscreenMode, diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt index 036e5fb7b..fb1aeb877 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt @@ -150,7 +150,10 @@ class PhysicalControllerHandler( val cursorSpeed = profile?.cursorSpeed ?: 1f val deltaX = (mouseMoveOffset.x * 10 * cursorSpeed).toInt() val deltaY = (mouseMoveOffset.y * 10 * cursorSpeed).toInt() - xServer?.injectPointerMoveDelta(deltaX, deltaY) + xServer?.let { + if (!it.renderer.isCursorVisible) it.renderer.setCursorVisible(true) + it.injectPointerMoveDelta(deltaX, deltaY) + } } }, 0, 1000 / 60) } diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt index df2ae38d9..24db2dda1 100644 --- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt @@ -807,7 +807,7 @@ fun XServerScreen( } override fun onUpdateWindowContent(window: Window) { if (!xServerState.value.winStarted && window.isApplicationWindow()) { - if (!container.isDisableMouseInput && !container.isTouchscreenMode) renderer?.setCursorVisible(true) + if (!container.isDisableMouseInput) renderer?.setCursorVisible(true) xServerState.value.winStarted = true } if (window.id == frameRatingWindowId) { diff --git a/app/src/main/java/com/winlator/inputcontrols/TouchMouse.java b/app/src/main/java/com/winlator/inputcontrols/TouchMouse.java index 2253e3b02..fa6f5557b 100644 --- a/app/src/main/java/com/winlator/inputcontrols/TouchMouse.java +++ b/app/src/main/java/com/winlator/inputcontrols/TouchMouse.java @@ -304,6 +304,10 @@ public boolean onExternalMouseEvent(MotionEvent event) { boolean handled = false; // if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { if (isMouseDevice(event.getDevice())) { + // show cursor on external mouse event + if (!xServer.getRenderer().isCursorVisible()) { + xServer.getRenderer().setCursorVisible(true); + } int actionButton = event.getActionButton(); switch (event.getAction()) { case MotionEvent.ACTION_BUTTON_PRESS: diff --git a/app/src/main/java/com/winlator/widget/InputControlsView.java b/app/src/main/java/com/winlator/widget/InputControlsView.java index 15ae1d5a8..81b4efa4d 100644 --- a/app/src/main/java/com/winlator/widget/InputControlsView.java +++ b/app/src/main/java/com/winlator/widget/InputControlsView.java @@ -288,6 +288,8 @@ private void createMouseMoveTimer() { mouseMoveTimer.schedule(new TimerTask() { @Override public void run() { + // show cursor when on-screen control simulates mouse + if (!xServer.getRenderer().isCursorVisible()) xServer.getRenderer().setCursorVisible(true); xServer.injectPointerMoveDelta((int)(mouseMoveOffset.x * 10 * cursorSpeed), (int)(mouseMoveOffset.y * 10 * cursorSpeed)); } }, 0, 1000 / 60); diff --git a/app/src/main/java/com/winlator/widget/TouchpadView.java b/app/src/main/java/com/winlator/widget/TouchpadView.java index 06666e3ba..7cc79fd26 100644 --- a/app/src/main/java/com/winlator/widget/TouchpadView.java +++ b/app/src/main/java/com/winlator/widget/TouchpadView.java @@ -180,6 +180,10 @@ public boolean onTouchEvent(MotionEvent event) { && !event.isFromSource(InputDevice.SOURCE_MOUSE)) { return true; // consume without generating mouse events } + // hide cursor on touch in touchscreen mode, it reappears on external mouse event + if (isTouchscreenMode && !event.isFromSource(InputDevice.SOURCE_MOUSE) && xServer.getRenderer().isCursorVisible()) { + xServer.getRenderer().setCursorVisible(false); + } if (toolType == MotionEvent.TOOL_TYPE_STYLUS) { return handleStylusEvent(event); } else if (isTouchscreenMode) { @@ -602,6 +606,11 @@ public void setMoveCursorToTouchpoint(boolean moveCursorToTouchpoint) { } public boolean onExternalMouseEvent(MotionEvent event) { + // show cursor on external mouse event + if (event.isFromSource(InputDevice.SOURCE_MOUSE) + && !xServer.getRenderer().isCursorVisible()) { + xServer.getRenderer().setCursorVisible(true); + } // one-shot: capture external mouse on first event, don't re-capture after user release if (capturePointerOnExternalMouse && !pointerCaptureRequested) { pointerCaptureRequested = true; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bddc95a38..a41d4f2bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -559,7 +559,8 @@ Enable XInput API Enable DirectInput API DirectInput Mapper Type - Disable Mouse Input + Disable Touchscreen + Prevent touch from generating mouse events. External mouse and controller still work. Touchscreen Mode Direct touch-to-cursor movement (ON) vs touchpad-style relative movement (OFF) External Display Input