|  | @@ -266,11 +266,11 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
 | 
	
		
			
			| 266 | 266 |        RenderZefyrParagraph paragraph = box.child;
 | 
	
		
			
			| 267 | 267 |        if (_scope.controller.getStyleForSelection(selection).contains(NotusAttribute.link)) {
 | 
	
		
			
			| 268 | 268 |          // 当前点击的是link
 | 
	
		
			
			| 269 |  | -        var position = paragraph.getRenderBoxPositionForOffset(localPoint);
 | 
	
		
			
			| 270 |  | -        // 第一个字符和最后一个字符将不触发onTap
 | 
	
		
			
			|  | 269 | +        var spanPosition = paragraph.getRenderBoxPositionForOffset(localPoint);
 | 
	
		
			
			|  | 270 | +        // // 第一个字符和最后一个字符将不触发onTap
 | 
	
		
			
			| 271 | 271 |          final TextSpan span = paragraph.text.getSpanForPosition(TextPosition(
 | 
	
		
			
			| 272 |  | -          offset: position.offset == 0 ? position.offset - 1 : position.offset + 1,
 | 
	
		
			
			| 273 |  | -          affinity: position.affinity,
 | 
	
		
			
			|  | 272 | +          offset: spanPosition.offset == 0 ? spanPosition.offset - 1 : spanPosition.offset + 1,
 | 
	
		
			
			|  | 273 | +          affinity: spanPosition.affinity,
 | 
	
		
			
			| 274 | 274 |          ));
 | 
	
		
			
			| 275 | 275 |          final recognizer = (span?.recognizer as TapGestureRecognizer);
 | 
	
		
			
			| 276 | 276 |          if (recognizer != null) {
 | 
	
	
		
			
			|  | @@ -310,13 +310,32 @@ class _ZefyrSelectionOverlayState extends State<ZefyrSelectionOverlay>
 | 
	
		
			
			| 310 | 310 |      _longPressPosition = null;
 | 
	
		
			
			| 311 | 311 |      HitTestResult result = HitTestResult();
 | 
	
		
			
			| 312 | 312 |      WidgetsBinding.instance.hitTest(result, globalPoint);
 | 
	
		
			
			| 313 |  | -    final box = _getEditableBox(result);
 | 
	
		
			
			|  | 313 | +    RenderEditableProxyBox box = _getEditableBox(result);
 | 
	
		
			
			| 314 | 314 |      if (box == null) {
 | 
	
		
			
			| 315 | 315 |        return;
 | 
	
		
			
			| 316 | 316 |      }
 | 
	
		
			
			| 317 | 317 |      final localPoint = box.globalToLocal(globalPoint);
 | 
	
		
			
			| 318 | 318 |      final position = box.getPositionForOffset(localPoint);
 | 
	
		
			
			| 319 |  | -    final word = box.getWordBoundary(position);
 | 
	
		
			
			|  | 319 | +    var word = box.getWordBoundary(position);
 | 
	
		
			
			|  | 320 | +    
 | 
	
		
			
			|  | 321 | +    if (box?.child is RenderZefyrParagraph) {
 | 
	
		
			
			|  | 322 | +      RenderZefyrParagraph paragraph = box.child;
 | 
	
		
			
			|  | 323 | +      if (_scope.controller.getStyleForSelection(TextSelection.collapsed(
 | 
	
		
			
			|  | 324 | +          offset: position.offset,
 | 
	
		
			
			|  | 325 | +          affinity: position.affinity,
 | 
	
		
			
			|  | 326 | +        )).contains(NotusAttribute.link)) {
 | 
	
		
			
			|  | 327 | +        // 当前点击的是link
 | 
	
		
			
			|  | 328 | +        var spanPosition = paragraph.getRenderBoxPositionForOffset(localPoint);
 | 
	
		
			
			|  | 329 | +        // // 第一个字符和最后一个字符将不触发onTap
 | 
	
		
			
			|  | 330 | +        final TextSpan span = paragraph.text.getSpanForPosition(TextPosition(
 | 
	
		
			
			|  | 331 | +          offset: spanPosition.offset == 0 ? spanPosition.offset - 1 : spanPosition.offset + 1,
 | 
	
		
			
			|  | 332 | +          affinity: spanPosition.affinity,
 | 
	
		
			
			|  | 333 | +        ));
 | 
	
		
			
			|  | 334 | +        if (span != null) {
 | 
	
		
			
			|  | 335 | +          word = paragraph.getRenderBoxWordBoundary(span.text.length);
 | 
	
		
			
			|  | 336 | +        }
 | 
	
		
			
			|  | 337 | +      }
 | 
	
		
			
			|  | 338 | +    }
 | 
	
		
			
			| 320 | 339 |      final selection = TextSelection(
 | 
	
		
			
			| 321 | 340 |        baseOffset: word.start,
 | 
	
		
			
			| 322 | 341 |        extentOffset: word.end,
 | 
	
	
		
			
			|  | @@ -489,16 +508,22 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver>
 | 
	
		
			
			| 489 | 508 |          alignment: Alignment.topLeft,
 | 
	
		
			
			| 490 | 509 |          width: interactiveRect.width,
 | 
	
		
			
			| 491 | 510 |          height: interactiveRect.height,
 | 
	
		
			
			| 492 |  | -        child: RawGestureDetector(
 | 
	
		
			
			|  | 511 | +        child: 
 | 
	
		
			
			|  | 512 | +        //  RawGestureDetector(
 | 
	
		
			
			|  | 513 | +        //   behavior: HitTestBehavior.translucent,
 | 
	
		
			
			|  | 514 | +        //   gestures: <Type, GestureRecognizerFactory>{
 | 
	
		
			
			|  | 515 | +        //     CustomPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<
 | 
	
		
			
			|  | 516 | +        //         CustomPanGestureRecognizer>(
 | 
	
		
			
			|  | 517 | +        //       () => CustomPanGestureRecognizer(
 | 
	
		
			
			|  | 518 | +        //           onPanDown: _handleDragStart, onPanUpdate: _handleDragUpdate),
 | 
	
		
			
			|  | 519 | +        //       (CustomPanGestureRecognizer instance) {},
 | 
	
		
			
			|  | 520 | +        //     ),
 | 
	
		
			
			|  | 521 | +        //   },
 | 
	
		
			
			|  | 522 | +        GestureDetector(
 | 
	
		
			
			| 493 | 523 |            behavior: HitTestBehavior.translucent,
 | 
	
		
			
			| 494 |  | -          gestures: <Type, GestureRecognizerFactory>{
 | 
	
		
			
			| 495 |  | -            CustomPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<
 | 
	
		
			
			| 496 |  | -                CustomPanGestureRecognizer>(
 | 
	
		
			
			| 497 |  | -              () => CustomPanGestureRecognizer(
 | 
	
		
			
			| 498 |  | -                  onPanDown: _handleDragStart, onPanUpdate: _handleDragUpdate),
 | 
	
		
			
			| 499 |  | -              (CustomPanGestureRecognizer instance) {},
 | 
	
		
			
			| 500 |  | -            ),
 | 
	
		
			
			| 501 |  | -          },
 | 
	
		
			
			|  | 524 | +          dragStartBehavior: DragStartBehavior.start,
 | 
	
		
			
			|  | 525 | +          onPanStart: _handleDragStart,
 | 
	
		
			
			|  | 526 | +          onPanUpdate: _handleDragUpdate,
 | 
	
		
			
			| 502 | 527 |            child: Padding(
 | 
	
		
			
			| 503 | 528 |              padding: EdgeInsets.only(
 | 
	
		
			
			| 504 | 529 |                left: padding.left,
 | 
	
	
		
			
			|  | @@ -548,13 +573,13 @@ class _SelectionHandleDriverState extends State<SelectionHandleDriver>
 | 
	
		
			
			| 548 | 573 |      }
 | 
	
		
			
			| 549 | 574 |    }
 | 
	
		
			
			| 550 | 575 |  
 | 
	
		
			
			| 551 |  | -  bool _handleDragStart(Offset details) {
 | 
	
		
			
			| 552 |  | -    _dragPosition = Offset(details.dx, details.dy);
 | 
	
		
			
			|  | 576 | +  bool _handleDragStart(DragStartDetails details) {
 | 
	
		
			
			|  | 577 | +    _dragPosition = details.globalPosition;
 | 
	
		
			
			| 553 | 578 |      return true;
 | 
	
		
			
			| 554 | 579 |    }
 | 
	
		
			
			| 555 | 580 |  
 | 
	
		
			
			| 556 |  | -  void _handleDragUpdate(Offset details) {
 | 
	
		
			
			| 557 |  | -    _dragPosition = Offset(details.dx, details.dy);
 | 
	
		
			
			|  | 581 | +  void _handleDragUpdate(DragUpdateDetails details) {
 | 
	
		
			
			|  | 582 | +    _dragPosition += details.delta;
 | 
	
		
			
			| 558 | 583 |      final globalPoint = _dragPosition;
 | 
	
		
			
			| 559 | 584 |      final paragraph = _scope.renderContext.boxForGlobalPoint(globalPoint);
 | 
	
		
			
			| 560 | 585 |      if (paragraph == null) {
 |