NSTextView: how to disable individual clicks, but still allow the choice to copy and paste?

I have a component based on NSTextView, and I would like to disable single clicks on it, so its insertion point is not affected by these single clicks, but you can still select text fragments for copy and paste

  • single clicks do nothing
  • copying and pasting is possible and does not affect the insertion point

What I want is exactly what we have in the terminal application by default: there is an insertion point, and this cannot be changed with the mouse, but text can be selected for copy and paste.

I tried looking for the method - (void)mouseDown:(NSEvent *)theEvent , but did not find anything useful.

+6
source share
1 answer

I found a hacky workaround to achieve this behavior. I created the corresponding TerminalLikeTextView class. This solution works fine, but I would still like to have a better solution: less hacker and less dependent on the internal mechanics of NSTextView, so if anyone has such a request, please share.

Key steps are:

1) Set mouseDownFlag to YES before mouse click and NO after:

 @property (assign, nonatomic) BOOL mouseDownFlag; - (void)mouseDown:(NSEvent *)theEvent { self.mouseDownFlag = YES; [super mouseDown:theEvent]; self.mouseDownFlag = NO; } 

2) To prevent the insertion point from being added early from the updateInsertionPointStateAndRestartTimer method:

 - (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag { if (self.mouseDownFlag) { return; } [super updateInsertionPointStateAndRestartTimer:flag]; } 

3) The first two steps will make the input point not move with the mouse, however the selectionRange will still change, so we need to track it:

 static const NSUInteger kCursorLocationSnapshotNotExists = NSUIntegerMax; @property (assign, nonatomic) NSUInteger cursorLocationSnapshot; #pragma mark - <NSTextViewDelegate> - (NSRange)textView:(NSTextView *)textView willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange toCharacterRange:(NSRange)newSelectedCharRange { if (self.mouseDownFlag && self.cursorLocationSnapshot == kCursorLocationSnapshotNotExists) { self.cursorLocationSnapshot = oldSelectedCharRange.location; } return newSelectedCharRange; } 

4) Attempting to print using the keys restores the location if necessary:

 - (void)keyDown:(NSEvent *)event { NSString *characters = event.characters; [self insertTextToCurrentPosition:characters]; } - (void)insertTextToCurrentPosition:(NSString *)text { if (self.cursorLocationSnapshot != kCursorLocationSnapshotNotExists) { self.selectedRange = NSMakeRange(self.cursorLocationSnapshot, 0); self.cursorLocationSnapshot = kCursorLocationSnapshotNotExists; } [self insertText:text replacementRange:NSMakeRange(self.selectedRange.location, 0)]; } 
+1
source

All Articles