summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-10-22 04:55:12 -0400
committerGitHub <noreply@github.com>2022-10-22 04:55:12 -0400
commitbc4d08047d43e9d12131ee77b6cd58e020a3a35f (patch)
tree9c66868d3684f1ffaef4685ad8cadbaa461f6d96 /Source/Core/InputCommon
parent4bf8a2393c49cb4e888b6e85f8a93466f446583e (diff)
parent588c4bd6355f20dd74008054b1bb876810f4ba13 (diff)
Merge pull request #10979 from tellowkrinkle/QuartzWindowSpeed
InputCommon:QuartzKB&M: Use KVO to watch window position
Diffstat (limited to 'Source/Core/InputCommon')
-rw-r--r--Source/Core/InputCommon/CMakeLists.txt3
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h11
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm102
3 files changed, 87 insertions, 29 deletions
diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt
index 53929b7f6c..2caa334cca 100644
--- a/Source/Core/InputCommon/CMakeLists.txt
+++ b/Source/Core/InputCommon/CMakeLists.txt
@@ -124,6 +124,9 @@ elseif(APPLE)
${FORCEFEEDBACK_LIBRARY}
${IOK_LIBRARY}
)
+ target_compile_options(inputcommon PRIVATE
+ -fobjc-arc
+ )
elseif(X11_FOUND)
target_sources(inputcommon PRIVATE
ControllerInterface/Xlib/XInput2.cpp
diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h
index dfcf216e45..e4bdb6e5fb 100644
--- a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h
+++ b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h
@@ -8,6 +8,12 @@
#include "Common/Matrix.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
+#ifdef __OBJC__
+@class DolWindowPositionObserver;
+#else
+class DolWindowPositionObserver;
+#endif
+
namespace ciface::Quartz
{
std::string KeycodeToName(const CGKeyCode keycode);
@@ -59,13 +65,16 @@ public:
void UpdateInput() override;
explicit KeyboardAndMouse(void* view);
+ ~KeyboardAndMouse() override;
std::string GetName() const override;
std::string GetSource() const override;
private:
+ void MainThreadInitialization(void* view);
+
Common::Vec2 m_cursor;
- uint32_t m_windowid;
+ DolWindowPositionObserver* m_window_pos_observer;
};
} // namespace ciface::Quartz
diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm
index b8ae0219be..a610956d93 100644
--- a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm
+++ b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm
@@ -4,6 +4,7 @@
#include "InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.h"
#include <map>
+#include <mutex>
#include <Carbon/Carbon.h>
#include <Cocoa/Cocoa.h>
@@ -12,6 +13,66 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
+/// Helper class to get window position data from threads other than the main thread
+@interface DolWindowPositionObserver : NSObject
+
+- (instancetype)initWithView:(NSView*)view;
+@property(readonly) NSRect frame;
+
+@end
+
+@implementation DolWindowPositionObserver
+{
+ NSView* _view;
+ NSWindow* _window;
+ NSRect _frame;
+ std::mutex _mtx;
+}
+
+- (NSRect)calcFrame
+{
+ return [_window convertRectToScreen:[_view frame]];
+}
+
+- (instancetype)initWithView:(NSView*)view
+{
+ self = [super init];
+ if (self)
+ {
+ _view = view;
+ _window = [view window];
+ _frame = [self calcFrame];
+ [_window addObserver:self forKeyPath:@"frame" options:0 context:nil];
+ }
+ return self;
+}
+
+- (NSRect)frame
+{
+ std::lock_guard<std::mutex> guard(_mtx);
+ return _frame;
+}
+
+- (void)observeValueForKeyPath:(NSString*)keyPath
+ ofObject:(id)object
+ change:(NSDictionary<NSKeyValueChangeKey, id>*)change
+ context:(void*)context
+{
+ if (object == _window)
+ {
+ NSRect new_frame = [self calcFrame];
+ std::lock_guard<std::mutex> guard(_mtx);
+ _frame = new_frame;
+ }
+}
+
+- (void)dealloc
+{
+ [_window removeObserver:self forKeyPath:@"frame"];
+}
+
+@end
+
namespace ciface::Quartz
{
std::string KeycodeToName(const CGKeyCode keycode)
@@ -149,20 +210,12 @@ KeyboardAndMouse::KeyboardAndMouse(void* view)
AddCombinedInput("Shift", {"Left Shift", "Right Shift"});
AddCombinedInput("Ctrl", {"Left Control", "Right Control"});
- NSView* cocoa_view = reinterpret_cast<NSView*>(view);
-
// PopulateDevices may be called on the Emuthread, so we need to ensure that
// these UI APIs are only ever called on the main thread.
if ([NSThread isMainThread])
- {
- m_windowid = [[cocoa_view window] windowNumber];
- }
+ MainThreadInitialization(view);
else
- {
- dispatch_sync(dispatch_get_main_queue(), ^{
- m_windowid = [[cocoa_view window] windowNumber];
- });
- }
+ dispatch_sync(dispatch_get_main_queue(), [this, view] { MainThreadInitialization(view); });
// cursor, with a hax for-loop
for (unsigned int i = 0; i < 4; ++i)
@@ -173,26 +226,19 @@ KeyboardAndMouse::KeyboardAndMouse(void* view)
AddInput(new Button(kCGMouseButtonCenter));
}
-void KeyboardAndMouse::UpdateInput()
-{
- CGRect bounds = CGRectZero;
- CGWindowID windowid[1] = {m_windowid};
- CFArrayRef windowArray = CFArrayCreate(nullptr, (const void**)windowid, 1, nullptr);
- CFArrayRef windowDescriptions = CGWindowListCreateDescriptionFromArray(windowArray);
- CFDictionaryRef windowDescription =
- static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windowDescriptions, 0));
-
- if (CFDictionaryContainsKey(windowDescription, kCGWindowBounds))
- {
- CFDictionaryRef boundsDictionary =
- static_cast<CFDictionaryRef>(CFDictionaryGetValue(windowDescription, kCGWindowBounds));
+// Very important that this is here
+// C++ and ObjC++ have different views of the header, and only ObjC++'s will deallocate properly
+KeyboardAndMouse::~KeyboardAndMouse() = default;
- if (boundsDictionary != nullptr)
- CGRectMakeWithDictionaryRepresentation(boundsDictionary, &bounds);
- }
+void KeyboardAndMouse::MainThreadInitialization(void* view)
+{
+ NSView* cocoa_view = (__bridge NSView*)view;
+ m_window_pos_observer = [[DolWindowPositionObserver alloc] initWithView:cocoa_view];
+}
- CFRelease(windowDescriptions);
- CFRelease(windowArray);
+void KeyboardAndMouse::UpdateInput()
+{
+ NSRect bounds = [m_window_pos_observer frame];
const double window_width = std::max(bounds.size.width, 1.0);
const double window_height = std::max(bounds.size.height, 1.0);