Tk Source Code

Check-in [83bb08d7]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:TIP #438 - <<TextLineHeightsInvalid>> event added, with corresponding new tests
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-438
Files: files | file ages | folders
SHA1: 83bb08d79338f9383b77e1710d90d3420800f321
User & Date: fvogel 2015-11-14 13:05:04
Context
2015-11-16
13:54
Merge core-8-5-branch check-in: 5b73d5ef user: jan.nijtmans tags: tip-438
2015-11-14
13:05
TIP #438 - <<TextLineHeightsInvalid>> event added, with corresponding new tests check-in: 83bb08d7 user: fvogel tags: tip-438
09:11
TIP #438 - [.text pendingyupdate] command added, with corresponding new tests check-in: f815da13 user: fvogel tags: tip-438
2015-11-10
21:03
Implementation of TIP #438 - Solution using virtual events Closed-Leaf check-in: 94b42ed3 user: fvogel tags: tip-438-events
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkTextDisp.c.

586
587
588
589
590
591
592

593
594
595
596
597
598
599
....
2925
2926
2927
2928
2929
2930
2931


2932
2933
2934
2935
2936
2937
2938
....
2953
2954
2955
2956
2957
2958
2959





































2960
2961
2962
2963
2964
2965
2966
static int		DlineXOfIndex(TkText *textPtr,
			    DLine *dlPtr, int byteIndex);
static int		TextGetScrollInfoObj(Tcl_Interp *interp,
			    TkText *textPtr, int objc,
			    Tcl_Obj *CONST objv[], double *dblPtr,
			    int *intPtr);
static void		AsyncUpdateLineMetrics(ClientData clientData);

static void		AsyncUpdateYScrollbar(ClientData clientData);
static int              IsStartOfNotMergedLine(TkText *textPtr,
                            CONST TkTextIndex *indexPtr);

/*
 * Result values returned by TextGetScrollInfoObj:
 */
................................................................................
    if (tkTextDebug) {
	char buffer[2 * TCL_INTEGER_SPACE + 1];

	sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine);
	LOG("tk_textInvalidateLine", buffer);
    }



    /*
     * If we're not in the middle of a long-line calculation (metricEpoch==-1)
     * and we've reached the last line, then we're done.
     */

    if (dInfoPtr->metricEpoch == -1
	    && lineNum == dInfoPtr->lastMetricUpdateLine) {
................................................................................
     * Re-arm the timer. We already have a refCount on the text widget so no
     * need to adjust that.
     */

    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
	    AsyncUpdateLineMetrics, (ClientData) textPtr);
}





































 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
 *
 *	This function updates the pixel height calculations of a range of






>







 







>
>







 







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







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
....
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
....
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
static int		DlineXOfIndex(TkText *textPtr,
			    DLine *dlPtr, int byteIndex);
static int		TextGetScrollInfoObj(Tcl_Interp *interp,
			    TkText *textPtr, int objc,
			    Tcl_Obj *CONST objv[], double *dblPtr,
			    int *intPtr);
static void		AsyncUpdateLineMetrics(ClientData clientData);
static void		GenerateTextLineHeightsInvalidEvent(TkText *textPtr);
static void		AsyncUpdateYScrollbar(ClientData clientData);
static int              IsStartOfNotMergedLine(TkText *textPtr,
                            CONST TkTextIndex *indexPtr);

/*
 * Result values returned by TextGetScrollInfoObj:
 */
................................................................................
    if (tkTextDebug) {
	char buffer[2 * TCL_INTEGER_SPACE + 1];

	sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine);
	LOG("tk_textInvalidateLine", buffer);
    }

    GenerateTextLineHeightsInvalidEvent(textPtr);

    /*
     * If we're not in the middle of a long-line calculation (metricEpoch==-1)
     * and we've reached the last line, then we're done.
     */

    if (dInfoPtr->metricEpoch == -1
	    && lineNum == dInfoPtr->lastMetricUpdateLine) {
................................................................................
     * Re-arm the timer. We already have a refCount on the text widget so no
     * need to adjust that.
     */

    dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1,
	    AsyncUpdateLineMetrics, (ClientData) textPtr);
}
 
/*
 *----------------------------------------------------------------------
 *
 * GenerateTextLineHeightsInvalidEvent --
 *
 *      Send the <<TextLineHeightsInvalid>> event related to the text widget
 *      line metrics asynchronous update.
 *      This is equivalent to:
 *         event generate $textWidget <<TextLineHeightsInvalid>> -detail $N
 *      where $N is the number of lines for which the height is outdated.
 *
 * Results:
 *      None
 *
 * Side effects:
 *      If corresponding bindings are present, they will trigger.
 *
 *----------------------------------------------------------------------
 */

static void
GenerateTextLineHeightsInvalidEvent(
    TkText *textPtr)		/* Information about text widget. */
{
    union {XEvent general; XVirtualEvent virtual;} event;

    memset(&event, 0, sizeof(event));
    event.general.xany.type = VirtualEvent;
    event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
    event.general.xany.send_event = False;
    event.general.xany.window = Tk_WindowId(textPtr->tkwin);
    event.general.xany.display = Tk_Display(textPtr->tkwin);
    event.virtual.name = Tk_GetUid("TextLineHeightsInvalid");
    event.virtual.user_data = Tcl_NewIntObj(TkTextPendingyupdate(textPtr));
    Tk_HandleEvent(&event.general);
}
 
/*
 *----------------------------------------------------------------------
 *
 * TkTextUpdateLineMetrics --
 *
 *	This function updates the pixel height calculations of a range of

Changes to tests/text.test.

1017
1018
1019
1020
1021
1022
1023




























1024
1025
1026
1027
1028
1029
1030
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # ensure the test is relevant
    lappend res [expr {[.top.yt pendingyupdate] > 0}]
    # asynchronously wait for completion of line metrics calculation
    while {[.top.yt pendingyupdate]} {update}




























    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}

# edit, mark, scan, search, see, tag, window, xview and yview actions are tested elsewhere.







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







1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # ensure the test is relevant
    lappend res [expr {[.top.yt pendingyupdate] > 0}]
    # asynchronously wait for completion of line metrics calculation
    while {[.top.yt pendingyupdate]} {update}
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}
test text-11a.21 {"<<TextLineHeightsInvalid>>" event} {
    destroy .top.yt .top
    toplevel .top
    pack [text .top.yt]
    set content {}
    for {set i 1} {$i < 300} {incr i} {
        append content [string repeat "$i " 15] \n
    }
    .top.yt insert 1.0 $content
    update
    bind .top.yt <<TextLineHeightsInvalid>> { if {%d == 0} {set yud(%W) 1} }
    # wait for end of line metrics calculation to get correct $fraction1
    # as a reference
    if {[.top.yt pendingyupdate]} {vwait yud(.top.yt)}
    .top.yt yview moveto 1
    set fraction1 [lindex [.top.yt yview] 0]
    set res [expr {$fraction1 > 0}]
    .top.yt delete 1.0 end
    .top.yt insert 1.0 $content
    # synchronously wait for completion of line metrics calculation
    # and ensure the test is relevant
    set waited 0
    if {[.top.yt pendingyupdate]} {set waited 1 ; vwait yud(.top.yt)}
    lappend res $waited
    .top.yt yview moveto $fraction1
    set fraction2 [lindex [.top.yt yview] 0]
    lappend res [expr {$fraction1 == $fraction2}]
} {1 1 1}

# edit, mark, scan, search, see, tag, window, xview and yview actions are tested elsewhere.