Tk Source Code

Check-in [52287ff4]
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:Automatically bind text, entry, ttk::entry widgets to Services API at widget creation/mapping; re-work data mechanism to use selection rather than clipboard API, thanks to Marc Culler for that insight
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mac_services
Files: files | file ages | folders
SHA3-256: 52287ff456250cb15971a7a75517df953c142662d02018521f2a09065887fc27
User & Date: kevin_walzer 2019-04-30 11:40:13
Context
2019-05-01
01:43
Remove unnecessary call to Button1-Release in text widget check-in: 432d6fa9 user: kevin_walzer tags: mac_services
2019-04-30
11:40
Automatically bind text, entry, ttk::entry widgets to Services API at widget creation/mapping; re-work data mechanism to use selection rather than clipboard API, thanks to Marc Culler for that insight check-in: 52287ff4 user: kevin_walzer tags: mac_services
2019-04-24
03:27
Tweak text widget bindings to fire Services menu more consistently; formatting cleanup; thanks to Marc Culler for user feedback and patch for formatting check-in: 1c685607 user: kevin_walzer tags: mac_services
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to library/entry.tcl.

70
71
72
73
74
75
76
77
78
79
80


81
82
83
84
85
86
87
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
bind Entry <<TraverseIn>> {
    %W selection range 0 end
    %W icursor end
}

# Standard Motif bindings:

bind Entry <1> {
    if {[tk windowingsystem] eq "aqua"} {
	tk::RegisterServiceWidget %W
    }


    tk::EntryButton1 %W %x
    %W selection clear
}
bind Entry <B1-Motion> {
    set tk::Priv(x) %x
    tk::EntryMouseSelect %W %x
}
................................................................................
    tk::EntryAutoScan %W
}
bind Entry <B1-Enter> {
    tk::CancelRepeat
}
bind Entry <ButtonRelease-1> {
    tk::CancelRepeat
    if {[tk windowingsystem] eq "aqua"} {
	catch {::tk::CheckEntrySelection %W}
    }
}
bind Entry <Control-1> {
    %W icursor @%x
}

bind Entry <<PrevChar>> {
    tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
................................................................................
    if {[$w cget -show] ne ""} {
	return [string repeat [string index [$w cget -show] 0] \
		[string length $entryString]]
    }
    return $entryString
}

# ::tk::CheckEntrySelection --
#
# Writes selected text to the clipboard on macOS.
#
# Arguments:
# w -         The entry window from which the text to get

proc ::tk::CheckEntrySelection {w} {
    if {[$w selection present]} {
	clipboard clear
	clipboard append [::tk::EntryGetSelection $w]
    }
}















|

|

>
>







 







<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<








70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
114
115
116
117
118
119
120



121
122
123
124
125
126
127
...
654
655
656
657
658
659
660














661
662
663
664
665
666
667
668
bind Entry <<TraverseIn>> {
    %W selection range 0 end
    %W icursor end
}

# Standard Motif bindings:

bind Entry <Map> {
    if {[tk windowingsystem] eq "aqua"} {
    	::tk::RegisterServiceWidget %W
    }
}
bind Entry <1> {
    tk::EntryButton1 %W %x
    %W selection clear
}
bind Entry <B1-Motion> {
    set tk::Priv(x) %x
    tk::EntryMouseSelect %W %x
}
................................................................................
    tk::EntryAutoScan %W
}
bind Entry <B1-Enter> {
    tk::CancelRepeat
}
bind Entry <ButtonRelease-1> {
    tk::CancelRepeat



}
bind Entry <Control-1> {
    %W icursor @%x
}

bind Entry <<PrevChar>> {
    tk::EntrySetCursor %W [expr {[%W index insert] - 1}]
................................................................................
    if {[$w cget -show] ne ""} {
	return [string repeat [string index [$w cget -show] 0] \
		[string length $entryString]]
    }
    return $entryString
}























Changes to library/text.tcl.

33
34
35
36
37
38
39
40


41






42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
....
1208
1209
1210
1211
1212
1213
1214
1215
1216

#			and auto-scanning.
#
#-------------------------------------------------------------------------

#-------------------------------------------------------------------------
# The code below creates the default class bindings for text widgets.
#-------------------------------------------------------------------------



