ui/cocoa: Use qemu_add_mouse_change_notifier

This eliminates the polling in cocoa_refresh and implements the
propagation of the mouse mode change from absolute to relative.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
Tested-by: Phil Dennis-Jordan <phil@philjordan.eu>
Message-ID: <20240322-mouse-v1-1-0b7d4d9bdfbf@daynix.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
Akihiko Odaki 2024-03-22 19:54:25 +09:00 committed by Philippe Mathieu-Daudé
parent 3476103689
commit e7b53d160f

View File

@ -296,6 +296,14 @@ static void handleAnyDeviceErrors(Error * err)
{
QEMUScreen screen;
pixman_image_t *pixman_image;
/* The state surrounding mouse grabbing is potentially confusing.
* isAbsoluteEnabled tracks qemu_input_is_absolute() [ie "is the emulated
* pointing device an absolute-position one?"], but is only updated on
* next refresh.
* isMouseGrabbed tracks whether GUI events are directed to the guest;
* it controls whether special keys like Cmd get sent to the guest,
* and whether we capture the mouse when in non-absolute mode.
*/
BOOL isMouseGrabbed;
BOOL isAbsoluteEnabled;
CFMachPortRef eventsTap;
@ -307,17 +315,8 @@ static void handleAnyDeviceErrors(Error * err)
- (void) handleMonitorInput:(NSEvent *)event;
- (bool) handleEvent:(NSEvent *)event;
- (bool) handleEventLocked:(NSEvent *)event;
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
/* The state surrounding mouse grabbing is potentially confusing.
* isAbsoluteEnabled tracks qemu_input_is_absolute() [ie "is the emulated
* pointing device an absolute-position one?"], but is only updated on
* next refresh.
* isMouseGrabbed tracks whether GUI events are directed to the guest;
* it controls whether special keys like Cmd get sent to the guest,
* and whether we capture the mouse when in non-absolute mode.
*/
- (void) notifyMouseModeChange;
- (BOOL) isMouseGrabbed;
- (BOOL) isAbsoluteEnabled;
- (QEMUScreen) gscreen;
- (void) raiseAllKeys;
@end
@ -404,6 +403,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
qkbd_state_switch_console(kbd, con);
dcl.con = con;
register_displaychangelistener(&dcl);
[self notifyMouseModeChange];
[self updateUIInfo];
}
@ -1109,14 +1109,26 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
[self raiseAllButtons];
}
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {
- (void) notifyMouseModeChange {
bool tIsAbsoluteEnabled = bool_with_bql(^{
return qemu_input_is_absolute(dcl.con);
});
if (tIsAbsoluteEnabled == isAbsoluteEnabled) {
return;
}
isAbsoluteEnabled = tIsAbsoluteEnabled;
if (isMouseGrabbed) {
CGAssociateMouseAndMouseCursorPosition(isAbsoluteEnabled);
if (isAbsoluteEnabled) {
[self ungrabMouse];
} else {
CGAssociateMouseAndMouseCursorPosition(isAbsoluteEnabled);
}
}
}
- (BOOL) isMouseGrabbed {return isMouseGrabbed;}
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
- (QEMUScreen) gscreen {return screen;}
/*
@ -1791,6 +1803,17 @@ static void addRemovableDevicesMenuItems(void)
qapi_free_BlockInfoList(pointerToFree);
}
static void cocoa_mouse_mode_change_notify(Notifier *notifier, void *data)
{
dispatch_async(dispatch_get_main_queue(), ^{
[cocoaView notifyMouseModeChange];
});
}
static Notifier mouse_mode_change_notifier = {
.notify = cocoa_mouse_mode_change_notify
};
@interface QemuCocoaPasteboardTypeOwner : NSObject<NSPasteboardTypeOwner>
@end
@ -1975,17 +1998,6 @@ static void cocoa_refresh(DisplayChangeListener *dcl)
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
graphic_hw_update(dcl->con);
if (qemu_input_is_absolute(dcl->con)) {
dispatch_async(dispatch_get_main_queue(), ^{
if (![cocoaView isAbsoluteEnabled]) {
if ([cocoaView isMouseGrabbed]) {
[cocoaView ungrabMouse];
}
}
[cocoaView setAbsoluteEnabled:YES];
});
}
if (cbchangecount != [[NSPasteboard generalPasteboard] changeCount]) {
qemu_clipboard_info_unref(cbinfo);
cbinfo = qemu_clipboard_info_new(&cbpeer, QEMU_CLIPBOARD_SELECTION_CLIPBOARD);
@ -2062,6 +2074,8 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
// register vga output callbacks
register_displaychangelistener(&dcl);
qemu_add_mouse_mode_change_notifier(&mouse_mode_change_notifier);
[cocoaView notifyMouseModeChange];
[cocoaView updateUIInfo];
qemu_event_init(&cbevent, false);