diff mbox series

git-gui: keep showing selection when diff view gets deactivated on Mac

Message ID 20201130201837.19091-2-stefan@haller-berlin.de (mailing list archive)
State New, archived
Headers show
Series git-gui: keep showing selection when diff view gets deactivated on Mac | expand

Commit Message

Stefan Haller Nov. 30, 2020, 8:18 p.m. UTC
On Mac, Tk text widgets don't draw the selection when they are inactive and
disabled [1]. This causes the diff selection to disappear on Mac when the diff
view loses focus.

To work around that, we configure text views to be enabled when they become
deactivated. While this feels wrong, there's not problem with it because as soon
as the user tries to interact with the view, the first thing that happens is
that it gets disabled again.

[1] https://github.com/tcltk/tk/blob/main/generic/tkTextDisp.c#L847

Signed-off-by: Stefan Haller <stefan@haller-berlin.de>
---
 lib/themed.tcl | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

--
2.29.0.21.g59e7d82785.dirty
diff mbox series

Patch

diff --git a/lib/themed.tcl b/lib/themed.tcl
index db49085..eeb5bf8 100644
--- a/lib/themed.tcl
+++ b/lib/themed.tcl
@@ -302,6 +302,38 @@  proc tspinbox {w args} {
 	}
 }

+proc focus_text {w} {
+	global text_states
+
+	[winfo parent $w] state focus
+
+	if {[is_MacOSX]} {
+		# Restore the disabled state that we remembered for this widget when it
+		# got deactivated last. If there's no remembered state, then this is the
+		# first time we are being activated right after construction, and
+		# there's no need to change the state.
+		if {[info exists text_states($w)]} {
+			$w configure -state $text_states($w)
+			unset text_states($w)
+		}
+	}
+}
+
+proc unfocus_text {w} {
+	global text_states
+
+	[winfo parent $w] state !focus
+
+	if {[is_MacOSX]} {
+		# On Mac, the selection is not drawn when a text widget is inactive and
+		# disabled. To work around that, set the disabled state back to normal
+		# when deactivating the widget. Remember the disabled state so that we
+		# can restore it when we become active again.
+		set text_states($w) [lindex [$w configure -state] end]
+		$w configure -state normal
+	}
+}
+
 # Create a text widget with any theme specific properties.
 proc ttext {w args} {
 	global use_ttk
@@ -315,8 +347,8 @@  proc ttext {w args} {
 	set w [eval [linsert $args 0 text $w]]
 	if {$use_ttk} {
 		if {[winfo class [winfo parent $w]] eq "EntryFrame"} {
-			bind $w <FocusIn> {[winfo parent %W] state focus}
-			bind $w <FocusOut> {[winfo parent %W] state !focus}
+			bind $w <FocusIn> {focus_text %W}
+			bind $w <FocusOut> {unfocus_text %W}
 		}
 	}
 	return $w