diff --git a/Sources/STTextView/Extensions/NSTextLayoutManager+Helpers.swift b/Sources/STTextView/Extensions/NSTextLayoutManager+Helpers.swift index 3d8e5d9..a688ab8 100644 --- a/Sources/STTextView/Extensions/NSTextLayoutManager+Helpers.swift +++ b/Sources/STTextView/Extensions/NSTextLayoutManager+Helpers.swift @@ -84,9 +84,12 @@ extension NSTextLayoutManager { extension NSTextLayoutManager { /// Returns a location of text produced by a tap or click at the point you specify. + /// - Parameters: + /// - point: A CGPoint that represents the location of the tap or click. + /// - containerLocation: A NSTextLocation that describes the contasiner location. + /// - Returns: A location public func location(interactingAt point: CGPoint, inContainerAt containerLocation: NSTextLocation) -> NSTextLocation? { - guard let lineFragmentRange = lineFragmentRange(for: point, inContainerAt: containerLocation) - else { + guard let lineFragmentRange = lineFragmentRange(for: point, inContainerAt: containerLocation) else { return nil } diff --git a/Sources/STTextView/STTextLayoutManager.swift b/Sources/STTextView/STTextLayoutManager.swift index 1d52f51..d6e9922 100644 --- a/Sources/STTextView/STTextLayoutManager.swift +++ b/Sources/STTextView/STTextLayoutManager.swift @@ -13,9 +13,4 @@ final class STTextLayoutManager: NSTextLayoutManager { } } - // lineFragmentRange return invalid ranges FB11898356 that result in broken selection - //override func lineFragmentRange(for point: CGPoint, inContainerAt location: NSTextLocation) -> NSTextRange? { - // let textRange = super.lineFragmentRange(for: point, inContainerAt: location) - // return textRange - //} } diff --git a/Sources/STTextView/STTextView+Mouse.swift b/Sources/STTextView/STTextView+Mouse.swift index d2ff14f..21e6a05 100644 --- a/Sources/STTextView/STTextView+Mouse.swift +++ b/Sources/STTextView/STTextView+Mouse.swift @@ -43,14 +43,23 @@ extension STTextView { } } + open override func mouseUp(with event: NSEvent) { + super.mouseUp(with: event) + mouseDraggingSelectionAnchors = nil + } + open override func mouseDragged(with event: NSEvent) { if isSelectable, event.type == .leftMouseDragged, (!event.deltaY.isZero || !event.deltaX.isZero) { let point = convert(event.locationInWindow, from: nil) + if mouseDraggingSelectionAnchors == nil { + mouseDraggingSelectionAnchors = textLayoutManager.textSelections + } + updateTextSelection( interactingAt: point, - inContainerAt: textLayoutManager.documentRange.location, - anchors: textLayoutManager.textSelections, + inContainerAt: mouseDraggingSelectionAnchors?.first?.textRanges.first?.location ?? textLayoutManager.documentRange.location, + anchors: mouseDraggingSelectionAnchors!, extending: true, isDragging: true, visual: event.modifierFlags.contains(.option) diff --git a/Sources/STTextView/STTextView+Select.swift b/Sources/STTextView/STTextView+Select.swift index e80ccf3..4b7d43b 100644 --- a/Sources/STTextView/STTextView+Select.swift +++ b/Sources/STTextView/STTextView+Select.swift @@ -435,23 +435,6 @@ extension STTextView { modifiers.insert(.visual) } - // FB11898356 - // Something if wrong with textSelectionsInteractingAtPoint - // - // When drag mouse down it move text range to the previous line - // that is unexpected. This happens only when the anchor location - // is at the beginning of the line/paragraph - // - // Mouse position: (8.140625, 82.99609375) - // [NSTextSelection:<0x60000153fb10> granularity=character, affinity=upstream, transient, anchor position offset=5.000000, anchor location 512, textRanges=( - // "512...1106" - // )] - // - // Mouse position: (8.484375, 83.20703125) - // [NSTextSelection:<0x60000152f570> granularity=character, affinity=upstream, transient, anchor position offset=5.000000, anchor location 512, textRanges=( - // "511...1106" - // )] - // let selections = textLayoutManager.textSelectionNavigation.textSelections( interactingAt: point, inContainerAt: location, diff --git a/Sources/STTextView/STTextView.swift b/Sources/STTextView/STTextView.swift index dda1962..a7f9b56 100644 --- a/Sources/STTextView/STTextView.swift +++ b/Sources/STTextView/STTextView.swift @@ -20,7 +20,6 @@ import Cocoa /// A TextKit2 text view without NSTextView baggage open class STTextView: NSView, NSTextInput { - /// Posted before an object performs any operation that changes characters or formatting attributes. public static let textWillChangeNotification = NSNotification.Name("NSTextWillChangeNotification") @@ -410,6 +409,15 @@ open class STTextView: NSView, NSTextInput { } } + /// A dragging selection anchor + /// + /// FB11898356 - Something if wrong with textSelectionsInteractingAtPoint + /// it expects that the dragging operation does not change anchor selections + /// significantly. Specifically it does not play well if anchor and current + /// location is too close to each other, therefore `mouseDraggingSelectionAnchors` + /// keep the anchors unchanged while dragging. + internal var mouseDraggingSelectionAnchors: [NSTextSelection]? = nil + open override class var defaultMenu: NSMenu? { let menu = super.defaultMenu ?? NSMenu()