I am having trouble getting cursor updates with addGlobalMonitorForEventsMatchingMask and NSEventMaskCursorUpdate.
I was hoping this handler would be called when the (global) mouse cursor changes, but the handler is never called when the mouse cursor changes.
Does anyone have more information on when this can be used? Perhaps I am misunderstanding when this event is emitted.
Thanks
[NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskCursorUpdate handler:^(NSEvent *mouseEvent) {
....
}];
Related
I have a UISegmentedControl element where there are two buttons (i.e "Delete all Points" and "Delete Pt #x"). I don't want the buttons to ever remain selected so I have them set as "momentary = YES". I also don't want to handle click events until AFTER the user has released a button. The problem is, I can't figure out which of the two buttons was pressed within the UISegmentedControl view.
What I've tried:
1) I've tried using the "ValueChanged" event. The nice thing here is I can get the selected index for which button was pressed (even when momentary=YES), but the problem is that this event if triggered when the user presses down... which I don't want. I want the event when the user releases their finger, and at that I only want the event when the user releases WITHIN the button view
2) I've tried using the "Touch Up Inside" event. But it doesn't trigger any events when I tap on one of the buttons...
Any help on this would be appreciated. (Programming in Objective-C)
I'm not sure what you mean when you say "I've tried using the "Touch Up Inside" event." Unless you specify precisely what you tried, with code, that is just a meaningless phrase.
Ideally, you'd want create a method something like the following, and set it up as the button's action:
- (IBAction)myButtonTouched:(id)sender forEvent:(UIEvent *)event {
if (event.type == UIControlEventTouchUpInside) {
// do your thing
}
}
Basically you send every user event for that button to the handler and test for the one you want.
I have an application that processes keystrokes via keyDown.
This works well so far, with the exception of two problems (I'll post/ask the other later).
The problem here is the Shift+Tab combo. I would like to process it myself, but as explained in the Mac OS keyboard event doc, it is used to move the focus forward.
I tried capturing it under
-(BOOL)performKeyEquivalent:(NSEvent *)nsevent
{
}
where I do get an event for it, returning TRUE or FALSE but it still does not appear in keyDown:
I also know about selectNextKeyView: but ideally I am looking for a way to get the system to pass the combination to keyDown: for normal handling (incidentally keyUp: is called correctly for it).
-(void)selectNextKeyView:(id)sender
{
// shift+tabbed
}
Answering my own question:
I solved it by intercepting selectNextKeyView and selectPreviousKeyView and forwarding the [NSApp currentEvent] to my keyboard handler (the one that is called on keyDown: for all other keys)
-(void)selectNextKeyView:(id)sender
{
// this is part of the keyboard handling. Cocoa swallows ctrl+Tab and
// calls sselectNextKeyView, so we create a matchin key event for the occasion
NSEvent *nsevent= [NSApp currentEvent];
[self handleKeyEvent:nsevent isRaw:FALSE isUp:FALSE];
}
-(void)selectPreviousKeyView:(id)sender
{
// this is part of the keyboard handling. Cocoa swallows ctrl+shift+Tab and
// calls selectPreviousKeyView, so we create a matchin key event for the occasion
NSEvent *nsevent= [NSApp currentEvent];
[self handleKeyEvent:nsevent isRaw:FALSE isUp:FALSE];
}
I have an IBAction which should, when activated, wait until the mouse is clicked and then print the location. How do I do that properly? My attempt:
BOOL finished = NO;
while (!finished) {
if ([NSEvent pressedMouseButtons] == 1) {
finished = YES;
NSLog(#"%f | %f", [NSEvent mouseLocation].x, [NSEvent mouseLocation].y);
}
}
does work but will show a busy mouse pointer. So I guess there must be a much better way.
Both the IBaction and Click events occur on a Main Thread only. It seems you are blocking the main thread with a while loop in IBAction until the mouse click happens, which is like putting the Main thread busy.
You should run this while loop in a secondary thread so that Main thread will be free of this while loop checking.
I have an NSComboBox. I've set an action selector. When the box gets hidden the selector fires, even if the user never touched it. Yes, I need to hide it.
IBOutlet NSComboBox *comboBox;
[comboBox setAction:#selector(onComboBoxSelection:)];
- (void)onComboBoxSelection:(id)sender
{
NSLog(#"Why does this fire twice");
//My code doesn't actually set hidden here, it's just for proof while debugging the issue.
[comboBox setHidden:YES];
}
Why would hiding an NSControl fire it's selector? What's the best way to fix it?
Update:
I've fixed it by wrapping the method. But I'd still like to understand why, or other ways to fix it.
- (void)onComboBoxSelection:(id)sender
{
if(![sender isHidden]{
NSLog(#"Now only fires once");
//My code doesn't actually set hidden here, it's just for proof while debugging the issue.
[comboBox setHidden:YES];
}
}
Set a breakpoint in onComboBoxSelection: and look at the backtrace when it's called the second time (type bt in the debugger to see the backtrace). That will explain what's going.
A combo box is both a text field and a popup, and it will fire actions for both. The text field action is fired when editing ends, either by hitting the Return key or when it resigns first responder (e.g., tabbing out to another field).
When you hide the combo box, the text field resigns first responder and fires its action.
What you probably want to do is check if combo box value has actually changed, and only then proceed with hiding the combo box, etc.
Another option is to use data bindings to observe changes to the combo box. Bind the combo box value to a property on your controller. Then implement the property setter in your controller.
try this [comboBox setHidden:1];
I have simple global monitor for mouse clicks:
[NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask handler:^(NSEvent *event){
if ([event type] == NSLeftMouseDown) {
[self mouseDown];
if (self.lockMouse) {
// Cancel event
}
}
}];
Is there any way to cancel global mouse events, so clicking only notifies my app?
I.e.: After clicking on any button on screen (that don't belong to my app) while "locked", event goes here, but not to button that was below cursor. Something like event.preventDefault() in JavaScript.
Not with this API, no. From the documentation, it says that the block is:
The event handler block object. It is passed the event to monitor. You are unable to change the event, merely observe it.
If you want to intercept the event and prevent it from propagating, you need to use a CGEventTap instead.