# Standard Motif bindings:







bind Text <1> {
    tk::TextButton1 %W %x %y
    %W tag remove sel 0.0 end
    if {[tk windowingsystem] eq "aqua"} {
    	::tk::RegisterServiceWidget %W
    }
}
bind Text <B1-Motion> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::TextSelectTo %W %x %y
}
bind Text <Double-1> {
................................................................................
    tk::TextAutoScan %W
}
bind Text <B1-Enter> {
    tk::CancelRepeat
}
bind Text <ButtonRelease-1> {
    tk::CancelRepeat
    if {[tk windowingsystem] eq "aqua"} {
	clipboard clear
	catch { set selected [%W get sel.first sel.last]}
	catch {clipboard append $selected}
    }
}

bind Text <Control-1> {
    %W mark set insert @%x,%y
    # An operation that moves the insert mark without making it
    # one end of the selection must insert an autoseparator
................................................................................
	set Priv(y) $y
    }
    if {($x != $Priv(x)) || ($y != $Priv(y))} {
	set Priv(mouseMoved) 1
    }
    if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} {
	$w scan dragto $x $y
    }
}








>
>

>
>
>
>
>
>




<
<
<







 







|
|
<
<







 







|

>
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53



54
55
56
57
58
59
60
..
86
87
88
89
90
91
92
93
94


95
96
97
98
99
100
101
....
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
#			and auto-scanning.
#
#-------------------------------------------------------------------------

#-------------------------------------------------------------------------
# The code below creates the default class bindings for text widgets.
#-------------------------------------------------------------------------



# Standard Motif bindings:

bind Text <Map> {
    if {[tk windowingsystem] eq "aqua"} {
    	::tk::RegisterServiceWidget %W
    }
}

bind Text <1> {
    tk::TextButton1 %W %x %y
    %W tag remove sel 0.0 end



}
bind Text <B1-Motion> {
    set tk::Priv(x) %x
    set tk::Priv(y) %y
    tk::TextSelectTo %W %x %y
}
bind Text <Double-1> {
................................................................................
    tk::TextAutoScan %W
}
bind Text <B1-Enter> {
    tk::CancelRepeat
}
bind Text <ButtonRelease-1> {
    tk::CancelRepeat
      if {[tk windowingsystem] eq "aqua"} {
    	::tk::RegisterServiceWidget %W


    }
}

bind Text <Control-1> {
    %W mark set insert @%x,%y
    # An operation that moves the insert mark without making it
    # one end of the selection must insert an autoseparator
................................................................................
	set Priv(y) $y
    }
    if {($x != $Priv(x)) || ($y != $Priv(y))} {
	set Priv(mouseMoved) 1
    }
    if {[info exists Priv(mouseMoved)] && $Priv(mouseMoved)} {
	$w scan dragto $x $y
    }  
}

Changes to library/ttk/entry.tcl.

53
54
55
56
57
58
59







60
61
62
63
64
65
66
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
...
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
#	Judgment call.  If <Meta> happens to be assigned to the Alt key,
#	these could conflict with application accelerators.
#	(Plus, who has a Meta key these days?)
# <Control-Key-t>:
#	Another judgment call.  If anyone misses this, let me know
#	and I'll put it back.
#








## Clipboard events:
#
bind TEntry <<Cut>> 			{ ttk::entry::Cut %W }
bind TEntry <<Copy>> 			{ ttk::entry::Copy %W }
bind TEntry <<Paste>> 			{ ttk::entry::Paste %W }
bind TEntry <<Clear>> 			{ ttk::entry::Clear %W }
................................................................................
    $w selection clear
    $w instate !disabled { focus $w }

    # Set up for future drag, double-click, or triple-click.
    set State(x) $x
    set State(selectMode) char
    set State(anchor) [$w index insert]
    if {[tk windowingsystem] eq "aqua"} {
	::tk::RegisterServiceWidget $w
    }
}

