Tkabber

Changes On Branch optimize_chat_roster
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch optimize_chat_roster Excluding Merge-Ins

This is equivalent to a diff from 04a7caac75 to 140aba8b35

2025-04-17
05:02
Merge optimization of chat rosters. check-in: f00591d976 user: sgolovan tags: trunk
04:58
Update ChangeLog. Leaf check-in: 140aba8b35 user: sgolovan tags: optimize_chat_roster
2025-04-16
13:57
* chats.tcl, plugins/chat/nick_colors.tcl: Cache the groupchat roster and not rebuild it every time it needs to be redrawn. check-in: 42aabdc9b0 user: sgolovan tags: optimize_chat_roster
2025-04-14
16:42
Add debug prints to collect info on chat roster redraws. check-in: 9ac74b784c user: sgolovan tags: optimize_chat_roster
2025-04-13
19:54
Do not override border widths and roster item placement indents (adapt theme examples to high DPI displays). Define colors for spinbox arrow buttons. check-in: 04a7caac75 user: sgolovan tags: trunk
18:38
Fix undefined priority for a light theme. Add missing roster background definitions for the unix default theme. check-in: 62c6f7a8f7 user: sgolovan tags: trunk

Changes to ChangeLog.





1
2
3
4
5
6
7





2025-04-13  Sergei Golovan  <sgolovan@nes.ru>

	* plugins/unix/tktray.tcl: Add a workaround for a race condition in
	  Tcl 9 when the configure events for size of the tray icon come in
	  incorrect order.

	* tkabber.tcl: Determine by creating a text window whether the Tk
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
2025-04-16  Sergei Golovan  <sgolovan@nes.ru>

	* chats.tcl, plugins/chat/nick_colors.tcl: Cache the groupchat roster
	  and not rebuild it every time it needs to be redrawn.

2025-04-13  Sergei Golovan  <sgolovan@nes.ru>

	* plugins/unix/tktray.tcl: Add a workaround for a race condition in
	  Tcl 9 when the configure events for size of the tray icon come in
	  incorrect order.

	* tkabber.tcl: Determine by creating a text window whether the Tk
Changes to chats.tcl.
440
441
442
443
444
445
446










447
448
449
450
451
452
453
    }

    hook::run open_chat_pre_hook $chatid $type

    set chats(type,$chatid) $type
    set chats(subject,$chatid) ""
    set chats(exit_status,$chatid) ""










    add_to_opened $chatid

    set chat_id($cw) $chatid

    lassign [chat::window_titles $chatid] chats(tabtitlename,$chatid) \
        chats(titlename,$chatid)








>
>
>
>
>
>
>
>
>
>







440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    }

    hook::run open_chat_pre_hook $chatid $type

    set chats(type,$chatid) $type
    set chats(subject,$chatid) ""
    set chats(exit_status,$chatid) ""

    if {$type eq "groupchat"} {
        # Variable to hold groupchat roster items

        set chats(roster,$chatid) [dict create moderator {} \
                                               participant {} \
                                               visitor {} \
                                               user {}]
    }

    add_to_opened $chatid

    set chat_id($cw) $chatid

    lassign [chat::window_titles $chatid] chats(tabtitlename,$chatid) \
        chats(titlename,$chatid)

1106
1107
1108
1109
1110
1111
1112


1113
1114

1115


1116
























1117
1118
1119




















1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
}

hook::add client_presence_hook chat::change_presence 70

###############################################################################

proc chat::process_roster_event {chatid jid nick status args} {


    debugmsg chat "ROSTER: $chatid $jid $nick $status"


    if {[string equal $nick ""]} return



























    chat::redraw_roster_after_idle $chatid
}





















namespace eval chat {
    variable g2l
    array set g2l [list 1 [::msgcat::mc "Moderators"] \
                        2 [::msgcat::mc "Participants"] \
                        3 [::msgcat::mc "Visitors"] \
                        4 [::msgcat::mc "Users"]]
}

proc chat::redraw_roster {chatid} {
    variable g2l


    set userswin [users_win $chatid]

    if {![winfo exists $userswin]} return

    ifacetk::roster::clear $userswin 0

    set xlib [get_xlib $chatid]
    set group [get_jid $chatid]

    set levels {}
    foreach nick [::muc::roster $chatid] {
        set jid $group/$nick
        set role [::muc::get_role $xlib $jid]

        switch -- $role {
            moderator   {set level 1}
            participant {set level 2}
            visitor     {set level 3}
            default     {set level 4}
        }
        lappend levels $level
        lappend levelusers($level) [list $jid $nick]

    }
    set levels [lsort -unique $levels]

    foreach level $levels {
        ifacetk::roster::addline $userswin group \
            "$g2l($level) ([llength $levelusers($level)])" $level $level {} 0

        foreach item [lsort -index 1 -dictionary $levelusers($level)] {
            lassign $item jid nick
            set status [get_user_status $xlib $jid]

            if {$::plugins::nickcolors::options(use_colored_roster_nicks)} {
                set foreground [plugins::nickcolors::get_color $nick]
            } else {
                set foreground [ifacetk::roster::get_foreground $status]
            }
            ifacetk::roster::addline $userswin jid $nick \
                [list $xlib $jid] $level {} 0 \
                {} roster/user/$status $foreground
        }
    }

    ifacetk::roster::update_scrollregion $userswin
}

