mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
NSViewComponentPeer: Tidying
This commit is contained in:
parent
4e09161986
commit
31e917ca62
2 changed files with 344 additions and 413 deletions
|
|
@ -394,7 +394,7 @@ struct ObjCClass
|
|||
BOOL b = class_addIvar (cls, name, sizeof (Type), (uint8_t) rint (log2 (sizeof (Type))), @encode (Type));
|
||||
jassert (b); ignoreUnused (b);
|
||||
}
|
||||
|
||||
|
||||
template <typename Fn>
|
||||
void addMethod (SEL selector, Fn callbackFn) { addMethod (selector, detail::toFnPtr (callbackFn)); }
|
||||
|
||||
|
|
|
|||
|
|
@ -1935,85 +1935,331 @@ struct JuceNSViewClass : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
|
|||
{
|
||||
JuceNSViewClass() : NSViewComponentPeerWrapper ("JUCEView_")
|
||||
{
|
||||
addMethod (@selector (isOpaque), isOpaque);
|
||||
addMethod (@selector (drawRect:), drawRect);
|
||||
addMethod (@selector (updateTrackingAreas), updateTrackingAreas);
|
||||
addMethod (@selector (mouseDown:), mouseDown);
|
||||
addMethod (@selector (mouseUp:), mouseUp);
|
||||
addMethod (@selector (mouseDragged:), mouseDragged);
|
||||
addMethod (@selector (mouseMoved:), mouseMoved);
|
||||
addMethod (@selector (mouseEntered:), mouseEntered);
|
||||
addMethod (@selector (mouseExited:), mouseExited);
|
||||
addMethod (@selector (rightMouseDown:), mouseDown);
|
||||
addMethod (@selector (rightMouseDragged:), mouseDragged);
|
||||
addMethod (@selector (rightMouseUp:), mouseUp);
|
||||
addMethod (@selector (otherMouseDown:), mouseDown);
|
||||
addMethod (@selector (otherMouseDragged:), mouseDragged);
|
||||
addMethod (@selector (otherMouseUp:), mouseUp);
|
||||
addMethod (@selector (scrollWheel:), scrollWheel);
|
||||
addMethod (@selector (magnifyWithEvent:), magnify);
|
||||
addMethod (@selector (acceptsFirstMouse:), acceptsFirstMouse);
|
||||
addMethod (@selector (windowWillMiniaturize:), windowWillMiniaturize);
|
||||
addMethod (@selector (windowDidDeminiaturize:), windowDidDeminiaturize);
|
||||
addMethod (@selector (windowDidChangeScreen:), windowDidChangeScreen);
|
||||
addMethod (@selector (wantsDefaultClipping), wantsDefaultClipping);
|
||||
addMethod (@selector (worksWhenModal), worksWhenModal);
|
||||
addMethod (@selector (viewDidMoveToWindow), viewDidMoveToWindow);
|
||||
addMethod (@selector (viewWillDraw), viewWillDraw);
|
||||
addMethod (@selector (keyDown:), keyDown);
|
||||
addMethod (@selector (keyUp:), keyUp);
|
||||
addMethod (@selector (insertText:), insertText);
|
||||
addMethod (@selector (doCommandBySelector:), doCommandBySelector);
|
||||
addMethod (@selector (setMarkedText:selectedRange:), setMarkedText);
|
||||
addMethod (@selector (unmarkText), unmarkText);
|
||||
addMethod (@selector (hasMarkedText), hasMarkedText);
|
||||
addMethod (@selector (conversationIdentifier), conversationIdentifier);
|
||||
addMethod (@selector (attributedSubstringFromRange:), attributedSubstringFromRange);
|
||||
addMethod (@selector (markedRange), markedRange);
|
||||
addMethod (@selector (selectedRange), selectedRange);
|
||||
addMethod (@selector (firstRectForCharacterRange:), firstRectForCharacterRange);
|
||||
addMethod (@selector (characterIndexForPoint:), characterIndexForPoint);
|
||||
addMethod (@selector (validAttributesForMarkedText), validAttributesForMarkedText);
|
||||
addMethod (@selector (flagsChanged:), flagsChanged);
|
||||
addMethod (@selector (isOpaque), [] (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner == nullptr || owner->getComponent().isOpaque();
|
||||
});
|
||||
|
||||
addMethod (@selector (becomeFirstResponder), becomeFirstResponder);
|
||||
addMethod (@selector (resignFirstResponder), resignFirstResponder);
|
||||
addMethod (@selector (acceptsFirstResponder), acceptsFirstResponder);
|
||||
addMethod (@selector (updateTrackingAreas), [] (id self, SEL)
|
||||
{
|
||||
sendSuperclassMessage<void> (self, @selector (updateTrackingAreas));
|
||||
|
||||
addMethod (@selector (draggingEntered:), draggingEntered);
|
||||
addMethod (@selector (draggingUpdated:), draggingUpdated);
|
||||
addMethod (@selector (draggingEnded:), draggingEnded);
|
||||
addMethod (@selector (draggingExited:), draggingExited);
|
||||
addMethod (@selector (prepareForDragOperation:), prepareForDragOperation);
|
||||
addMethod (@selector (performDragOperation:), performDragOperation);
|
||||
addMethod (@selector (concludeDragOperation:), concludeDragOperation);
|
||||
resetTrackingArea (static_cast<NSView*> (self));
|
||||
});
|
||||
|
||||
addMethod (@selector (paste:), paste);
|
||||
addMethod (@selector (copy:), copy);
|
||||
addMethod (@selector (cut:), cut);
|
||||
addMethod (@selector (selectAll:), selectAll);
|
||||
addMethod (@selector (becomeFirstResponder), [] (id self, SEL)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusGain);
|
||||
return YES;
|
||||
});
|
||||
|
||||
addMethod (@selector (viewWillMoveToWindow:), willMoveToWindow);
|
||||
addMethod (@selector (resignFirstResponder), [] (id self, SEL)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusLoss);
|
||||
return YES;
|
||||
});
|
||||
|
||||
addMethod (@selector (isAccessibilityElement), getIsAccessibilityElement);
|
||||
addMethod (@selector (accessibilityChildren), getAccessibilityChildren);
|
||||
addMethod (@selector (accessibilityHitTest:), accessibilityHitTest);
|
||||
addMethod (@selector (accessibilityFocusedUIElement), getAccessibilityFocusedUIElement);
|
||||
addMethod (NSViewComponentPeer::dismissModalsSelector, [] (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::dismissModals); });
|
||||
addMethod (NSViewComponentPeer::frameChangedSelector, [] (id self, SEL, NSNotification*) { callOnOwner (self, &NSViewComponentPeer::redirectMovedOrResized); });
|
||||
addMethod (NSViewComponentPeer::becomeKeySelector, [] (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::becomeKey); });
|
||||
addMethod (NSViewComponentPeer::resignKeySelector, [] (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::resignKey); });
|
||||
|
||||
// deprecated methods required for backwards compatibility
|
||||
addMethod (@selector (accessibilityIsIgnored), getAccessibilityIsIgnored);
|
||||
addMethod (@selector (accessibilityAttributeValue:), getAccessibilityAttributeValue);
|
||||
addMethod (@selector (paste:), [] (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectPaste, s); });
|
||||
addMethod (@selector (copy:), [] (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCopy, s); });
|
||||
addMethod (@selector (cut:), [] (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCut, s); });
|
||||
addMethod (@selector (selectAll:), [] (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectSelectAll, s); });
|
||||
|
||||
addMethod (@selector (isFlipped), isFlipped);
|
||||
addMethod (@selector (viewWillMoveToWindow:), [] (id self, SEL, NSWindow* w) { callOnOwner (self, &NSViewComponentPeer::redirectWillMoveToWindow, w); });
|
||||
|
||||
addMethod (@selector (drawRect:), [] (id self, SEL, NSRect r) { callOnOwner (self, &NSViewComponentPeer::drawRect, r); });
|
||||
addMethod (@selector (viewDidMoveToWindow), [] (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::viewMovedToWindow); });
|
||||
addMethod (@selector (flagsChanged:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectModKeyChange, ev); });
|
||||
addMethod (@selector (mouseMoved:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseMove, ev); });
|
||||
addMethod (@selector (mouseEntered:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseEnter, ev); });
|
||||
addMethod (@selector (mouseExited:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseExit, ev); });
|
||||
addMethod (@selector (scrollWheel:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseWheel, ev); });
|
||||
addMethod (@selector (magnifyWithEvent:), [] (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMagnify, ev); });
|
||||
|
||||
addMethod (@selector (mouseDragged:), mouseDragged);
|
||||
addMethod (@selector (rightMouseDragged:), mouseDragged);
|
||||
addMethod (@selector (otherMouseDragged:), mouseDragged);
|
||||
|
||||
addMethod (NSViewComponentPeer::dismissModalsSelector, dismissModals);
|
||||
addMethod (NSViewComponentPeer::asyncMouseDownSelector, asyncMouseDown);
|
||||
addMethod (NSViewComponentPeer::asyncMouseUpSelector, asyncMouseUp);
|
||||
addMethod (NSViewComponentPeer::frameChangedSelector, frameChanged);
|
||||
addMethod (NSViewComponentPeer::becomeKeySelector, becomeKey);
|
||||
addMethod (NSViewComponentPeer::resignKeySelector, resignKey);
|
||||
|
||||
addMethod (@selector (performKeyEquivalent:), performKeyEquivalent);
|
||||
addMethod (@selector (mouseDown:), mouseDown);
|
||||
addMethod (@selector (rightMouseDown:), mouseDown);
|
||||
addMethod (@selector (otherMouseDown:), mouseDown);
|
||||
|
||||
addMethod (@selector (mouseUp:), mouseUp);
|
||||
addMethod (@selector (rightMouseUp:), mouseUp);
|
||||
addMethod (@selector (otherMouseUp:), mouseUp);
|
||||
|
||||
addMethod (@selector (draggingEntered:), draggingUpdated);
|
||||
addMethod (@selector (draggingUpdated:), draggingUpdated);
|
||||
|
||||
addMethod (@selector (draggingEnded:), draggingExited);
|
||||
addMethod (@selector (draggingExited:), draggingExited);
|
||||
|
||||
addMethod (@selector (acceptsFirstMouse:), [] (id, SEL, NSEvent*) { return YES; });
|
||||
|
||||
addMethod (@selector (windowWillMiniaturize:), [] (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
{
|
||||
if (p->isAlwaysOnTop)
|
||||
{
|
||||
// there is a bug when restoring minimised always on top windows so we need
|
||||
// to remove this behaviour before minimising and restore it afterwards
|
||||
p->setAlwaysOnTop (false);
|
||||
p->wasAlwaysOnTop = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (windowDidDeminiaturize:), [] (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
{
|
||||
if (p->wasAlwaysOnTop)
|
||||
p->setAlwaysOnTop (true);
|
||||
|
||||
p->redirectMovedOrResized();
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (windowDidChangeScreen:), [] (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
p->windowDidChangeScreen();
|
||||
});
|
||||
|
||||
addMethod (@selector (wantsDefaultClipping), [] (id, SEL) { return YES; }); // (this is the default, but may want to customise it in future)
|
||||
|
||||
addMethod (@selector (worksWhenModal), [] (id self, SEL)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
return p->worksWhenModal();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
addMethod (@selector (viewWillDraw), [] (id self, SEL)
|
||||
{
|
||||
// Without setting contentsFormat macOS Big Sur will always set the invalid area
|
||||
// to be the entire frame.
|
||||
#if defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
|
||||
if (@available (macOS 10.12, *))
|
||||
{
|
||||
CALayer* layer = ((NSView*) self).layer;
|
||||
layer.contentsFormat = kCAContentsFormatRGBA8Uint;
|
||||
}
|
||||
#endif
|
||||
|
||||
sendSuperclassMessage<void> (self, @selector (viewWillDraw));
|
||||
});
|
||||
|
||||
addMethod (@selector (keyDown:), [] (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
auto* target = owner->findCurrentTextInputTarget();
|
||||
owner->textWasInserted = false;
|
||||
|
||||
if (target != nullptr)
|
||||
[(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];
|
||||
else
|
||||
owner->stringBeingComposed.clear();
|
||||
|
||||
if (! (owner->textWasInserted || owner->redirectKeyDown (ev)))
|
||||
sendSuperclassMessage<void> (self, @selector (keyDown:), ev);
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (keyUp:), [] (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
|
||||
if (! owner->redirectKeyUp (ev))
|
||||
sendSuperclassMessage<void> (self, @selector (keyUp:), ev);
|
||||
});
|
||||
|
||||
addMethod (@selector (insertText:), [] (id self, SEL, id aString)
|
||||
{
|
||||
// This commits multi-byte text when return is pressed, or after every keypress for western keyboards
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString;
|
||||
|
||||
if ([newText length] > 0)
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
target->insertTextAtCaret (nsStringToJuce (newText));
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
owner->stringBeingComposed.clear();
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (doCommandBySelector:), [] (id, SEL, SEL) {});
|
||||
|
||||
addMethod (@selector (setMarkedText:selectedRange:), [] (id self, SEL, id aString, NSRange)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]]
|
||||
? [aString string] : aString);
|
||||
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
auto currentHighlight = target->getHighlightedRegion();
|
||||
target->insertTextAtCaret (owner->stringBeingComposed);
|
||||
target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (unmarkText), [] (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (owner->stringBeingComposed.isNotEmpty())
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
target->insertTextAtCaret (owner->stringBeingComposed);
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
|
||||
owner->stringBeingComposed.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addMethod (@selector (hasMarkedText), [] (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->stringBeingComposed.isNotEmpty();
|
||||
});
|
||||
|
||||
addMethod (@selector (conversationIdentifier), [] (id self, SEL)
|
||||
{
|
||||
return (long) (pointer_sized_int) self;
|
||||
});
|
||||
|
||||
addMethod (@selector (attributedSubstringFromRange:), [] (id self, SEL, NSRange theRange) -> NSAttributedString*
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
Range<int> r ((int) theRange.location,
|
||||
(int) (theRange.location + theRange.length));
|
||||
|
||||
return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (r))] autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
});
|
||||
|
||||
addMethod (@selector (markedRange), [] (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
if (owner->stringBeingComposed.isNotEmpty())
|
||||
return NSMakeRange (0, (NSUInteger) owner->stringBeingComposed.length());
|
||||
|
||||
return NSMakeRange (NSNotFound, 0);
|
||||
});
|
||||
|
||||
addMethod (@selector (selectedRange), [] (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
auto highlight = target->getHighlightedRegion();
|
||||
|
||||
if (! highlight.isEmpty())
|
||||
return NSMakeRange ((NSUInteger) highlight.getStart(),
|
||||
(NSUInteger) highlight.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
return NSMakeRange (NSNotFound, 0);
|
||||
});
|
||||
|
||||
addMethod (@selector (firstRectForCharacterRange:), [] (id self, SEL, NSRange)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
if (auto* comp = dynamic_cast<Component*> (owner->findCurrentTextInputTarget()))
|
||||
return flippedScreenRect (makeNSRect (comp->getScreenBounds()));
|
||||
|
||||
return NSZeroRect;
|
||||
});
|
||||
|
||||
addMethod (@selector (characterIndexForPoint:), [] (id, SEL, NSPoint) { return NSNotFound; });
|
||||
|
||||
addMethod (@selector (validAttributesForMarkedText), [] (id, SEL) { return [NSArray array]; });
|
||||
|
||||
addMethod (@selector (acceptsFirstResponder), [] (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->canBecomeKeyWindow();
|
||||
});
|
||||
|
||||
addMethod (@selector (prepareForDragOperation:), [] (id, SEL, id<NSDraggingInfo>) { return YES; });
|
||||
|
||||
addMethod (@selector (performDragOperation:), [] (id self, SEL, id<NSDraggingInfo> sender)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->sendDragCallback (&NSViewComponentPeer::handleDragDrop, sender);
|
||||
});
|
||||
|
||||
addMethod (@selector (concludeDragOperation:), [] (id, SEL, id<NSDraggingInfo>) {});
|
||||
|
||||
addMethod (@selector (isAccessibilityElement), [] (id, SEL) { return NO; });
|
||||
|
||||
addMethod (@selector (accessibilityChildren), getAccessibilityChildren);
|
||||
|
||||
addMethod (@selector (accessibilityHitTest:), [] (id self, SEL, NSPoint point)
|
||||
{
|
||||
return [getAccessibleChild (self) accessibilityHitTest: point];
|
||||
});
|
||||
|
||||
addMethod (@selector (accessibilityFocusedUIElement), [] (id self, SEL)
|
||||
{
|
||||
return [getAccessibleChild (self) accessibilityFocusedUIElement];
|
||||
});
|
||||
|
||||
// deprecated methods required for backwards compatibility
|
||||
addMethod (@selector (accessibilityIsIgnored), [] (id, SEL) { return YES; });
|
||||
|
||||
addMethod (@selector (accessibilityAttributeValue:), [] (id self, SEL, NSString* attribute) -> id
|
||||
{
|
||||
if ([attribute isEqualToString: NSAccessibilityChildrenAttribute])
|
||||
return getAccessibilityChildren (self, {});
|
||||
|
||||
return sendSuperclassMessage<id> (self, @selector (accessibilityAttributeValue:), attribute);
|
||||
});
|
||||
|
||||
addMethod (@selector (isFlipped), [] (id, SEL) { return true; });
|
||||
|
||||
addMethod (@selector (performKeyEquivalent:), [] (id self, SEL s, NSEvent* event)
|
||||
{
|
||||
// We try passing shortcut keys to the currently focused component first.
|
||||
// If the component doesn't want the event, we'll fall back to the superclass
|
||||
// implementation, which will pass the event to the main menu.
|
||||
if (tryPassingKeyEventToPeer (event))
|
||||
return YES;
|
||||
|
||||
return sendSuperclassMessage<BOOL> (self, s, event);
|
||||
});
|
||||
|
||||
addProtocol (@protocol (NSTextInput));
|
||||
|
||||
|
|
@ -2028,6 +2274,35 @@ private:
|
|||
resetTrackingArea (static_cast<NSView*> (self));
|
||||
}
|
||||
|
||||
static bool tryPassingKeyEventToPeer (NSEvent* e)
|
||||
{
|
||||
if ([e type] != NSEventTypeKeyDown && [e type] != NSEventTypeKeyUp)
|
||||
return false;
|
||||
|
||||
if (auto* focused = Component::getCurrentlyFocusedComponent())
|
||||
{
|
||||
if (auto* peer = dynamic_cast<NSViewComponentPeer*> (focused->getPeer()))
|
||||
{
|
||||
return [e type] == NSEventTypeKeyDown ? peer->redirectKeyDown (e)
|
||||
: peer->redirectKeyUp (e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Func, typename... Args>
|
||||
static void callOnOwner (id self, Func&& func, Args&&... args)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
(owner->*func) (std::forward<Args> (args)...);
|
||||
}
|
||||
|
||||
static void mouseDragged (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDrag, ev); }
|
||||
static void asyncMouseDown (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDown, ev); }
|
||||
static void asyncMouseUp (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseUp, ev); }
|
||||
static void draggingExited (id self, SEL, id<NSDraggingInfo> sender) { callOnOwner (self, &NSViewComponentPeer::sendDragCallback, &NSViewComponentPeer::handleDragExit, sender); }
|
||||
|
||||
static void mouseDown (id self, SEL s, NSEvent* ev)
|
||||
{
|
||||
if (JUCEApplicationBase::isStandaloneApp())
|
||||
|
|
@ -2062,263 +2337,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
static void asyncMouseDown (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDown, ev); }
|
||||
static void asyncMouseUp (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseUp, ev); }
|
||||
static void mouseDragged (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseDrag, ev); }
|
||||
static void mouseMoved (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseMove, ev); }
|
||||
static void mouseEntered (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseEnter, ev); }
|
||||
static void mouseExited (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseExit, ev); }
|
||||
static void scrollWheel (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMouseWheel, ev); }
|
||||
static void magnify (id self, SEL, NSEvent* ev) { callOnOwner (self, &NSViewComponentPeer::redirectMagnify, ev); }
|
||||
static void copy (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCopy, s); }
|
||||
static void paste (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectPaste, s); }
|
||||
static void cut (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectCut, s); }
|
||||
static void selectAll (id self, SEL, NSObject* s) { callOnOwner (self, &NSViewComponentPeer::redirectSelectAll, s); }
|
||||
static void willMoveToWindow (id self, SEL, NSWindow* w) { callOnOwner (self, &NSViewComponentPeer::redirectWillMoveToWindow, w); }
|
||||
|
||||
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }
|
||||
static BOOL wantsDefaultClipping (id, SEL) { return YES; } // (this is the default, but may want to customise it in future)
|
||||
static BOOL worksWhenModal (id self, SEL) { if (auto* p = getOwner (self)) return p->worksWhenModal(); return NO; }
|
||||
|
||||
static void drawRect (id self, SEL, NSRect r) { callOnOwner (self, &NSViewComponentPeer::drawRect, r); }
|
||||
static void frameChanged (id self, SEL, NSNotification*) { callOnOwner (self, &NSViewComponentPeer::redirectMovedOrResized); }
|
||||
static void viewDidMoveToWindow (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::viewMovedToWindow); }
|
||||
static void dismissModals (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::dismissModals); }
|
||||
static void becomeKey (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::becomeKey); }
|
||||
static void resignKey (id self, SEL) { callOnOwner (self, &NSViewComponentPeer::resignKey); }
|
||||
|
||||
static BOOL isFlipped (id, SEL) { return true; }
|
||||
|
||||
static void viewWillDraw (id self, SEL)
|
||||
{
|
||||
// Without setting contentsFormat macOS Big Sur will always set the invalid area
|
||||
// to be the entire frame.
|
||||
#if defined (MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12
|
||||
if (@available (macOS 10.12, *))
|
||||
{
|
||||
CALayer* layer = ((NSView*) self).layer;
|
||||
layer.contentsFormat = kCAContentsFormatRGBA8Uint;
|
||||
}
|
||||
#endif
|
||||
|
||||
sendSuperclassMessage<void> (self, @selector (viewWillDraw));
|
||||
}
|
||||
|
||||
static void windowWillMiniaturize (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
{
|
||||
if (p->isAlwaysOnTop)
|
||||
{
|
||||
// there is a bug when restoring minimised always on top windows so we need
|
||||
// to remove this behaviour before minimising and restore it afterwards
|
||||
p->setAlwaysOnTop (false);
|
||||
p->wasAlwaysOnTop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void windowDidDeminiaturize (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
{
|
||||
if (p->wasAlwaysOnTop)
|
||||
p->setAlwaysOnTop (true);
|
||||
|
||||
p->redirectMovedOrResized();
|
||||
}
|
||||
}
|
||||
|
||||
static void windowDidChangeScreen (id self, SEL, NSNotification*)
|
||||
{
|
||||
if (auto* p = getOwner (self))
|
||||
p->windowDidChangeScreen();
|
||||
}
|
||||
|
||||
static BOOL isOpaque (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner == nullptr || owner->getComponent().isOpaque();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static void keyDown (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
auto* target = owner->findCurrentTextInputTarget();
|
||||
owner->textWasInserted = false;
|
||||
|
||||
if (target != nullptr)
|
||||
[(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];
|
||||
else
|
||||
owner->stringBeingComposed.clear();
|
||||
|
||||
if (! (owner->textWasInserted || owner->redirectKeyDown (ev)))
|
||||
sendSuperclassMessage<void> (self, @selector (keyDown:), ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyUp (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
|
||||
if (! owner->redirectKeyUp (ev))
|
||||
sendSuperclassMessage<void> (self, @selector (keyUp:), ev);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static void insertText (id self, SEL, id aString)
|
||||
{
|
||||
// This commits multi-byte text when return is pressed, or after every keypress for western keyboards
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString;
|
||||
|
||||
if ([newText length] > 0)
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
target->insertTextAtCaret (nsStringToJuce (newText));
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
}
|
||||
|
||||
owner->stringBeingComposed.clear();
|
||||
}
|
||||
}
|
||||
|
||||
static void doCommandBySelector (id, SEL, SEL) {}
|
||||
|
||||
static void setMarkedText (id self, SEL, id aString, NSRange)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]]
|
||||
? [aString string] : aString);
|
||||
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
auto currentHighlight = target->getHighlightedRegion();
|
||||
target->insertTextAtCaret (owner->stringBeingComposed);
|
||||
target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void unmarkText (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (owner->stringBeingComposed.isNotEmpty())
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
target->insertTextAtCaret (owner->stringBeingComposed);
|
||||
owner->textWasInserted = true;
|
||||
}
|
||||
|
||||
owner->stringBeingComposed.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL hasMarkedText (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->stringBeingComposed.isNotEmpty();
|
||||
}
|
||||
|
||||
static long conversationIdentifier (id self, SEL)
|
||||
{
|
||||
return (long) (pointer_sized_int) self;
|
||||
}
|
||||
|
||||
static NSAttributedString* attributedSubstringFromRange (id self, SEL, NSRange theRange)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
Range<int> r ((int) theRange.location,
|
||||
(int) (theRange.location + theRange.length));
|
||||
|
||||
return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (r))] autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static NSRange markedRange (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
if (owner->stringBeingComposed.isNotEmpty())
|
||||
return NSMakeRange (0, (NSUInteger) owner->stringBeingComposed.length());
|
||||
|
||||
return NSMakeRange (NSNotFound, 0);
|
||||
}
|
||||
|
||||
static NSRange selectedRange (id self, SEL)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
{
|
||||
if (auto* target = owner->findCurrentTextInputTarget())
|
||||
{
|
||||
auto highlight = target->getHighlightedRegion();
|
||||
|
||||
if (! highlight.isEmpty())
|
||||
return NSMakeRange ((NSUInteger) highlight.getStart(),
|
||||
(NSUInteger) highlight.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
return NSMakeRange (NSNotFound, 0);
|
||||
}
|
||||
|
||||
static NSRect firstRectForCharacterRange (id self, SEL, NSRange)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
if (auto* comp = dynamic_cast<Component*> (owner->findCurrentTextInputTarget()))
|
||||
return flippedScreenRect (makeNSRect (comp->getScreenBounds()));
|
||||
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
static NSUInteger characterIndexForPoint (id, SEL, NSPoint) { return NSNotFound; }
|
||||
static NSArray* validAttributesForMarkedText (id, SEL) { return [NSArray array]; }
|
||||
|
||||
//==============================================================================
|
||||
static void flagsChanged (id self, SEL, NSEvent* ev)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::redirectModKeyChange, ev);
|
||||
}
|
||||
|
||||
static BOOL becomeFirstResponder (id self, SEL)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusGain);
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL resignFirstResponder (id self, SEL)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::viewFocusLoss);
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL acceptsFirstResponder (id self, SEL)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->canBecomeKeyWindow();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static NSDragOperation draggingEntered (id self, SEL s, id<NSDraggingInfo> sender)
|
||||
{
|
||||
return draggingUpdated (self, s, sender);
|
||||
}
|
||||
|
||||
static NSDragOperation draggingUpdated (id self, SEL, id<NSDraggingInfo> sender)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
|
|
@ -2328,97 +2346,10 @@ private:
|
|||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
static void draggingEnded (id self, SEL s, id<NSDraggingInfo> sender)
|
||||
{
|
||||
draggingExited (self, s, sender);
|
||||
}
|
||||
|
||||
static void draggingExited (id self, SEL, id<NSDraggingInfo> sender)
|
||||
{
|
||||
callOnOwner (self, &NSViewComponentPeer::sendDragCallback, &NSViewComponentPeer::handleDragExit, sender);
|
||||
}
|
||||
|
||||
static BOOL prepareForDragOperation (id, SEL, id<NSDraggingInfo>)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
static BOOL performDragOperation (id self, SEL, id<NSDraggingInfo> sender)
|
||||
{
|
||||
auto* owner = getOwner (self);
|
||||
return owner != nullptr && owner->sendDragCallback (&NSViewComponentPeer::handleDragDrop, sender);
|
||||
}
|
||||
|
||||
static void concludeDragOperation (id, SEL, id<NSDraggingInfo>) {}
|
||||
|
||||
//==============================================================================
|
||||
static BOOL getIsAccessibilityElement (id, SEL)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
static NSArray* getAccessibilityChildren (id self, SEL)
|
||||
{
|
||||
return NSAccessibilityUnignoredChildrenForOnlyChild (getAccessibleChild (self));
|
||||
}
|
||||
|
||||
static id accessibilityHitTest (id self, SEL, NSPoint point)
|
||||
{
|
||||
return [getAccessibleChild (self) accessibilityHitTest: point];
|
||||
}
|
||||
|
||||
static id getAccessibilityFocusedUIElement (id self, SEL)
|
||||
{
|
||||
return [getAccessibleChild (self) accessibilityFocusedUIElement];
|
||||
}
|
||||
|
||||
static BOOL getAccessibilityIsIgnored (id, SEL)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
static id getAccessibilityAttributeValue (id self, SEL, NSString* attribute)
|
||||
{
|
||||
if ([attribute isEqualToString: NSAccessibilityChildrenAttribute])
|
||||
return getAccessibilityChildren (self, {});
|
||||
|
||||
return sendSuperclassMessage<id> (self, @selector (accessibilityAttributeValue:), attribute);
|
||||
}
|
||||
|
||||
static bool tryPassingKeyEventToPeer (NSEvent* e)
|
||||
{
|
||||
if ([e type] != NSEventTypeKeyDown && [e type] != NSEventTypeKeyUp)
|
||||
return false;
|
||||
|
||||
if (auto* focused = Component::getCurrentlyFocusedComponent())
|
||||
{
|
||||
if (auto* peer = dynamic_cast<NSViewComponentPeer*> (focused->getPeer()))
|
||||
{
|
||||
return [e type] == NSEventTypeKeyDown ? peer->redirectKeyDown (e)
|
||||
: peer->redirectKeyUp (e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static BOOL performKeyEquivalent (id self, SEL s, NSEvent* event)
|
||||
{
|
||||
// We try passing shortcut keys to the currently focused component first.
|
||||
// If the component doesn't want the event, we'll fall back to the superclass
|
||||
// implementation, which will pass the event to the main menu.
|
||||
if (tryPassingKeyEventToPeer (event))
|
||||
return YES;
|
||||
|
||||
return sendSuperclassMessage<BOOL> (self, s, event);
|
||||
}
|
||||
|
||||
template <typename Func, typename... Args>
|
||||
static void callOnOwner (id self, Func&& func, Args&&... args)
|
||||
{
|
||||
if (auto* owner = getOwner (self))
|
||||
(owner->*func) (std::forward<Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue