From 88189dd7cb535486b74bcf50997253797f4b999c Mon Sep 17 00:00:00 2001 From: Michael Rappazzo Date: Sat, 13 Sep 2025 07:31:51 -0400 Subject: [PATCH 01/15] gitk: fix error when remote tracking branch is deleted When a remote tracking branch is deleted (e.g., via 'git push --delete origin branch'), the headids array entry for that branch is removed, but upstreamofref may still reference it. This causes gitk to show an error and prevents the Tags and Heads view from opening. Fix by checking that headids($upstreamofref($n)) exists before accessing it in the refill_reflist function. Signed-off-by: Michael Rappazzo Signed-off-by: Johannes Sixt --- gitk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 080192820e..fc502fbd68 100755 --- a/gitk +++ b/gitk @@ -10332,7 +10332,9 @@ proc refill_reflist {} { if {![string match "remotes/*" $n] && [string match $reflistfilter $n]} { if {[commitinview $headids($n) $curview]} { lappend localrefs [list $n H] - if {[info exists upstreamofref($n)] && [commitinview $headids($upstreamofref($n)) $curview]} { + if {[info exists upstreamofref($n)] && \ + [info exists headids($upstreamofref($n))] && \ + [commitinview $headids($upstreamofref($n)) $curview]} { lappend trackedremoterefs [list $upstreamofref($n) R] } } else { From 9611ef554d17b067195b6fa363bb59add39ab0d2 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Tue, 24 Jul 2018 02:51:20 -0400 Subject: [PATCH 02/15] gitk: fix MacOS 10.14 "Mojave" crash on launch On MacOS, a "wish" application started from the terminal opens in the background, thus doesn't match user expectation that a newly-launched application ought to be placed in the foreground. To address this shortcoming, both gitk and git-gui use Apple Events to send a message to "System Events" instructing it to foreground the "wish" application by PID. Unfortunately, MacOS 10.14 tightens restrictions on Apple Events, requiring explicit granting of permission to control applications in this fashion, and apparently such granting for "Automation" is not allowed at all[1]. As a consequence gitk crashes outright at launch time with a "Not authorized to send Apple events to System Events" error, thus is entirely unusable on "Mojave". In contrast, git-gui does not crash since it deliberately[2] catches and ignores Apple Events errors. This does mean that git-gui will not automatically become the foreground application on "Mojave", which is a minor inconvenience but far better than crashing outright as gitk does. Update gitk to catch and ignore Apple Events errors, mirroring git-gui's behavior, to avoid this crash. (Finding and implementing an alternate approach to foregrounding the "wish" application on "Mojave" may be desirable but is outside the scope of this crash fix.) [1]: https://lore.kernel.org/git/D295145E-7596-4409-9681-D8ADBB9EBB0C@me.com/ [2]: https://lore.kernel.org/git/CABNJ2G+h3zh+=wLA0KHjUn8TsfhqUK1Kn-1_=6hnXVRJUPhuuA@mail.gmail.com/ Reported-by: Evgeny Cherpak Signed-off-by: Eric Sunshine Signed-off-by: Johannes Sixt --- gitk | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gitk b/gitk index 6e4d71d585..cc2eab454c 100755 --- a/gitk +++ b/gitk @@ -12460,11 +12460,13 @@ namespace import ::msgcat::mc # on OSX bring the current Wish process window to front if {[tk windowingsystem] eq "aqua"} { - safe_exec [list osascript -e [format { - tell application "System Events" - set frontmost of processes whose unix id is %d to true - end tell - } [pid] ]] + catch { + safe_exec [list osascript -e [format { + tell application "System Events" + set frontmost of processes whose unix id is %d to true + end tell + } [pid] ]] + } } # Unset GIT_TRACE var if set From 811b8a34b9e081fdf885d83d21caa04408038889 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 21 Sep 2025 09:46:58 -0400 Subject: [PATCH 03/15] gitk: use themed spinboxes gitk uses classic (non-themed) spinboxes rather than the ttk variants. Commit d93f1713b0 ("gitk: Use themed tk widgets", 2009-04-17) that added ttk makes no mention of why ttk:spinboxes were omitted, but this leads to an inconsistent interface. Let's use the ttk version. Signed-off-by: Mark Levedahl --- gitk | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gitk b/gitk index 6e4d71d585..09df2988b4 100755 --- a/gitk +++ b/gitk @@ -2656,7 +2656,7 @@ proc makewindow {} { ttk::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: " pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap - spinbox .bleft.mid.diffcontext -width 5 \ + ttk::spinbox .bleft.mid.diffcontext -width 5 \ -from 0 -increment 1 -to 10000000 \ -validate all -validatecommand "diffcontextvalidate %P" \ -textvariable diffcontextstring @@ -11692,11 +11692,11 @@ proc prefspage_general {notebook} { grid $page.ldisp - -sticky w -pady 10 ttk::label $page.spacer -text " " ttk::label $page.maxwidthl -text [mc "Maximum graph width (lines)"] - spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth + ttk::spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w #xgettext:no-tcl-format ttk::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"] - spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct + ttk::spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct grid x $page.maxpctl $page.maxpct -sticky w ttk::checkbutton $page.showlocal -text [mc "Show local changes"] \ -variable showlocalchanges @@ -11721,17 +11721,17 @@ proc prefspage_general {notebook} { grid x $page.autoselect -sticky w } - spinbox $page.autosellen -from 1 -to $hashlength -width 4 -textvariable autosellen + ttk::spinbox $page.autosellen -from 1 -to $hashlength -width 4 -textvariable autosellen ttk::label $page.autosellenl -text [mc "Length of commit ID to copy"] grid x $page.autosellenl $page.autosellen -sticky w ttk::label $page.kscroll1 -text [mc "Wheel scrolling multiplier"] - spinbox $page.kscroll -from 1 -to 20 -width 4 -textvariable kscroll + ttk::spinbox $page.kscroll -from 1 -to 20 -width 4 -textvariable kscroll grid x $page.kscroll1 $page.kscroll -sticky w ttk::label $page.ddisp -text [mc "Diff display options"] -font mainfontbold grid $page.ddisp - -sticky w -pady 10 ttk::label $page.tabstopl -text [mc "Tab spacing"] - spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop + ttk::spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop grid x $page.tabstopl $page.tabstop -sticky w ttk::label $page.wrapcommentl -text [mc "Wrap comment text"] @@ -11746,7 +11746,7 @@ proc prefspage_general {notebook} { -variable showneartags grid x $page.ntag -sticky w ttk::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"] - spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs + ttk::spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs grid x $page.maxrefsl $page.maxrefs -sticky w ttk::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \ -variable limitdiffs From fe2005e7236a4e430ccf561376b7c14c33179064 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 21 Sep 2025 09:48:34 -0400 Subject: [PATCH 04/15] gitk: make sha1but a ttk::button gitk's 'Commit ID' button uses a classic widget, not a themed one, leading to inconsistent style. Commit 51a7e8b654 (d93f1713b0 ("gitk: Use themed tk widgets", 2009-04-17) that added themed widgets did not touch this particular widget, but does not say why. Regardless, let's use a themed button to be consistent with the rest of the interface. Signed-off-by: Mark Levedahl --- gitk | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gitk b/gitk index 09df2988b4..796933670a 100755 --- a/gitk +++ b/gitk @@ -2495,9 +2495,8 @@ proc makewindow {} { set sha1entry .tf.bar.sha1 set entries $sha1entry set sha1but .tf.bar.sha1label - button $sha1but -text "[mc "Commit ID:"] " -state disabled -relief flat \ + ttk::button $sha1but -text "[mc "Commit ID:"] " -state disabled \ -command gotocommit -width 8 - $sha1but conf -disabledforeground [$sha1but cget -foreground] pack .tf.bar.sha1label -side left ttk::entry $sha1entry -width $hashlength -font textfont -textvariable sha1string trace add variable sha1string write sha1change @@ -8910,9 +8909,9 @@ proc sha1change {n1 n2 op} { } if {[$sha1but cget -state] == $state} return if {$state == "normal"} { - $sha1but conf -state normal -relief raised -text "[mc "Goto:"] " + $sha1but conf -state normal -text "[mc "Goto:"] " } else { - $sha1but conf -state disabled -relief flat -text "[mc "Commit ID:"] " + $sha1but conf -state disabled -text "[mc "Commit ID:"] " } } From 8ccb2d4a762a0ea39c7f1df0712efbab3b7a4883 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Mon, 22 Sep 2025 10:36:41 -0400 Subject: [PATCH 05/15] gitk: use config variables to define and load a theme gitk uses themed tk, but has no capability to alter the theme defined by Tk. While there are documented ways to install other themes, and to make one the default, these methods are obscure at best. Instead, let's offer two config variables: - theme this is the name of the theme to use, and must be available. - themeloader - this is the full pathname of a tcl script that will load one or more themes into the Tk namespace. By default, theme is set to the theme active when Tk is started, and themeloader = {}. These variables must be defined to something else to have any user visible effect. Signed-off-by: Mark Levedahl --- gitk | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 796933670a..1f601153cb 100755 --- a/gitk +++ b/gitk @@ -2215,6 +2215,7 @@ proc setoptions {} { } proc setttkstyle {} { + global theme eval font configure TkDefaultFont [fontflags mainfont] eval font configure TkTextFont [fontflags textfont] eval font configure TkHeadingFont [fontflags mainfont] @@ -2224,6 +2225,10 @@ proc setttkstyle {} { eval font configure TkIconFont [fontflags uifont] eval font configure TkMenuFont [fontflags uifont] eval font configure TkSmallCaptionFont [fontflags uifont] + + if {[catch {ttk::style theme use $theme} err]} { + set theme [ttk::style theme use] + } } # Make a menu and submenus. @@ -12618,6 +12623,9 @@ set circleoutlinecolor $fgcolor set foundbgcolor yellow set currentsearchhitbgcolor orange +set theme [ttk::style theme use] +set themeloader {} + # button for popping up context menus if {[tk windowingsystem] eq "aqua" && [package vcompare $::tcl_version 8.7] < 0} { set ctxbut @@ -12701,6 +12709,8 @@ set config_variables { tagfgcolor tagoutlinecolor textfont + theme + themeloader uicolor uifgcolor uifgdisabledcolor @@ -12800,7 +12810,10 @@ set nullid "0000000000000000000000000000000000000000" set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" -setttkstyle +if {[file exists $themeloader]} { + source $themeloader +} + set appname "gitk" set runq {} @@ -12916,6 +12929,7 @@ if {[tk windowingsystem] eq "win32"} { focus -force . } +setttkstyle set_gui_colors getcommits {} From 7754656a4c8fb5c04a7304b73348ce54e1c189fa Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sat, 27 Sep 2025 08:19:08 -0400 Subject: [PATCH 06/15] gitk: do not invoke tk_setPalette gitk uses themed widgets with a user selected theme, but also invokes tk_setPalette to configure colors for the non-themed widgets including the menubar. However, themes in general are expected to configure those colors already. The builtin themes (default, alt, clam, classic on unix/X11) all have compatible colors, and need no such reconfiguration, and (most, if not all) available themes set the options database for this purpose as well. Furthermore, gitk in the past avoided invoking tk_setPalette on Windows to avoid some issues. So, let's stop calling tk_setPalette everywhere, and just rely upon the selected theme (possibly user installed) to have set all needed colors. Note: if a user installs more than one theme using $themeloader, the last one installed will have defined the colors to be used. Those colors will probably be incorrect for any other set, including Tk's builtin set. Signed-off-by: Mark Levedahl --- gitk | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/gitk b/gitk index 1f601153cb..fb42a7a913 100755 --- a/gitk +++ b/gitk @@ -11934,21 +11934,6 @@ proc setselbg {c} { allcanvs itemconf secsel -fill $c } -# This sets the background color and the color scheme for the whole UI. -# For some reason, tk_setPalette chooses a nasty dark red for selectColor -# if we don't specify one ourselves, which makes the checkbuttons and -# radiobuttons look bad. This chooses white for selectColor if the -# background color is light, or black if it is dark. -proc setui {c} { - if {[tk windowingsystem] eq "win32"} { return } - set bg [winfo rgb . $c] - set selc black - if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} { - set selc white - } - tk_setPalette background $c selectColor $selc -} - proc setbg {c} { global bglist @@ -11976,7 +11961,6 @@ proc set_gui_colors {} { global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors - setui $uicolor setbg $bgcolor setfg $fgcolor $ctext tag conf d0 -foreground [lindex $diffcolors 0] From 61c0cfe08ca56877a0537889f6d218c10f72d676 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 21 Sep 2025 15:13:54 -0400 Subject: [PATCH 07/15] gitk: use text labels for commit ID buttons gitk maintains a stack of commit ids visited, and allows navigating these using a pair of buttons shown with arrows using bitmaps. An attempt is made to recolor these bitmaps to handle different color schemes, but this is unreliable across multiple themes as the required colors are not universally known. Let's just use text labels for these buttons, allowing the themes to recolor the text along with everything else. Use utf code points for the text, presuming that these arrow glyphs are available in the selected font. Signed-off-by: Mark Levedahl --- gitk | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/gitk b/gitk index fb42a7a913..0d72621c03 100755 --- a/gitk +++ b/gitk @@ -2507,32 +2507,11 @@ proc makewindow {} { trace add variable sha1string write sha1change pack $sha1entry -side left -pady 2 - set bm_left_data { - #define left_width 16 - #define left_height 16 - static unsigned char left_bits[] = { - 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, - 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, - 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01}; - } - set bm_right_data { - #define right_width 16 - #define right_height 16 - static unsigned char right_bits[] = { - 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, - 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c, - 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01}; - } - image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor - image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor - image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor - image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor - - ttk::button .tf.bar.leftbut -command goback -state disabled -width 26 - .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray] + ttk::button .tf.bar.leftbut -command goback -state disabled + .tf.bar.leftbut configure -text \u2190 -width 3 pack .tf.bar.leftbut -side left -fill y - ttk::button .tf.bar.rightbut -command goforw -state disabled -width 26 - .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray] + ttk::button .tf.bar.rightbut -command goforw -state disabled + .tf.bar.rightbut configure -text \u2192 -width 3 pack .tf.bar.rightbut -side left -fill y ttk::label .tf.bar.rowlabel -text [mc "Row"] From 9950eff84178459a90c6047bb168659b05a998e6 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 21 Sep 2025 15:17:07 -0400 Subject: [PATCH 08/15] gitk: use text labels for next/prev search buttons gitk allows searching for commits with various criteria, and provides up/down search buttons to facilitate this search. These buttons are labelled with bitmaps, and those bitmaps are not always recolored correctly for the ui scheme as the theme colors are not known. Let's just use text labels on these, allowing the styles to handle any coloring needed. Use utf codepoints for the arrows, presuming that these code points are available in the selected font. Signed-off-by: Mark Levedahl --- gitk | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/gitk b/gitk index 0d72621c03..d2bf3f10b3 100755 --- a/gitk +++ b/gitk @@ -2542,31 +2542,8 @@ proc makewindow {} { # build up the bottom bar of upper window ttk::label .tf.lbar.flabel -text "[mc "Find"] " - set bm_down_data { - #define down_width 16 - #define down_height 16 - static unsigned char down_bits[] = { - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d, - 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}; - } - image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor - ttk::button .tf.lbar.fnext -width 26 -command {dofind 1 1} - .tf.lbar.fnext configure -image bm-down - - set bm_up_data { - #define up_width 16 - #define up_height 16 - static unsigned char up_bits[] = { - 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, - 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01}; - } - image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor - ttk::button .tf.lbar.fprev -width 26 -command {dofind -1 1} - .tf.lbar.fprev configure -image bm-up + ttk::button .tf.lbar.fnext -command {dofind 1 1} -text \u2193 -width 3 + ttk::button .tf.lbar.fprev -command {dofind -1 1} -text \u2191 -width 3 ttk::label .tf.lbar.flab2 -text " [mc "commit"] " From 1eadf0f3e065ce8967279fcb1fedc0f29f3fca2a Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Tue, 23 Sep 2025 07:48:40 -0400 Subject: [PATCH 09/15] gitk: eliminate Interface color option from gui gitk offers to change the ui color on the colors prefs page, but the variable set has no effect because gitk is using themes. Let's eliminate the "Interface" color selection option from that page. Signed-off-by: Mark Levedahl --- gitk | 5 ----- 1 file changed, 5 deletions(-) diff --git a/gitk b/gitk index d2bf3f10b3..4162a853a1 100755 --- a/gitk +++ b/gitk @@ -11741,10 +11741,6 @@ proc prefspage_colors {notebook} { ttk::label $page.cdisp -text [mc "Colors: press to choose"] -font mainfontbold grid $page.cdisp - -sticky w -pady 10 - label $page.ui -padx 40 -relief sunk -background $uicolor - ttk::button $page.uibut -text [mc "Interface"] \ - -command [list choosecolor uicolor {} $page [mc "interface"]] - grid x $page.uibut $page.ui -sticky w label $page.bg -padx 40 -relief sunk -background $bgcolor ttk::button $page.bgbut -text [mc "Background"] \ -command [list choosecolor bgcolor {} $page [mc "background"]] @@ -11788,7 +11784,6 @@ proc prefspage_set_colorswatches {page} { global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors - $page.ui configure -background $uicolor $page.bg configure -background $bgcolor $page.fg configure -background $fgcolor $page.diffold configure -background [lindex $diffcolors 0] From 83a2de9ca6bd2c191dbdfe1dc89eabb3622b8cc9 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Tue, 23 Sep 2025 07:55:21 -0400 Subject: [PATCH 10/15] gitk: eliminate unused ui color variables gitk has a number of variables used in setting up colors for the classic (non-themed) widget set. These variables are unused with ttk, so let's eliminate them. But, leave the variables in the config file for now - those can be eliminated after this change is merged. Signed-off-by: Mark Levedahl --- gitk | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gitk b/gitk index 4162a853a1..2d6a1693f6 100755 --- a/gitk +++ b/gitk @@ -2381,7 +2381,6 @@ proc makewindow {} { global highlight_files gdttype global searchstring sstring global bgcolor fgcolor bglist fglist diffcolors diffbgcolors selectbgcolor - global uifgcolor uifgdisabledcolor global filesepbgcolor filesepfgcolor global mergecolors foundbgcolor currentsearchhitbgcolor global headctxmenu progresscanv progressitem progresscoords statusw @@ -11734,7 +11733,7 @@ proc prefspage_general {notebook} { } proc prefspage_colors {notebook} { - global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor + global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors set page [create_prefs_page $notebook.colors] @@ -11781,7 +11780,7 @@ proc prefspage_colors {notebook} { } proc prefspage_set_colorswatches {page} { - global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor + global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors $page.bg configure -background $bgcolor @@ -11909,7 +11908,7 @@ proc setfg {c} { } proc set_gui_colors {} { - global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor + global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors setbg $bgcolor @@ -12508,17 +12507,11 @@ if {[tk windowingsystem] eq "aqua"} { set colors {"#00ff00" red blue magenta darkgrey brown orange} if {[tk windowingsystem] eq "win32"} { - set uicolor SystemButtonFace - set uifgcolor SystemButtonText - set uifgdisabledcolor SystemDisabledText set bgcolor SystemWindow set fgcolor SystemWindowText set selectbgcolor SystemHighlight set web_browser "cmd /c start" } else { - set uicolor grey85 - set uifgcolor black - set uifgdisabledcolor "#999" set bgcolor white set fgcolor black set selectbgcolor gray85 @@ -12560,6 +12553,9 @@ set currentsearchhitbgcolor orange set theme [ttk::style theme use] set themeloader {} +set uicolor {} +set uifgcolor {} +set uifgdisabledcolor {} # button for popping up context menus if {[tk windowingsystem] eq "aqua" && [package vcompare $::tcl_version 8.7] < 0} { From 830c4578cdc4478e3e74286bb1d007e184700ae1 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sun, 28 Sep 2025 23:04:54 -0400 Subject: [PATCH 11/15] gitk: add proc run_themeloader gitk currently accepts a single themeloader file via the config file, and will source this with errors reported to the console. This is fine for simple configuration, but will not support interactive theme exploration from the gui. In particular, a themeloader file must be sourced only once as the themes defined cannot be re-defined. Also, errors must be handled rather than just aborting while printing to the console. So, add a proc to handle the above, supporting expansion of the gui config pages. Signed-off-by: Mark Levedahl --- gitk | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 2d6a1693f6..4798ff3709 100755 --- a/gitk +++ b/gitk @@ -11861,6 +11861,23 @@ proc choose_extdiff {} { } } +proc run_themeloader {f} { + if {![info exists ::_themefiles_seen]} { + set ::_themefiles_seen [dict create] + } + + set fn [file normalize $f] + if {![dict exists $::_themefiles_seen $fn]} { + if {[catch {source $fn} err]} { + error_popup "could not interpret: $fn\n$err" + dict set ::_themefiles_seen $fn 0 + } else { + dict set ::_themefiles_seen $fn 1 + } + } + return [dict get $::_themefiles_seen $fn] +} + proc choosecolor {v vi prefspage x} { global $v @@ -12742,7 +12759,10 @@ set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" if {[file exists $themeloader]} { - source $themeloader + if {[run_themeloader $themeloader] == 0} { + puts stderr "Could not interpret themeloader: $themeloader" + exit 1 + } } set appname "gitk" From c0932eda80bce73a72d73ded74a5e618c520afb2 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Mon, 22 Sep 2025 13:15:49 -0400 Subject: [PATCH 12/15] gitk: add theme selection to color configuration page gitk allows configuring a particular theme in its configuration file (default on linux: ~/.config/git/gitk), but offers no ability to modify this from gitk's configuration editor. Let's add this to the color configuration page. Present the offered themes in a list, and allow choosing / modifying a theme definition file ($themeloader). Update the list of themes if the theme file is modified, and update the theme if specifically requested (by default, just change the value for use after gitk is restarted). Any theme definition file can change the global options database, affecting potentially any theme. So, the ultimate configuration should have either - no theme definition file (themeloader = {}), and a native Tk, theme, or - themeloader naming a valid file, and $theme naming a theme defined by that file. But, there is no trivial way to enforce the above. Shrug. Helped-by: Johannes Sixt Signed-off-by: Mark Levedahl --- gitk | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/gitk b/gitk index 4798ff3709..b23896d97a 100755 --- a/gitk +++ b/gitk @@ -11735,9 +11735,32 @@ proc prefspage_general {notebook} { proc prefspage_colors {notebook} { global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor global diffbgcolors + global themeloader set page [create_prefs_page $notebook.colors] + ttk::label $page.themesel -font mainfontbold \ + -text [mc "Themes - change requires restart"] + grid $page.themesel - -sticky w -pady 10 + ttk::label $page.themelabel -text [mc "Theme to use after restart"] + makedroplist $page.theme theme {*}[lsort [ttk::style theme names]] + grid x $page.themelabel $page.theme -sticky w + + ttk::entry $page.tloadvar -textvariable themeloader + ttk::frame $page.tloadframe + ttk::label $page.tloadframe.l -text [mc "Theme definition file"] + ttk::button $page.tloadframe.b -text [mc "Choose..."] \ + -command [list choose_themeloader $page] + pack $page.tloadframe.l $page.tloadframe.b -side left -padx 2 + pack configure $page.tloadframe.l -padx 0 + grid x $page.tloadframe $page.tloadvar -sticky ew + + ttk::label $page.themelabel2 -text \ + [mc "The theme definition file may affect all themes."] + ttk::button $page.themebut2 -text [mc "Apply theme"] \ + -command [list updatetheme $page] + grid x $page.themebut2 $page.themelabel2 -sticky w + ttk::label $page.cdisp -text [mc "Colors: press to choose"] -font mainfontbold grid $page.cdisp - -sticky w -pady 10 label $page.bg -padx 40 -relief sunk -background $bgcolor @@ -11878,6 +11901,34 @@ proc run_themeloader {f} { return [dict get $::_themefiles_seen $fn] } +proc updatetheme {prefspage {dotheme 1}} { + global theme + global themeloader + if {$themeloader ne {}} { + if {![run_themeloader $themeloader]} { + set themeloader {} + return + } else { + $prefspage.theme configure -values \ + [lsort [ttk::style theme names]] + } + } + if {$dotheme} { + ttk::style theme use $theme + set_gui_colors + prefspage_set_colorswatches $prefspage + } +} + +proc choose_themeloader {prefspage} { + global themeloader + set tfile [tk_getOpenFile -title [mc "Gitk: select theme definition"] -multiple false] + if {$tfile ne {}} { + set themeloader $tfile + updatetheme $prefspage 0 + } +} + proc choosecolor {v vi prefspage x} { global $v @@ -11949,6 +12000,7 @@ proc prefscan {} { catch {destroy $prefstop} unset prefstop fontcan + setttkstyle set_gui_colors } @@ -12759,7 +12811,7 @@ set nullid2 "0000000000000000000000000000000000000001" set nullfile "/dev/null" if {[file exists $themeloader]} { - if {[run_themeloader $themeloader] == 0} { + if {![run_themeloader $themeloader]} { puts stderr "Could not interpret themeloader: $themeloader" exit 1 } From b9f6b8237db9ebe999064e029c1b4784a7f4cfcd Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Tue, 30 Sep 2025 19:35:59 -0400 Subject: [PATCH 13/15] gitk: make configuration dialog resizing useful gitk's configuration dialog can be resized, but this does not expand the space allocated to any widgets. Some items may have long lines of text that would be visible if the widgets expanded, but this does not happen. The top-level container uses a two column grid and allocates any space change equally to both columns. However, the configuration pages are contained in one cell so half the additional space is wasted if expanding. Also, the individual configuration pages do not mark any column or widgets to expand, so any additional space given is just used as padding. Collapse the top-level page to have one column, placing the "OK" and "Cancel" buttons in a non-resizing frame in column 1 (this keeps the buttons in constant geometry as the dialog is expanded). This makes all additional space go to the configuration page. Mark column 3 of the individual pages to get all additional space, and mark the text widgets in that column so they will expand to use the space. While we're at it, eliminate or simplify use of frames to contain column 2 content, and harmonize the indents of that content. prefspage_general adds a special "spacer" label in row 2, column 1, that causes all of the subsequent rows with no column 1 content to indent, and this carries over to the next notebook tab (prefspage_color) through some undocumented feature. The fonts page has a different indent, again for unknown reason. The documented approach would be to use -padx explicitly on all the rows to set the indents. Signed-off-by: Mark Levedahl --- gitk | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/gitk b/gitk index b23896d97a..c52ffd0fc4 100755 --- a/gitk +++ b/gitk @@ -11567,9 +11567,10 @@ proc mkfontdisp {font top which} { set fontpref($font) [set $font] ttk::button $top.${font}but -text $which \ -command [list choosefont $font $which] - ttk::label $top.$font -relief flat -font $font \ - -text $fontattr($font,family) -justify left + ttk::label $top.$font -font $font \ + -text $fontattr($font,family) grid x $top.${font}but $top.$font -sticky w + grid configure $top.$font -sticky ew } proc centertext {w} { @@ -11665,11 +11666,9 @@ proc prefspage_general {notebook} { grid x $page.hideremotes -sticky w ttk::entry $page.refstohide -textvariable refstohide - ttk::frame $page.refstohidef - ttk::label $page.refstohidef.l -text [mc "Refs to hide (space-separated globs)" ] - pack $page.refstohidef.l -side left - pack configure $page.refstohidef.l -padx 10 - grid x $page.refstohidef $page.refstohide -sticky ew + ttk::label $page.refstohidel -text [mc "Refs to hide (space-separated globs)"] + grid x $page.refstohidel $page.refstohide -sticky ew + grid configure $page.refstohide -padx {0 5} ttk::checkbutton $page.autocopy -text [mc "Copy commit ID to clipboard"] \ -variable autocopy @@ -11718,16 +11717,17 @@ proc prefspage_general {notebook} { ttk::frame $page.extdifff ttk::label $page.extdifff.l -text [mc "External diff tool" ] ttk::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff - pack $page.extdifff.l $page.extdifff.b -side left - pack configure $page.extdifff.l -padx 10 + pack $page.extdifff.l -side left + pack $page.extdifff.b -side right -padx {0 5} grid x $page.extdifff $page.extdifft -sticky ew + grid configure $page.extdifft -padx {0 5} ttk::entry $page.webbrowser -textvariable web_browser - ttk::frame $page.webbrowserf - ttk::label $page.webbrowserf.l -text [mc "Web browser" ] - pack $page.webbrowserf.l -side left - pack configure $page.webbrowserf.l -padx 10 - grid x $page.webbrowserf $page.webbrowser -sticky ew + ttk::label $page.webbrowserl -text [mc "Web browser" ] + grid x $page.webbrowserl $page.webbrowser -sticky ew + grid configure $page.webbrowser -padx {0 5} + + grid columnconfigure $page 2 -weight 1 return $page } @@ -11751,9 +11751,11 @@ proc prefspage_colors {notebook} { ttk::label $page.tloadframe.l -text [mc "Theme definition file"] ttk::button $page.tloadframe.b -text [mc "Choose..."] \ -command [list choose_themeloader $page] - pack $page.tloadframe.l $page.tloadframe.b -side left -padx 2 + pack $page.tloadframe.l -side left + pack $page.tloadframe.b -side right -padx {0 5} pack configure $page.tloadframe.l -padx 0 grid x $page.tloadframe $page.tloadvar -sticky ew + grid configure $page.tloadvar -padx {0 5} ttk::label $page.themelabel2 -text \ [mc "The theme definition file may affect all themes."] @@ -11799,6 +11801,9 @@ proc prefspage_colors {notebook} { ttk::button $page.selbgbut -text [mc "Select bg"] \ -command [list choosecolor selectbgcolor {} $page [mc "background"]] grid x $page.selbgbut $page.selbgsep -sticky w + + grid columnconfigure $page 2 -weight 1 + return $page } @@ -11824,6 +11829,7 @@ proc prefspage_fonts {notebook} { mkfontdisp mainfont $page [mc "Main font"] mkfontdisp textfont $page [mc "Diff display font"] mkfontdisp uifont $page [mc "User interface font"] + grid columnconfigure $page 2 -weight 1 return $page } @@ -11858,7 +11864,7 @@ proc doprefs {} { grid rowconfigure $notebook 1 -weight 1 raise [lindex $pages 0] - grid $notebook -sticky news -padx 2 -pady 2 + grid $notebook -sticky news -padx 3 -pady 3 grid rowconfigure $top 0 -weight 1 grid columnconfigure $top 0 -weight 1 @@ -11867,11 +11873,8 @@ proc doprefs {} { ttk::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal bind $top prefsok bind $top prefscan - grid $top.buts.ok $top.buts.can - grid columnconfigure $top.buts 0 -weight 1 -uniform a - grid columnconfigure $top.buts 1 -weight 1 -uniform a - grid $top.buts - - -pady 10 -sticky ew - grid columnconfigure $top 2 -weight 1 + grid $top.buts.ok $top.buts.can -padx 20 + grid $top.buts -sticky w -pady 10 bind $top [list focus $top.buts.ok] } From 8e65d38064c6ab981955f64b75f8cc068f25a415 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Tue, 30 Sep 2025 23:28:36 -0400 Subject: [PATCH 14/15] gitk: separate code blocks for configuration dialog gitk's configuration dialog uses a large number of widgets, and this code is hard to read as there is no easily recognizable grouping or breaks. Help this by adding space between items that occupy a single row in the dialog. Signed-off-by: Mark Levedahl --- gitk | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gitk b/gitk index c52ffd0fc4..67d2dced42 100755 --- a/gitk +++ b/gitk @@ -11650,6 +11650,7 @@ proc prefspage_general {notebook} { ttk::label $page.ldisp -text [mc "Commit list display options"] -font mainfontbold grid $page.ldisp - -sticky w -pady 10 + ttk::label $page.spacer -text " " ttk::label $page.maxwidthl -text [mc "Maximum graph width (lines)"] ttk::spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth @@ -11658,9 +11659,11 @@ proc prefspage_general {notebook} { ttk::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"] ttk::spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct grid x $page.maxpctl $page.maxpct -sticky w + ttk::checkbutton $page.showlocal -text [mc "Show local changes"] \ -variable showlocalchanges grid x $page.showlocal -sticky w + ttk::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \ -variable hideremotes grid x $page.hideremotes -sticky w @@ -11673,6 +11676,7 @@ proc prefspage_general {notebook} { ttk::checkbutton $page.autocopy -text [mc "Copy commit ID to clipboard"] \ -variable autocopy grid x $page.autocopy -sticky w + if {[haveselectionclipboard]} { ttk::checkbutton $page.autoselect -text [mc "Copy commit ID to X11 selection"] \ -variable autoselect @@ -11682,12 +11686,14 @@ proc prefspage_general {notebook} { ttk::spinbox $page.autosellen -from 1 -to $hashlength -width 4 -textvariable autosellen ttk::label $page.autosellenl -text [mc "Length of commit ID to copy"] grid x $page.autosellenl $page.autosellen -sticky w + ttk::label $page.kscroll1 -text [mc "Wheel scrolling multiplier"] ttk::spinbox $page.kscroll -from 1 -to 20 -width 4 -textvariable kscroll grid x $page.kscroll1 $page.kscroll -sticky w ttk::label $page.ddisp -text [mc "Diff display options"] -font mainfontbold grid $page.ddisp - -sticky w -pady 10 + ttk::label $page.tabstopl -text [mc "Tab spacing"] ttk::spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop grid x $page.tabstopl $page.tabstop -sticky w @@ -11703,12 +11709,15 @@ proc prefspage_general {notebook} { ttk::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \ -variable showneartags grid x $page.ntag -sticky w + ttk::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"] ttk::spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs grid x $page.maxrefsl $page.maxrefs -sticky w + ttk::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \ -variable limitdiffs grid x $page.ldiff -sticky w + ttk::checkbutton $page.lattr -text [mc "Support per-file encodings"] \ -variable perfile_attrs grid x $page.lattr -sticky w @@ -11742,6 +11751,7 @@ proc prefspage_colors {notebook} { ttk::label $page.themesel -font mainfontbold \ -text [mc "Themes - change requires restart"] grid $page.themesel - -sticky w -pady 10 + ttk::label $page.themelabel -text [mc "Theme to use after restart"] makedroplist $page.theme theme {*}[lsort [ttk::style theme names]] grid x $page.themelabel $page.theme -sticky w @@ -11769,34 +11779,42 @@ proc prefspage_colors {notebook} { ttk::button $page.bgbut -text [mc "Background"] \ -command [list choosecolor bgcolor {} $page [mc "background"]] grid x $page.bgbut $page.bg -sticky w + label $page.fg -padx 40 -relief sunk -background $fgcolor ttk::button $page.fgbut -text [mc "Foreground"] \ -command [list choosecolor fgcolor {} $page [mc "foreground"]] grid x $page.fgbut $page.fg -sticky w + label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0] ttk::button $page.diffoldbut -text [mc "Diff: old lines"] \ -command [list choosecolor diffcolors 0 $page [mc "diff old lines"]] grid x $page.diffoldbut $page.diffold -sticky w + label $page.diffoldbg -padx 40 -relief sunk -background [lindex $diffbgcolors 0] ttk::button $page.diffoldbgbut -text [mc "Diff: old lines bg"] \ -command [list choosecolor diffbgcolors 0 $page [mc "diff old lines bg"]] grid x $page.diffoldbgbut $page.diffoldbg -sticky w + label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1] ttk::button $page.diffnewbut -text [mc "Diff: new lines"] \ -command [list choosecolor diffcolors 1 $page [mc "diff new lines"]] grid x $page.diffnewbut $page.diffnew -sticky w + label $page.diffnewbg -padx 40 -relief sunk -background [lindex $diffbgcolors 1] ttk::button $page.diffnewbgbut -text [mc "Diff: new lines bg"] \ -command [list choosecolor diffbgcolors 1 $page [mc "diff new lines bg"]] grid x $page.diffnewbgbut $page.diffnewbg -sticky w + label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2] ttk::button $page.hunksepbut -text [mc "Diff: hunk header"] \ -command [list choosecolor diffcolors 2 $page [mc "diff hunk header"]] grid x $page.hunksepbut $page.hunksep -sticky w + label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor ttk::button $page.markbgbut -text [mc "Marked line bg"] \ -command [list choosecolor markbgcolor {} $page [mc "marked line background"]] grid x $page.markbgbut $page.markbgsep -sticky w + label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor ttk::button $page.selbgbut -text [mc "Select bg"] \ -command [list choosecolor selectbgcolor {} $page [mc "background"]] From 6565ca82203c5926881bba95bae7c17c130b73a4 Mon Sep 17 00:00:00 2001 From: Mark Levedahl Date: Sat, 4 Oct 2025 09:57:18 -0400 Subject: [PATCH 15/15] gitk: set minimum size on configuration dialog gitk sets no size limit on its configuration dialog, allowing the user to collapse the window so almost nothing is visible. The geometry manager sets an initial size so all the widgets are visible, though ignores the potentially very long text in the entry widgets in doing so. Let's use this initial size as the minimum. The size information is computed in Tk's idle processing queue, so a wait is required. Signed-off-by: Mark Levedahl --- gitk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gitk b/gitk index 67d2dced42..9a0e6f721a 100755 --- a/gitk +++ b/gitk @@ -11894,6 +11894,10 @@ proc doprefs {} { grid $top.buts.ok $top.buts.can -padx 20 grid $top.buts -sticky w -pady 10 bind $top [list focus $top.buts.ok] + + # let geometry manager determine run, set minimum size + update idletasks + wm minsize $top [winfo reqwidth $top] [winfo reqheight $top] } proc choose_extdiff {} {