summaryrefslogtreecommitdiffstats
path: root/library/menu.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'library/menu.tcl')
-rw-r--r--library/menu.tcl135
1 files changed, 91 insertions, 44 deletions
diff --git a/library/menu.tcl b/library/menu.tcl
index ff62484..8337eae 100644
--- a/library/menu.tcl
+++ b/library/menu.tcl
@@ -259,8 +259,10 @@ proc ::tk::MbPost {w {x {}} {y {}}} {
if {$cur ne ""} {
MenuUnpost {}
}
- set Priv(cursor) [$w cget -cursor]
- $w configure -cursor arrow
+ if {$::tk_strictMotif} {
+ set Priv(cursor) [$w cget -cursor]
+ $w configure -cursor arrow
+ }
if {[tk windowingsystem] ne "aqua"} {
set Priv(relief) [$w cget -relief]
$w configure -relief raised
@@ -303,7 +305,7 @@ proc ::tk::MbPost {w {x {}} {y {}}} {
set x [expr {[winfo rootx $w] - [winfo reqwidth $menu]}]
set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
set entry [MenuFindName $menu [$w cget -text]]
- if {[$w cget -indicatoron]} {
+ if {[$w cget -indicatoron] && $entry ne ""} {
if {$entry == [$menu index last]} {
incr y [expr {-([$menu yposition $entry] \
+ [winfo reqheight $menu])/2}]
@@ -323,7 +325,7 @@ proc ::tk::MbPost {w {x {}} {y {}}} {
set x [expr {[winfo rootx $w] + [winfo width $w]}]
set y [expr {(2 * [winfo rooty $w] + [winfo height $w]) / 2}]
set entry [MenuFindName $menu [$w cget -text]]
- if {[$w cget -indicatoron]} {
+ if {[$w cget -indicatoron] && $entry ne ""} {
if {$entry == [$menu index last]} {
incr y [expr {-([$menu yposition $entry] \
+ [winfo reqheight $menu])/2}]
@@ -402,12 +404,19 @@ proc ::tk::MenuUnpost menu {
# Unpost menu(s) and restore some stuff that's dependent on
# what was posted.
+ after cancel [array get Priv menuActivatedTimer]
+ unset -nocomplain Priv(menuActivated)
+ after cancel [array get Priv menuDeactivatedTimer]
+ unset -nocomplain Priv(menuDeactivated)
+
catch {
if {$mb ne ""} {
set menu [$mb cget -menu]
$menu unpost
set Priv(postedMb) {}
- $mb configure -cursor $Priv(cursor)
+ if {$::tk_strictMotif} {
+ $mb configure -cursor $Priv(cursor)
+ }
if {[tk windowingsystem] ne "aqua"} {
$mb configure -relief $Priv(relief)
} else {
@@ -416,7 +425,8 @@ proc ::tk::MenuUnpost menu {
} elseif {$Priv(popup) ne ""} {
$Priv(popup) unpost
set Priv(popup) {}
- } elseif {[$menu cget -type] ne "menubar" && [$menu cget -type] ne "tearoff"} {
+ } elseif {[$menu cget -type] ne "menubar" \
+ && [$menu cget -type] ne "tearoff"} {
# We're in a cascaded sub-menu from a torn-off menu or popup.
# Unpost all the menus up to the toplevel one (but not
# including the top-level torn-off one) and deactivate the
@@ -424,7 +434,8 @@ proc ::tk::MenuUnpost menu {
while {1} {
set parent [winfo parent $menu]
- if {[winfo class $parent] ne "Menu" || ![winfo ismapped $parent]} {
+ if {[winfo class $parent] ne "Menu" \
+ || ![winfo ismapped $parent]} {
break
}
$parent activate none
@@ -453,7 +464,9 @@ proc ::tk::MenuUnpost menu {
}
RestoreOldGrab
if {$Priv(menuBar) ne ""} {
- $Priv(menuBar) configure -cursor $Priv(cursor)
+ if {$::tk_strictMotif} {
+ $Priv(menuBar) configure -cursor $Priv(cursor)
+ }
set Priv(menuBar) {}
}
if {[tk windowingsystem] ne "x11"} {
@@ -537,6 +550,7 @@ proc ::tk::MbButtonUp w {
proc ::tk::MenuMotion {menu x y state} {
variable ::tk::Priv
if {$menu eq $Priv(window)} {
+ set activeindex [$menu index active]
if {[$menu cget -type] eq "menubar"} {
if {[info exists Priv(focus)] && $menu ne $Priv(focus)} {
$menu activate @$x,$y
@@ -546,9 +560,22 @@ proc ::tk::MenuMotion {menu x y state} {
$menu activate @$x,$y
GenerateMenuSelect $menu
}
- }
- if {($state & 0x1f00) != 0} {
- $menu postcascade active
+ set index [$menu index @$x,$y]
+ if {[info exists Priv(menuActivated)] \
+ && $index ne "none" \
+ && $index ne $activeindex} {
+ set mode [option get $menu clickToFocus ClickToFocus]
+ if {[string is false $mode]} {
+ set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}]
+ if {[$menu type $index] eq "cascade"} {
+ set Priv(menuActivatedTimer) \
+ [after $delay [list $menu postcascade active]]
+ } else {
+ set Priv(menuDeactivatedTimer) \
+ [after $delay [list $menu postcascade none]]
+ }
+ }
+ }
}
}
@@ -584,10 +611,15 @@ proc ::tk::MenuButtonDown menu {
set menu [winfo parent $menu]
}
- if {$Priv(menuBar) eq ""} {
+ if {$Priv(menuBar) eq {}} {
set Priv(menuBar) $menu
- set Priv(cursor) [$menu cget -cursor]
- $menu configure -cursor arrow
+ if {$::tk_strictMotif} {
+ set Priv(cursor) [$menu cget -cursor]
+ $menu configure -cursor arrow
+ }
+ if {[$menu type active] eq "cascade"} {
+ set Priv(menuActivated) 1
+ }
}
# Don't update grab information if the grab window isn't changing.
@@ -625,7 +657,8 @@ proc ::tk::MenuLeave {menu rootx rooty state} {
return
}
if {[$menu type active] eq "cascade" \
- && [winfo containing $rootx $rooty] eq [$menu entrycget active -menu]} {
+ && [winfo containing $rootx $rooty] eq \
+ [$menu entrycget active -menu]} {
return
}
$menu activate none
@@ -779,7 +812,8 @@ proc ::tk::MenuNextMenu {menu direction} {
} else {
set parent [winfo parent $menu]
while {$parent ne "."} {
- if {[winfo class $parent] eq "Menu" && [$parent cget -type] eq "menubar"} {
+ if {[winfo class $parent] eq "Menu" \
+ && [$parent cget -type] eq "menubar"} {
tk_menuSetFocus $parent
MenuNextEntry $parent 1
return
@@ -803,16 +837,14 @@ proc ::tk::MenuNextMenu {menu direction} {
}
}
- # Can't traverse into or out of a cascaded menu. Go to the next
+ # Can't traverse into or out of a cascaded menu. Go to the next
# or previous menubutton, if that makes sense.
set m2 [winfo parent $menu]
- if {[winfo class $m2] eq "Menu"} {
- if {[$m2 cget -type] eq "menubar"} {
- tk_menuSetFocus $m2
- MenuNextEntry $m2 -1
- return
- }
+ if {[winfo class $m2] eq "Menu" && [$m2 cget -type] eq "menubar"} {
+ tk_menuSetFocus $m2
+ MenuNextEntry $m2 -1
+ return
}
set w $Priv(postedMb)
@@ -932,7 +964,8 @@ proc ::tk::MenuFind {w char} {
if {[winfo toplevel $w] ne [winfo toplevel $child]} {
continue
}
- if {[winfo class $child] eq "Menu" && [$child cget -type] eq "menubar"} {
+ if {[winfo class $child] eq "Menu" && \
+ [$child cget -type] eq "menubar"} {
if {$char eq ""} {
return $child
}
@@ -957,7 +990,7 @@ proc ::tk::MenuFind {w char} {
if {[winfo toplevel $w] ne [winfo toplevel $child]} {
continue
}
- switch [winfo class $child] {
+ switch -- [winfo class $child] {
Menubutton {
set char2 [string index [$child cget -text] \
[$child cget -underline]]
@@ -997,10 +1030,11 @@ proc ::tk::TraverseToMenu {w char} {
return
}
while {[winfo class $w] eq "Menu"} {
+ if {[$w cget -type] ne "menubar" && $Priv(postedMb) eq ""} {
+ return
+ }
if {[$w cget -type] eq "menubar"} {
break
- } elseif {$Priv(postedMb) eq ""} {
- return
}
set w [winfo parent $w]
}
@@ -1112,15 +1146,15 @@ proc ::tk::MenuFirstEntry menu {
}
for {set i 0} {$i <= $last} {incr i} {
if {([catch {set state [$menu entrycget $i -state]}] == 0) \
- && $state ne "disabled" \
- && [$menu type $i] ne "tearoff"} {
+ && $state ne "disabled" && [$menu type $i] ne "tearoff"} {
$menu activate $i
GenerateMenuSelect $menu
# Only post the cascade if the current menu is a menubar;
# otherwise, if the first entry of the cascade is a cascade,
# we can get an annoying cascading effect resulting in a bunch of
# menus getting posted (bug 676)
- if {[$menu type $i] eq "cascade" && [$menu cget -type] eq "menubar"} {
+ if {[$menu type $i] eq "cascade" \
+ && [$menu cget -type] eq "menubar"} {
set cascade [$menu entrycget $i -menu]
if {$cascade ne ""} {
$menu postcascade $i
@@ -1188,23 +1222,34 @@ proc ::tk::PostOverPoint {menu x y {entry {}}} {
}
incr x [expr {-[winfo reqwidth $menu]/2}]
}
+
if {$tcl_platform(platform) eq "windows"} {
+ # osVersion is not available in safe interps
+ set ver 5
+ if {[info exists tcl_platform(osVersion)]} {
+ scan $tcl_platform(osVersion) %d ver
+ }
+
# We need to fix some problems with menu posting on Windows,
# where, if the menu would overlap top or bottom of screen,
# Windows puts it in the wrong place for us. We must also
# subtract an extra amount for half the height of the current
# entry. To be safe we subtract an extra 10.
- set yoffset [expr {[winfo screenheight $menu] \
- - $y - [winfo reqheight $menu] - 10}]
- if {$yoffset < [winfo vrooty $menu]} {
- # The bottom of the menu is offscreen, so adjust upwards
- incr y [expr {$yoffset - [winfo vrooty $menu]}]
- }
- # If we're off the top of the screen (either because we were
- # originally or because we just adjusted too far upwards),
- # then make the menu popup on the top edge.
- if {$y < [winfo vrooty $menu]} {
- set y [winfo vrooty $menu]
+ # NOTE: this issue appears to have been resolved in the Window
+ # manager provided with Vista and Windows 7.
+ if {$ver < 6} {
+ set yoffset [expr {[winfo screenheight $menu] \
+ - $y - [winfo reqheight $menu] - 10}]
+ if {$yoffset < [winfo vrooty $menu]} {
+ # The bottom of the menu is offscreen, so adjust upwards
+ incr y [expr {$yoffset - [winfo vrooty $menu]}]
+ }
+ # If we're off the top of the screen (either because we were
+ # originally or because we just adjusted too far upwards),
+ # then make the menu popup on the top edge.
+ if {$y < [winfo vrooty $menu]} {
+ set y [winfo vrooty $menu]
+ }
}
}
$menu post $x $y
@@ -1242,7 +1287,7 @@ proc ::tk::RestoreOldGrab {} {
# be visible anymore.
catch {
- if {$Priv(grabStatus) eq "global"} {
+ if {$Priv(grabStatus) eq "global"} {
grab set -global $Priv(oldGrab)
} else {
grab set $Priv(oldGrab)
@@ -1259,11 +1304,12 @@ proc ::tk_menuSetFocus {menu} {
}
focus $menu
}
-
+
proc ::tk::GenerateMenuSelect {menu} {
variable ::tk::Priv
- if {$Priv(activeMenu) eq $menu && $Priv(activeItem) eq [$menu index active]} {
+ if {$Priv(activeMenu) eq $menu \
+ && $Priv(activeItem) eq [$menu index active]} {
return
}
@@ -1295,6 +1341,7 @@ proc ::tk_popup {menu x y {entry {}}} {
tk::SaveGrabInfo $menu
grab -global $menu
set Priv(popup) $menu
+ set Priv(menuActivated) 1
tk_menuSetFocus $menu
}
}