mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-25 14:54:56 +00:00
Merge pull request #10858 from AdmiralCurtiss/mouse-center-hotkey
Add hotkey for centering mouse in render window.
This commit is contained in:
commit
9d15a1c5a1
9 changed files with 108 additions and 32 deletions
|
@ -35,6 +35,7 @@ constexpr std::array<const char*, NUM_HOTKEYS> s_hotkey_labels{{
|
||||||
_trans("Take Screenshot"),
|
_trans("Take Screenshot"),
|
||||||
_trans("Exit"),
|
_trans("Exit"),
|
||||||
_trans("Unlock Cursor"),
|
_trans("Unlock Cursor"),
|
||||||
|
_trans("Center Mouse"),
|
||||||
_trans("Activate NetPlay Chat"),
|
_trans("Activate NetPlay Chat"),
|
||||||
_trans("Control NetPlay Golf Mode"),
|
_trans("Control NetPlay Golf Mode"),
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum Hotkey
|
||||||
HK_SCREENSHOT,
|
HK_SCREENSHOT,
|
||||||
HK_EXIT,
|
HK_EXIT,
|
||||||
HK_UNLOCK_CURSOR,
|
HK_UNLOCK_CURSOR,
|
||||||
|
HK_CENTER_MOUSE,
|
||||||
HK_ACTIVATE_CHAT,
|
HK_ACTIVATE_CHAT,
|
||||||
HK_REQUEST_GOLF_CONTROL,
|
HK_REQUEST_GOLF_CONTROL,
|
||||||
|
|
||||||
|
|
|
@ -233,6 +233,9 @@ void HotkeyScheduler::Run()
|
||||||
if (IsHotkey(HK_UNLOCK_CURSOR))
|
if (IsHotkey(HK_UNLOCK_CURSOR))
|
||||||
emit UnlockCursor();
|
emit UnlockCursor();
|
||||||
|
|
||||||
|
if (IsHotkey(HK_CENTER_MOUSE, true))
|
||||||
|
g_controller_interface.SetMouseCenteringRequested(true);
|
||||||
|
|
||||||
auto& settings = Settings::Instance();
|
auto& settings = Settings::Instance();
|
||||||
|
|
||||||
// Toggle Chat
|
// Toggle Chat
|
||||||
|
|
|
@ -421,6 +421,16 @@ Common::Vec2 ControllerInterface::GetWindowInputScale() const
|
||||||
return {1 / ar, 1.f};
|
return {1 / ar, 1.f};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ControllerInterface::SetMouseCenteringRequested(bool center)
|
||||||
|
{
|
||||||
|
m_requested_mouse_centering = center;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerInterface::IsMouseCenteringRequested() const
|
||||||
|
{
|
||||||
|
return m_requested_mouse_centering.load();
|
||||||
|
}
|
||||||
|
|
||||||
// Register a callback to be called when a device is added or removed (as from the input backends'
|
// Register a callback to be called when a device is added or removed (as from the input backends'
|
||||||
// hotplug thread), or when devices are refreshed
|
// hotplug thread), or when devices are refreshed
|
||||||
// Returns a handle for later removing the callback.
|
// Returns a handle for later removing the callback.
|
||||||
|
|
|
@ -106,6 +106,11 @@ public:
|
||||||
// Inputs based on window coordinates should be multiplied by this.
|
// Inputs based on window coordinates should be multiplied by this.
|
||||||
Common::Vec2 GetWindowInputScale() const;
|
Common::Vec2 GetWindowInputScale() const;
|
||||||
|
|
||||||
|
// Request that the mouse cursor should be centered in the render window at the next opportunity.
|
||||||
|
void SetMouseCenteringRequested(bool center);
|
||||||
|
|
||||||
|
bool IsMouseCenteringRequested() const;
|
||||||
|
|
||||||
HotplugCallbackHandle RegisterDevicesChangedCallback(std::function<void(void)> callback);
|
HotplugCallbackHandle RegisterDevicesChangedCallback(std::function<void(void)> callback);
|
||||||
void UnregisterDevicesChangedCallback(const HotplugCallbackHandle& handle);
|
void UnregisterDevicesChangedCallback(const HotplugCallbackHandle& handle);
|
||||||
void InvokeDevicesChangedCallbacks() const;
|
void InvokeDevicesChangedCallbacks() const;
|
||||||
|
@ -127,6 +132,7 @@ private:
|
||||||
std::atomic<int> m_populating_devices_counter;
|
std::atomic<int> m_populating_devices_counter;
|
||||||
WindowSystemInfo m_wsi;
|
WindowSystemInfo m_wsi;
|
||||||
std::atomic<float> m_aspect_ratio_adjustment = 1;
|
std::atomic<float> m_aspect_ratio_adjustment = 1;
|
||||||
|
std::atomic<bool> m_requested_mouse_centering = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ciface
|
namespace ciface
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
|
#include "Core/Host.h"
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
||||||
|
@ -168,13 +170,6 @@ KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device,
|
||||||
|
|
||||||
void KeyboardMouse::UpdateCursorInput()
|
void KeyboardMouse::UpdateCursorInput()
|
||||||
{
|
{
|
||||||
POINT point = {};
|
|
||||||
GetCursorPos(&point);
|
|
||||||
|
|
||||||
// Get the cursor position relative to the upper left corner of the current window
|
|
||||||
// (separate or render to main)
|
|
||||||
ScreenToClient(s_hwnd, &point);
|
|
||||||
|
|
||||||
// Get the size of the current window (in my case Rect.top and Rect.left was zero).
|
// Get the size of the current window (in my case Rect.top and Rect.left was zero).
|
||||||
RECT rect;
|
RECT rect;
|
||||||
GetClientRect(s_hwnd, &rect);
|
GetClientRect(s_hwnd, &rect);
|
||||||
|
@ -183,6 +178,26 @@ void KeyboardMouse::UpdateCursorInput()
|
||||||
const auto win_width = std::max(rect.right - rect.left, 1l);
|
const auto win_width = std::max(rect.right - rect.left, 1l);
|
||||||
const auto win_height = std::max(rect.bottom - rect.top, 1l);
|
const auto win_height = std::max(rect.bottom - rect.top, 1l);
|
||||||
|
|
||||||
|
POINT point = {};
|
||||||
|
if (g_controller_interface.IsMouseCenteringRequested() && Host_RendererHasFocus())
|
||||||
|
{
|
||||||
|
point.x = win_width / 2;
|
||||||
|
point.y = win_height / 2;
|
||||||
|
|
||||||
|
POINT screen_point = point;
|
||||||
|
ClientToScreen(s_hwnd, &screen_point);
|
||||||
|
SetCursorPos(screen_point.x, screen_point.y);
|
||||||
|
g_controller_interface.SetMouseCenteringRequested(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetCursorPos(&point);
|
||||||
|
|
||||||
|
// Get the cursor position relative to the upper left corner of the current window
|
||||||
|
// (separate or render to main)
|
||||||
|
ScreenToClient(s_hwnd, &point);
|
||||||
|
}
|
||||||
|
|
||||||
const auto window_scale = g_controller_interface.GetWindowInputScale();
|
const auto window_scale = g_controller_interface.GetWindowInputScale();
|
||||||
|
|
||||||
// Convert the cursor position to a range from -1 to 1.
|
// Convert the cursor position to a range from -1 to 1.
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "Core/Host.h"
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
|
|
||||||
namespace ciface::Quartz
|
namespace ciface::Quartz
|
||||||
|
@ -192,6 +194,25 @@ void KeyboardAndMouse::UpdateInput()
|
||||||
CFRelease(windowDescriptions);
|
CFRelease(windowDescriptions);
|
||||||
CFRelease(windowArray);
|
CFRelease(windowArray);
|
||||||
|
|
||||||
|
const double window_width = std::max(bounds.size.width, 1.0);
|
||||||
|
const double window_height = std::max(bounds.size.height, 1.0);
|
||||||
|
|
||||||
|
if (g_controller_interface.IsMouseCenteringRequested() && Host_RendererHasFocus())
|
||||||
|
{
|
||||||
|
m_cursor.x = 0;
|
||||||
|
m_cursor.y = 0;
|
||||||
|
|
||||||
|
const CGPoint window_center_global_coordinates =
|
||||||
|
CGPointMake(bounds.origin.x + window_width / 2.0, bounds.origin.y + window_height / 2.0);
|
||||||
|
CGWarpMouseCursorPosition(window_center_global_coordinates);
|
||||||
|
// Without this line there is a short but obvious delay after centering the cursor before it can
|
||||||
|
// be moved again
|
||||||
|
CGAssociateMouseAndMouseCursorPosition(true);
|
||||||
|
|
||||||
|
g_controller_interface.SetMouseCenteringRequested(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
CGEventRef event = CGEventCreate(nil);
|
CGEventRef event = CGEventCreate(nil);
|
||||||
CGPoint loc = CGEventGetLocation(event);
|
CGPoint loc = CGEventGetLocation(event);
|
||||||
CFRelease(event);
|
CFRelease(event);
|
||||||
|
@ -200,8 +221,9 @@ void KeyboardAndMouse::UpdateInput()
|
||||||
|
|
||||||
loc.x -= bounds.origin.x;
|
loc.x -= bounds.origin.x;
|
||||||
loc.y -= bounds.origin.y;
|
loc.y -= bounds.origin.y;
|
||||||
m_cursor.x = (loc.x / std::max(bounds.size.width, 1.0) * 2 - 1.0) * window_scale.x;
|
m_cursor.x = (loc.x / window_width * 2 - 1.0) * window_scale.x;
|
||||||
m_cursor.y = (loc.y / std::max(bounds.size.height, 1.0) * 2 - 1.0) * window_scale.y;
|
m_cursor.y = (loc.y / window_height * 2 - 1.0) * window_scale.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardAndMouse::GetName() const
|
std::string KeyboardAndMouse::GetName() const
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
#include "Core/Host.h"
|
||||||
|
|
||||||
// This is an input plugin using the XInput 2.0 extension to the X11 protocol,
|
// This is an input plugin using the XInput 2.0 extension to the X11 protocol,
|
||||||
// loosely based on the old XLib plugin. (Has nothing to do with the XInput
|
// loosely based on the old XLib plugin. (Has nothing to do with the XInput
|
||||||
// API on Windows.)
|
// API on Windows.)
|
||||||
|
@ -209,11 +211,27 @@ KeyboardMouse::~KeyboardMouse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the mouse cursor controls
|
// Update the mouse cursor controls
|
||||||
void KeyboardMouse::UpdateCursor()
|
void KeyboardMouse::UpdateCursor(bool should_center_mouse)
|
||||||
{
|
{
|
||||||
double root_x, root_y, win_x, win_y;
|
double root_x, root_y, win_x, win_y;
|
||||||
Window root, child;
|
Window root, child;
|
||||||
|
|
||||||
|
XWindowAttributes win_attribs;
|
||||||
|
XGetWindowAttributes(m_display, m_window, &win_attribs);
|
||||||
|
const auto win_width = std::max(win_attribs.width, 1);
|
||||||
|
const auto win_height = std::max(win_attribs.height, 1);
|
||||||
|
|
||||||
|
if (should_center_mouse)
|
||||||
|
{
|
||||||
|
win_x = win_width / 2;
|
||||||
|
win_y = win_height / 2;
|
||||||
|
|
||||||
|
XIWarpPointer(m_display, pointer_deviceid, None, m_window, 0.0, 0.0, 0, 0, win_x, win_y);
|
||||||
|
|
||||||
|
g_controller_interface.SetMouseCenteringRequested(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// unused-- we're not interested in button presses here, as those are
|
// unused-- we're not interested in button presses here, as those are
|
||||||
// updated using events
|
// updated using events
|
||||||
XIButtonState button_state;
|
XIButtonState button_state;
|
||||||
|
@ -224,15 +242,13 @@ void KeyboardMouse::UpdateCursor()
|
||||||
&win_y, &button_state, &mods, &group);
|
&win_y, &button_state, &mods, &group);
|
||||||
|
|
||||||
free(button_state.mask);
|
free(button_state.mask);
|
||||||
|
}
|
||||||
XWindowAttributes win_attribs;
|
|
||||||
XGetWindowAttributes(m_display, m_window, &win_attribs);
|
|
||||||
|
|
||||||
const auto window_scale = g_controller_interface.GetWindowInputScale();
|
const auto window_scale = g_controller_interface.GetWindowInputScale();
|
||||||
|
|
||||||
// the mouse position as a range from -1 to 1
|
// the mouse position as a range from -1 to 1
|
||||||
m_state.cursor.x = (win_x / std::max(win_attribs.width, 1) * 2 - 1) * window_scale.x;
|
m_state.cursor.x = (win_x / win_width * 2 - 1) * window_scale.x;
|
||||||
m_state.cursor.y = (win_y / std::max(win_attribs.height, 1) * 2 - 1) * window_scale.y;
|
m_state.cursor.y = (win_y / win_height * 2 - 1) * window_scale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardMouse::UpdateInput()
|
void KeyboardMouse::UpdateInput()
|
||||||
|
@ -318,8 +334,10 @@ void KeyboardMouse::UpdateInput()
|
||||||
m_state.axis.y /= MOUSE_AXIS_SMOOTHING + 1.0f;
|
m_state.axis.y /= MOUSE_AXIS_SMOOTHING + 1.0f;
|
||||||
|
|
||||||
// Get the absolute position of the mouse pointer
|
// Get the absolute position of the mouse pointer
|
||||||
if (mouse_moved)
|
const bool should_center_mouse =
|
||||||
UpdateCursor();
|
g_controller_interface.IsMouseCenteringRequested() && Host_RendererHasFocus();
|
||||||
|
if (mouse_moved || should_center_mouse)
|
||||||
|
UpdateCursor(should_center_mouse);
|
||||||
|
|
||||||
// KeyRelease and FocusOut events are sometimes not received.
|
// KeyRelease and FocusOut events are sometimes not received.
|
||||||
// Cycling Alt-Tab and landing on the same window results in a stuck "Alt" key.
|
// Cycling Alt-Tab and landing on the same window results in a stuck "Alt" key.
|
||||||
|
|
|
@ -108,7 +108,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SelectEventsForDevice(XIEventMask* mask, int deviceid);
|
void SelectEventsForDevice(XIEventMask* mask, int deviceid);
|
||||||
void UpdateCursor();
|
void UpdateCursor(bool should_center_mouse);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void UpdateInput() override;
|
void UpdateInput() override;
|
||||||
|
|
Loading…
Add table
Reference in a new issue