proc chat::redraw_roster_after_idle {group} {
    variable afterid

    if {[info exists afterid($group)]} \
        return

    set afterid($group) [after idle "
        chat::redraw_roster [list $group]
        unset [list ::chat::afterid($group)]
    "]
}

proc chat::restore_subject {chatid} {
    variable chats

    set sw [winid $chatid].status.subject







>
>
|

>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|
|
|




>








<

<
|
<
<
|
<
|
<
<
<
<
<
|
>
|
<
<
<
|
<

<
|
<
|
<
<
<
<
|
|
<
|






|


|


|
|
|







1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197

1198

1199


1200

1201





1202
1203
1204



1205

1206

1207

1208




1209
1210

1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
}

hook::add client_presence_hook chat::change_presence 70

###############################################################################

proc chat::process_roster_event {chatid jid nick status args} {
    variable chats

    debugmsg chat "ROSTER: $chatid $jid $nick $status $args"

    if {$nick eq ""} return

    foreach role {moderator participant visitor user} {
        dict unset chats(roster,$chatid) $role $nick
    }

    if {$status ne "unavailable"} {
        set role user
        array set tmp $args
        switch -- $tmp(-role) {
            moderator -
            participant -
            visitor {
                set role $tmp(-role)
            }
            default {
                set role user
            }
        }

        if {$::plugins::nickcolors::options(use_colored_roster_nicks)} {
            set foreground [plugins::nickcolors::get_color $nick]
        } else {
            set foreground [ifacetk::roster::get_foreground $status]
        }

        dict set chats(roster,$chatid) $role $nick [list $jid $status $foreground]
    }

    chat::redraw_roster_after_idle $chatid
}

proc chat::update_roster_foregrounds {chatid} {
    variable chats

    foreach role {moderator participant visitor user} {
        dict for {nick val} [dict get $chats(roster,$chatid) $role] {
            lassign $val jid status foreground

            if {$::plugins::nickcolors::options(use_colored_roster_nicks)} {
                set foreground [plugins::nickcolors::get_color $nick]
            } else {
                set foreground [ifacetk::roster::get_foreground $status]
            }

            dict set chats(roster,$chatid) $role $nick [list $jid $status $foreground]
        }
    }

    chat::redraw_roster_after_idle $chatid
}

namespace eval chat {
    variable g2l
    array set g2l [list moderator   [::msgcat::mc "Moderators"] \
                        participant [::msgcat::mc "Participants"] \
                        visitor     [::msgcat::mc "Visitors"] \
                        user        [::msgcat::mc "Users"]]
}

proc chat::redraw_roster {chatid} {
    variable g2l
    variable chats

    set userswin [users_win $chatid]

    if {![winfo exists $userswin]} return

    ifacetk::roster::clear $userswin 0

    set xlib [get_xlib $chatid]



    foreach role {moderator participant visitor user} {


        set users [lsort -dictionary [dict keys [dict get $chats(roster,$chatid) $role]]]

        set nusers [llength $users]





        if {$nusers == 0} {
            continue
        }



        ifacetk::roster::addline $userswin group "$g2l($role) ($nusers)" $role $role {} 0



        foreach nick $users {

            lassign [dict get $chats(roster,$chatid) $role $nick] jid status foreground





            ifacetk::roster::addline $userswin jid $nick [list $xlib $jid] $role {} 0 \

                                     {} roster/user/$status $foreground
        }
    }

    ifacetk::roster::update_scrollregion $userswin
}

proc chat::redraw_roster_after_idle {chatid} {
    variable afterid

    if {[info exists afterid($chatid)]} \
        return

    set afterid($chatid) [after idle "
        chat::redraw_roster [list $chatid]
        unset [list ::chat::afterid($chatid)]
    "]
}

proc chat::restore_subject {chatid} {
    variable chats

    set sw [winid $chatid].status.subject
Changes to plugins/chat/nick_colors.tcl.
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    variable options
    variable NicksInChat

    foreach chatid [chat::opened] {
        set wn [chat::chat_win $chatid]
        if {[winfo exists $wn]} {
            if {[chat::is_groupchat $chatid]} {
                chat::redraw_roster_after_idle $chatid
            }
            foreach nick $NicksInChat($chatid) {
                set clr [get_color $nick]
                $wn tag configure NICK-$nick \
                    -foreground [expr {$options(use_colored_nicks) ? $clr : ""}]
                $wn tag configure NICKMSG-$nick \
                    -foreground [expr {$options(use_colored_nicks) ? $clr : ""}]







|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    variable options
    variable NicksInChat

    foreach chatid [chat::opened] {
        set wn [chat::chat_win $chatid]
        if {[winfo exists $wn]} {
            if {[chat::is_groupchat $chatid]} {
                chat::update_roster_foregrounds $chatid
            }
            foreach nick $NicksInChat($chatid) {
                set clr [get_color $nick]
                $wn tag configure NICK-$nick \
                    -foreground [expr {$options(use_colored_nicks) ? $clr : ""}]
                $wn tag configure NICKMSG-$nick \
                    -foreground [expr {$options(use_colored_nicks) ? $clr : ""}]