## Shift-Press -- Shift-ButtonPress-1 binding.
#	Extends the selection, sets anchor for future drag operations.
#
proc ttk::entry::Shift-Press {w x} {
    variable State
................................................................................

## <ButtonRelease-1> binding
#
proc ttk::entry::Release {w} {
    variable State
    set State(selectMode) none
    ttk::CancelRepeat 	;# suspend autoscroll
    if {[tk windowingsystem] eq "aqua"} {
	catch {::ttk::CheckEntrySelection $w}
    }	
}

## AutoScroll
#	Called repeatedly when the mouse is outside an entry window
#	with Button 1 down.  Scroll the window left or right,
#	depending on where the mouse left the window, and extend
#	the selection according to the current selection mode.
................................................................................
#	If there is a selection, delete that instead.
#
proc ttk::entry::Delete {w} {
    if {![PendingDelete $w]} {
	$w delete insert
    }
}

if {[tk windowingsystem] eq "aqua"} {
    # ::ttk::CheckEntrySelection --
    #
    # Writes selected text to the clipboard on macOS.
    #
    # Arguments:
    # w -         The entry window from which the text to get

    proc ::ttk::CheckEntrySelection {w} {
	if {[$w selection present]} {
	    clipboard clear
	    clipboard append [::ttk::entry::EntrySelection $w]
	}
    }
}


#*EOF*






>
>
>
>
>
>
>







 







<
<
<







 







<
<
<







 








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
351
352
353
354
355
356
357



358
359
360
361
362
363
364
...
430
431
432
433
434
435
436



437
438
439
440
441
442
443
...
606
607
608
609
610
611
612
613

















614
#	Judgment call.  If <Meta> happens to be assigned to the Alt key,
#	these could conflict with application accelerators.
#	(Plus, who has a Meta key these days?)
# <Control-Key-t>:
#	Another judgment call.  If anyone misses this, let me know
#	and I'll put it back.
#

##Bindings to register with macOS Services API.
bind T.Entry <Map> {
    if {[tk windowingsystem] eq "aqua"} {
    	::tk::RegisterServiceWidget %W
    }
}

## Clipboard events:
#
bind TEntry <<Cut>> 			{ ttk::entry::Cut %W }
bind TEntry <<Copy>> 			{ ttk::entry::Copy %W }
bind TEntry <<Paste>> 			{ ttk::entry::Paste %W }
bind TEntry <<Clear>> 			{ ttk::entry::Clear %W }
................................................................................
    $w selection clear
    $w instate !disabled { focus $w }

    # Set up for future drag, double-click, or triple-click.
    set State(x) $x
    set State(selectMode) char
    set State(anchor) [$w index insert]



}

## Shift-Press -- Shift-ButtonPress-1 binding.
#	Extends the selection, sets anchor for future drag operations.
#
proc ttk::entry::Shift-Press {w x} {
    variable State
................................................................................

## <ButtonRelease-1> binding
#
proc ttk::entry::Release {w} {
    variable State
    set State(selectMode) none
    ttk::CancelRepeat 	;# suspend autoscroll



}

## AutoScroll
#	Called repeatedly when the mouse is outside an entry window
#	with Button 1 down.  Scroll the window left or right,
#	depending on where the mouse left the window, and extend
#	the selection according to the current selection mode.
................................................................................
#	If there is a selection, delete that instead.
#
proc ttk::entry::Delete {w} {
    if {![PendingDelete $w]} {
	$w delete insert
    }
}


















#*EOF*

Changes to macosx/tkMacOSXServices.c.

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
			     types:(NSArray *)types
{
    NSArray *typesDeclared;
    if ([types containsObject:NSStringPboardType] == NO) {
	return NO;
    }

    Tcl_Eval(ServicesInterp,"clipboard get");
    char *copystring;
    copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));

    NSString *writestring = [NSString stringWithUTF8String:copystring];
    typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
    [pboard declareTypes:typesDeclared owner:nil];
    return [pboard setString:writestring forType:NSStringPboardType];






|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
			     types:(NSArray *)types
{
    NSArray *typesDeclared;
    if ([types containsObject:NSStringPboardType] == NO) {
	return NO;
    }

    Tcl_Eval(ServicesInterp,"selection get");
    char *copystring;
    copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));

    NSString *writestring = [NSString stringWithUTF8String:copystring];
    typesDeclared = [NSArray arrayWithObject:NSStringPboardType];
    [pboard declareTypes:typesDeclared owner:nil];
    return [pboard setString:writestring forType:NSStringPboardType];