cocoa - screen not refreshing after CGEventPost mouse click
I am programatically generating mouse clicks when a user clicks a certain keyboard key (CapsLock). So I do a left mouse down when CapsLock is switched on, then a left mouse up when CapsLock is switched off.
This behaves correctly in that if I for example place the mouse over a window title bar, click CapsLock, then move the mouse, then click CapsLock, the window correctly moves. i.e. I correctly 'drag' the window as if I had held the left mouse button down whilst moving the mou开发者_开发知识库se.
However there is one problem - the window does not move whilst I am moving the mouse, it only moves to the final position after I have clicked CapsLock a second time. i.e. after I have 'released' the mouse button.
What do I need to do to ensure the screen is refreshed during the mouse move?
Interestingly, I also hooked to
[NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDraggedMask
and found that my NSLog statement only output after I released the left mouse button (the real left mouse button)
Mouse click code is below, I can post all the code if necessary, there isn't much of it..
// simulate mouse down
// get current mouse pos
CGEventRef ourEvent = CGEventCreate(NULL);
CGPoint point = CGEventGetLocation(ourEvent);
NSLog(@"Location? x= %f, y = %f", (float)point.x, (float)point.y);
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef theEvent = CGEventCreateMouseEvent(source, kCGEventLeftMouseDown, point, kCGMouseButtonLeft);
CGEventSetType(theEvent, kCGEventLeftMouseDown);
CGEventPost(kCGHIDEventTap, theEvent);
CFRelease(theEvent);
// simulate mouse up
// get current mouse pos
CGEventRef ourEvent = CGEventCreate(NULL);
CGPoint point = CGEventGetLocation(ourEvent);
NSLog(@"Location? x= %f, y = %f", (float)point.x, (float)point.y);
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef theEvent = CGEventCreateMouseEvent(source, kCGEventLeftMouseUp, point, kCGMouseButtonLeft);
CGEventSetType(theEvent, kCGEventLeftMouseUp);
CGEventPost(kCGHIDEventTap, theEvent);
CFRelease(theEvent);
If you want to be able to drag windows, the problem is that you also need to post a LeftMouseDragged
event.
Simply call beginEventMonitoring
to start listening for caps lock key events and mouse move events. The event handlers will simulate a left mouse press and movement just as you wanted. Here is a link to my blog where you can download a full working example for Xcode 4: http://www.jakepetroules.com/2011/06/25/simulating-mouse-events-in-cocoa
The example is in the public domain, do whatever you like with it. :)
According to Apple (NSEvent documentation), "Enable access for assistive devices" needs to be checked in System Preferences > Universal Access for this to work, but I have it unchecked and it wasn't an issue. Just a heads up.
Please let me know if you have any further issues and I will try my best to help.
// Begin listening for caps lock key presses and mouse movements
- (void)beginEventMonitoring
{
// Determines whether the caps lock key was initially down before we started listening for events
wasCapsLockDown = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_CapsLock);
capsLockEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSFlagsChangedMask) handler: ^(NSEvent *event)
{
// Determines whether the caps lock key was pressed and posts a mouse down or mouse up event depending on its state
bool isCapsLockDown = [event modifierFlags] & NSAlphaShiftKeyMask;
if (isCapsLockDown && !wasCapsLockDown)
{
[self simulateMouseEvent: kCGEventLeftMouseDown];
wasCapsLockDown = true;
}
else if (wasCapsLockDown)
{
[self simulateMouseEvent: kCGEventLeftMouseUp];
wasCapsLockDown = false;
}
}];
mouseMovementEventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSMouseMovedMask) handler:^(NSEvent *event)
{
[self simulateMouseEvent: kCGEventLeftMouseDragged];
}];
}
// Cease listening for caps lock key presses and mouse movements
- (void)endEventMonitoring
{
if (capsLockEventMonitor)
{
[NSEvent removeMonitor: capsLockEventMonitor];
capsLockEventMonitor = nil;
}
if (mouseMovementEventMonitor)
{
[NSEvent removeMonitor: mouseMovementEventMonitor];
mouseMovementEventMonitor = nil;
}
}
-(void)simulateMouseEvent:(CGEventType)eventType
{
// Get the current mouse position
CGEventRef ourEvent = CGEventCreate(NULL);
CGPoint mouseLocation = CGEventGetLocation(ourEvent);
// Create and post the event
CGEventRef event = CGEventCreateMouseEvent(CGEventSourceCreate(kCGEventSourceStateHIDSystemState), eventType, mouseLocation, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
}
精彩评论