11import 'dart:math' ;
22
3+ import 'package:flutter/foundation.dart' ;
34import 'package:flutter/gestures.dart' ;
45import 'package:flutter/material.dart' ;
56import 'package:flutter/services.dart' ;
@@ -365,11 +366,16 @@ class _CodeFieldState extends State<CodeField> {
365366
366367 textStyle = defaultTextStyle.merge (widget.textStyle);
367368
368- // Adjust textStyle to have consistent line height
369- // This is a key fix for Chrome selection issues
369+ // Get Chrome-specific text selection fixes
370+ final chromeTextSelectionFixes = getChromeTextSelectionFixes ();
371+ final useCustomSelectionStyle = chromeTextSelectionFixes['useCustomSelectionStyle' ] as bool ;
372+
373+ // Adjust textStyle to have consistent line height and Chrome-specific fixes
370374 final adjustedTextStyle = textStyle.copyWith (
371- height: getLineHeight (), // Use the function instead of constant
372- leadingDistribution: TextLeadingDistribution .even, // Added for consistent text baselines
375+ height: getLineHeight (),
376+ leadingDistribution: useCustomSelectionStyle
377+ ? chromeTextSelectionFixes['leadingDistribution' ] as TextLeadingDistribution
378+ : TextLeadingDistribution .proportional,
373379 );
374380
375381 final codeField = TextField (
@@ -382,16 +388,18 @@ class _CodeFieldState extends State<CodeField> {
382388 expands: widget.expands,
383389 scrollController: _codeScroll,
384390 keyboardType: widget.keyboardType,
385- selectionControls: MaterialTextSelectionControls (),
386- decoration: const InputDecoration (
391+ selectionControls: kIsWeb ? DesktopTextSelectionControls () : MaterialTextSelectionControls (),
392+ decoration: InputDecoration (
387393 isCollapsed: true ,
388- // Add more vertical padding to help with line selection
389- contentPadding: EdgeInsets .symmetric (vertical: 16 ),
394+ // Add vertical padding - adjust based on selection fixes
395+ contentPadding: EdgeInsets .symmetric (
396+ vertical: useCustomSelectionStyle ? 14.0 : 16.0 ,
397+ ),
390398 disabledBorder: InputBorder .none,
391399 border: InputBorder .none,
392400 focusedBorder: InputBorder .none,
393401 ),
394- textAlignVertical: TextAlignVertical .top, // Align text at the top for better matching
402+ textAlignVertical: TextAlignVertical .top,
395403 cursorColor: widget.cursorColor ?? defaultTextStyle.color,
396404 cursorHeight: widget.cursorHeight,
397405 autocorrect: false ,
@@ -413,14 +421,7 @@ class _CodeFieldState extends State<CodeField> {
413421
414422 final editingField = Theme (
415423 data: Theme .of (context).copyWith (
416- textSelectionTheme: widget.textSelectionTheme ??
417- TextSelectionThemeData (
418- // Use a more pronounced and distinguishable selection color
419- // This helps with Chrome's selection rendering
420- selectionColor: Theme .of (context).colorScheme.primary.withOpacity (0.5 ),
421- cursorColor: widget.cursorColor ?? defaultTextStyle.color,
422- selectionHandleColor: Theme .of (context).colorScheme.primary,
423- ),
424+ textSelectionTheme: _getTextSelectionTheme (context),
424425 ),
425426 child: LayoutBuilder (
426427 builder: (BuildContext context, BoxConstraints constraints) {
@@ -457,14 +458,20 @@ class _CodeFieldState extends State<CodeField> {
457458 final lineNumberSize = textStyle.fontSize;
458459 final lineNumberColor = widget.gutterStyle.textStyle? .color ?? textStyle.color? .withOpacity (.5 );
459460
461+ // Get Chrome-specific text selection fixes
462+ final chromeTextSelectionFixes = getChromeTextSelectionFixes ();
463+ final useCustomSelectionStyle = chromeTextSelectionFixes['useCustomSelectionStyle' ] as bool ;
464+
460465 // Ensure same text style properties for consistent line height
461466 final lineNumberTextStyle = (widget.gutterStyle.textStyle ?? textStyle).copyWith (
462467 color: lineNumberColor,
463468 fontFamily: textStyle.fontFamily,
464469 fontSize: lineNumberSize,
465- height: getLineHeight (), // Use the function instead of constant
470+ height: getLineHeight (),
466471 // Add additional properties to ensure metrics consistency
467- leadingDistribution: TextLeadingDistribution .even,
472+ leadingDistribution: useCustomSelectionStyle
473+ ? chromeTextSelectionFixes['leadingDistribution' ] as TextLeadingDistribution
474+ : TextLeadingDistribution .proportional,
468475 );
469476
470477 final gutterStyle = widget.gutterStyle.copyWith (
@@ -548,9 +555,11 @@ class _CodeFieldState extends State<CodeField> {
548555 return renderBox.localToGlobal (Offset .zero);
549556 }
550557
551- // Instead of calculating line position based on newlines,
552- // we'll use the TextPainter's getOffsetForCaret method which
553- // properly accounts for text wrapping
558+ // Get Chrome-specific text selection fixes
559+ final chromeTextSelectionFixes = getChromeTextSelectionFixes ();
560+ final useCustomSelectionStyle = chromeTextSelectionFixes['useCustomSelectionStyle' ] as bool ;
561+ final selectionHeightFix = useCustomSelectionStyle ?
562+ (chromeTextSelectionFixes['selectionHeightFix' ] as bool ? ?? false ) : false ;
554563
555564 // Create a text painter for the entire text
556565 final fullTextPainter = TextPainter (
@@ -576,15 +585,21 @@ class _CodeFieldState extends State<CodeField> {
576585
577586 // Apply scroll offsets
578587 final double adjustedX = rawOffset.dx - horizontalScrollOffset;
579- final double adjustedY = rawOffset.dy - scrollY;
588+ double adjustedY = rawOffset.dy - scrollY;
589+
590+ // Apply Chrome-specific vertical adjustment if needed
591+ if (selectionHeightFix) {
592+ // This small offset helps Chrome render selections correctly without changing line height
593+ adjustedY += 2.0 ;
594+ }
580595
581596 // Convert to global coordinates
582597 return renderBox.localToGlobal (Offset (adjustedX, adjustedY));
583598 }
584599
585600 double getLineHeight () {
586- // Default line height multiple if not specified in the style
587- return getChromeLineHeight () ?? ( textStyle.height ?? 1.2 ) ;
601+ // Use a consistent line height that looks good ( not the special Chrome value)
602+ return textStyle.height ?? 1.2 ;
588603 }
589604
590605 void _onPopupStateChanged () {
@@ -639,4 +654,27 @@ class _CodeFieldState extends State<CodeField> {
639654 }
640655 }
641656 }
657+
658+ TextSelectionThemeData _getTextSelectionTheme (BuildContext context) {
659+ final chromeTextSelectionFixes = getChromeTextSelectionFixes ();
660+ final useCustomSelectionStyle = chromeTextSelectionFixes['useCustomSelectionStyle' ] as bool ;
661+
662+ // Create a more optimized selection style for Chrome
663+ if (useCustomSelectionStyle) {
664+ return widget.textSelectionTheme ??
665+ TextSelectionThemeData (
666+ selectionColor: Theme .of (context).colorScheme.primary.withOpacity (0.3 ),
667+ cursorColor: widget.cursorColor ?? textStyle.color,
668+ selectionHandleColor: Theme .of (context).colorScheme.primary,
669+ );
670+ }
671+
672+ // Default selection style for other browsers
673+ return widget.textSelectionTheme ??
674+ TextSelectionThemeData (
675+ selectionColor: Theme .of (context).colorScheme.primary.withOpacity (0.5 ),
676+ cursorColor: widget.cursorColor ?? textStyle.color,
677+ selectionHandleColor: Theme .of (context).colorScheme.primary,
678+ );
679+ }
642680}
0 commit comments