︙ | | |
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
+
|
if {![winfo exists $w]} {
return
}
if {[$w cget -state] eq "active" && [tk windowingsystem] ne "aqua"} {
$w configure -state normal
}
}
# ::tk::MbPost --
# Given a menubutton, this procedure does all the work of posting
# its associated menu and unposting any other menu that is currently
# posted.
#
# Arguments:
|
︙ | | |
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
|
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
|
$w configure -state active
}
set Priv(postedMb) $w
set Priv(focus) [focus]
$menu activate none
GenerateMenuSelect $menu
# If this looks like an option menubutton then post the menu so
# that the current entry is on top of the mouse. Otherwise post
# the menu just below the menubutton, as for a pull-down.
update idletasks
if {[catch {
switch [$w cget -direction] {
above {
set x [winfo rootx $w]
set y [expr {[winfo rooty $w] - [winfo reqheight $menu]}]
# if we go offscreen to the top, show as 'below'
if {$y < [winfo vrooty $w]} {
set y [expr {[winfo vrooty $w] + [winfo rooty $w] + [winfo reqheight $w]}]
}
PostOverPoint $menu $x $y
}
below {
set x [winfo rootx $w]
set y [expr {[winfo rooty $w] + [winfo height $w]}]
# if we go offscreen to the bottom, show as 'above'
set mh [winfo reqheight $menu]
if {($y + $mh) > ([winfo vrooty $w] + [winfo vrootheight $w])} {
set y [expr {[winfo vrooty $w] + [winfo vrootheight $w] + [winfo rooty $w] - $mh}]
}
PostOverPoint $menu $x $y
}
left {
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 {$entry eq ""} {
set entry 0
}
if {[$w cget -indicatoron]} {
if {$entry == [$menu index last]} {
incr y [expr {-([$menu yposition $entry] \
+ [winfo reqheight $menu])/2}]
} else {
incr y [expr {-([$menu yposition $entry] \
+ [$menu yposition [expr {$entry+1}]])/2}]
}
}
PostOverPoint $menu $x $y
if {$entry ne "" \
&& [$menu entrycget $entry -state] ne "disabled"} {
$menu activate $entry
GenerateMenuSelect $menu
}
}
right {
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 {$entry eq ""} {
set entry 0
}
if {[$w cget -indicatoron]} {
if {$entry == [$menu index last]} {
incr y [expr {-([$menu yposition $entry] \
+ [winfo reqheight $menu])/2}]
} else {
incr y [expr {-([$menu yposition $entry] \
+ [$menu yposition [expr {$entry+1}]])/2}]
}
}
PostOverPoint $menu $x $y
if {$entry ne "" \
&& [$menu entrycget $entry -state] ne "disabled"} {
$menu activate $entry
GenerateMenuSelect $menu
}
}
default {
if {[$w cget -indicatoron]} {
if {$y eq ""} {
set x [expr {[winfo rootx $w] + [winfo width $w]/2}]
set y [expr {[winfo rooty $w] + [winfo height $w]/2}]
}
PostOverPoint $menu $x $y [MenuFindName $menu [$w cget -text]]
} else {
PostOverPoint $menu [winfo rootx $w] [expr {[winfo rooty $w]+[winfo height $w]}]
}
}
}
} msg opt]} {
if {[catch {PostMenubuttonMenu $w $menu} msg opt]} {
# Error posting menu (e.g. bogus -postcommand). Unpost it and
# reflect the error.
MenuUnpost {}
return -options $opt $msg
}
set Priv(tearoff) $tearoff
if {$tearoff != 0} {
if {$tearoff != 0 && [tk windowingsystem] ne "aqua"} {
focus $menu
if {[winfo viewable $w]} {
SaveGrabInfo $w
grab -global $w
}
}
}
|
︙ | | |
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
|
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
|
+
+
-
+
-
+
|
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"} {
# Catch these postcascade commands since the menu could be
# destroyed before they run.
set Priv(menuActivatedTimer) \
[after $delay [list $menu postcascade active]]
[after $delay "catch {$menu postcascade active}"]
} else {
set Priv(menuDeactivatedTimer) \
[after $delay [list $menu postcascade none]]
[after $delay "catch {$menu postcascade none}"]
}
}
}
}
}
# ::tk::MenuButtonDown --
|
︙ | | |
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
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
|
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
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
-
+
-
-
+
-
-
-
-
-
+
+
+
+
+
|
if {$label eq $s} {
return $i
}
}
}
return ""
}
# ::tk::PostMenubuttonMenu --
#
# Given a menubutton and a menu, this procedure posts the menu at the
# appropriate location. If the menubutton looks like an option
# menubutton, meaning that the indicator is on and the direction is
# neither above nor below, then the menu is posted so that the current
# entry is vertically aligned with the menubutton. On the Mac this
# will expose a small amount of the blue indicator on the right hand
# side. On other platforms the entry is centered over the button.
if {[tk windowingsystem] eq "aqua"} {
proc ::tk::PostMenubuttonMenu {button menu} {
set entry ""
if {[$button cget -indicatoron]} {
set entry [MenuFindName $menu [$button cget -text]]
if {$entry eq ""} {
set entry 0
}
}
set x [winfo rootx $button]
set y [expr {2 + [winfo rooty $button]}]
switch [$button cget -direction] {
above {
set entry ""
incr y [expr {4 - [winfo reqheight $menu]}]
}
below {
set entry ""
incr y [expr {2 + [winfo height $button]}]
}
left {
incr x [expr {-[winfo reqwidth $menu]}]
}
right {
incr x [winfo width $button]
}
default {
incr x [expr {[winfo width $button] - [winfo reqwidth $menu] - 5}]
}
}
PostOverPoint $menu $x $y $entry
}
} else {
proc ::tk::PostMenubuttonMenu {button menu} {
set entry ""
if {[$button cget -indicatoron]} {
set entry [MenuFindName $menu [$button cget -text]]
if {$entry eq ""} {
set entry 0
}
}
if {$entry ne ""} {
if {$entry == [$menu index last]} {
set entryHeight [expr {[winfo reqheight $menu] \
- [$menu yposition $entry]}]
} else {
set entryHeight [expr {[$menu yposition [expr {$entry+1}]] \
- [$menu yposition $entry]}]
}
}
set x [winfo rootx $button]
set y [winfo rooty $button]
switch [$button cget -direction] {
above {
incr y [expr {-[winfo reqheight $menu]}]
# if we go offscreen to the top, show as 'below'
if {$y < [winfo vrooty $button]} {
set y [expr {[winfo vrooty $button] + [winfo rooty $button]\
+ [winfo reqheight $button]}]
}
set entry {}
}
below {
incr y [winfo height $button]
# if we go offscreen to the bottom, show as 'above'
set mh [winfo reqheight $menu]
if {($y + $mh) > ([winfo vrooty $button] + [winfo vrootheight $button])} {
set y [expr {[winfo vrooty $button] + [winfo vrootheight $button] \
+ [winfo rooty $button] - $mh}]
}
set entry {}
}
left {
# It is not clear why this is needed.
if {[tk windowingsystem] eq "win32"} {
incr x [expr {-4 - [winfo reqwidth $button] / 2}]
}
incr x [expr {- [winfo reqwidth $menu]}]
}
right {
incr x [expr {[winfo width $button]}]
}
default {
if {[$button cget -indicatoron]} {
incr x [expr {([winfo width $button] - \
[winfo reqwidth $menu])/ 2}]
} else {
incr y [winfo height $button]
}
}
}
PostOverPoint $menu $x $y $entry
}
}
# ::tk::PostOverPoint --
#
# This procedure posts a given menu such that a given entry in the
# menu is centered over a given point in the root window. It also
# activates the given entry.
# This procedure posts a menu on the screen so that a given entry in
# the menu is positioned with its upper left corner at a given point
# in the root window. The procedure also activates that entry. If no
# entry is specified the upper left corner of the entire menu is
# placed at the point.
#
# Arguments:
# menu - Menu to post.
# x, y - Root coordinates of point.
# entry - Index of entry within menu to center over (x,y).
# If omitted or specified as {}, then the menu's
# upper-left corner goes at (x,y).
if {[tk windowingsystem] ne "win32"} {
proc ::tk::PostOverPoint {menu x y {entry {}}} {
if {$entry ne ""} {
if {$entry == [$menu index last]} {
incr y [expr {-([$menu yposition $entry] \
+ [winfo reqheight $menu])/2}]
proc ::tk::PostOverPoint {menu x y {entry {}}} {
if {$entry ne ""} {
$menu post $x $y $entry
if {[$menu entrycget $entry -state] ne "disabled"} {
$menu activate $entry
GenerateMenuSelect $menu
}
} else {
incr y [expr {-([$menu yposition $entry] \
$menu post $x $y
+ [$menu yposition [expr {$entry+1}]])/2}]
}
incr x [expr {-[winfo reqwidth $menu]/2}]
return
}
} else {
proc ::tk::PostOverPoint {menu x y {entry {}}} {
if {$entry ne ""} {
incr y [expr {-[$menu yposition $entry]}]
}
if {[tk windowingsystem] eq "win32"} {
# 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.
# 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}]
- $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
if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
$menu activate $entry
GenerateMenuSelect $menu
$menu post $x $y
if {$entry ne "" && [$menu entrycget $entry -state] ne "disabled"} {
$menu activate $entry
GenerateMenuSelect $menu
}
}
}
# ::tk::SaveGrabInfo --
# Sets the variables tk::Priv(oldGrab) and tk::Priv(grabStatus) to record
# the state of any existing grab on the w's display.
#
|
︙ | | |
︙ | | |
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
|
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
|
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
-
+
+
+
+
+
-
+
-
+
+
-
+
-
-
+
+
-
-
-
+
+
-
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
}
/*
*----------------------------------------------------------------------
*
* TkpPostMenu --
*
* Posts a menu on the screen
* Posts a menu on the screen. If entry is < 0 then the menu is
* drawn so its top left corner is located at the point with
* screen coordinates (x, y). Otherwise the top left corner of
* the specified entry is located at that point.
*
* Results:
* None.
* Returns a standard Tcl result.
*
* Side effects:
* The menu is posted and handled.
*
*----------------------------------------------------------------------
*/
int
TkpPostMenu(
Tcl_Interp *interp, /* The interpreter this menu lives in */
TkMenu *menuPtr, /* The menu we are posting */
int x, /* The global x-coordinate of the top, left-
* hand corner of where the menu is supposed
* to be posted. */
int y) /* The global y-coordinate */
int x, int y, /* The screen coordinates where the top left
* corner of the menu, or of the specified
* entry, will be located. */
int index)
{
int result;
/* Get the object that holds this Tk Window.*/
Tk_Window root;
root = Tk_MainWindow(interp);
Tk_Window root = Tk_MainWindow(interp);
if (root == NULL) {
return TCL_ERROR;
}
Drawable d = Tk_WindowId(root);
NSView *rootview = TkMacOSXGetRootControl(d);
NSWindow *win = [rootview window];
NSView *view = [win contentView];
NSMenu *menu = (NSMenu *) menuPtr->platformData;
NSInteger itemIndex = index;
NSInteger numItems = [menu numberOfItems];
NSMenuItem *item = nil;
int result;
NSPoint location = NSMakePoint(x, tkMacOSXZeroScreenHeight - y);
inPostMenu = 1;
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
inPostMenu = 0;
return result;
}
if (itemIndex >= numItems) {
itemIndex = numItems - 1;
}
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
NSView *view = [win contentView];
if (itemIndex >= 0) {
item = [menu itemAtIndex:itemIndex];
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
frame.origin = [view convertPoint:
}
[win tkConvertPointFromScreen:frame.origin] fromView:nil];
/*
* The post commands could have deleted the menu, which means we are dead
* and should go away.
*/
NSMenu *menu = (NSMenu *) menuPtr->platformData;
if (menuPtr->tkwin == NULL) {
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
initTextCell:@"" pullsDown:NO];
[popUpButtonCell setAltersStateOfSelectedItem:NO];
[popUpButtonCell setMenu:menu];
return TCL_OK;
}
[menu popUpMenuPositioningItem:item
[popUpButtonCell selectItem:nil];
[popUpButtonCell performClickWithFrame:frame inView:view];
atLocation:[win tkConvertPointFromScreen:location]
inView:view];
[popUpButtonCell release];
Tcl_SetServiceMode(oldMode);
inPostMenu = 0;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpPostTearoffMenu --
*
* Tearoff menus are not supported on the Mac. This placeholder
* function, which is simply a copy of the unix function, posts a
* completely useless window with a black background on the screen. If
* entry is < 0 then the window is positioned so that its top left corner
* is located at the point with screen coordinates (x, y). Otherwise the
* window position is offset so that top left corner of the specified
* entry would be located at that point, if there actually were a menu.
*
* Mac menus steal all mouse or keyboard input from the application until
* the menu is dismissed, with or without a selection, by a mouse or key
* event. Posting a Mac menu in a regression test will cause the test to
* halt waiting for user input. This is why the TkpPostMenu function is
* not being used as the placeholder.
*
* Results:
* None.
*
* Side effects:
* A useless window is posted.
*
*----------------------------------------------------------------------
*/
int
TkpPostTearoffMenu(
Tcl_Interp *interp, /* The interpreter this menu lives in */
TkMenu *menuPtr, /* The menu we are posting */
int x, int y, int index) /* The screen coordinates where the top left
* corner of the menu, or of the specified
* entry, will be located. */
{
int vRootX, vRootY, vRootWidth, vRootHeight;
int result;
if (index >= menuPtr->numEntries) {
index = menuPtr->numEntries - 1;
}
if (index >= 0) {
y -= menuPtr->entries[index]->y;
}
TkActivateMenuEntry(menuPtr, -1);
TkRecomputeMenu(menuPtr);
result = TkPostCommand(menuPtr);
if (result != TCL_OK) {
return result;
}
/*
* The post commands could have deleted the menu, which means we are dead
* and should go away.
*/
if (menuPtr->tkwin == NULL) {
return TCL_OK;
}
/*
* Adjust the position of the menu if necessary to keep it visible on the
* screen. There are two special tricks to make this work right:
*
* 1. If a virtual root window manager is being used then the coordinates
* are in the virtual root window of menuPtr's parent; since the menu
* uses override-redirect mode it will be in the *real* root window for
* the screen, so we have to map the coordinates from the virtual root
* (if any) to the real root. Can't get the virtual root from the menu
* itself (it will never be seen by the wm) so use its parent instead
* (it would be better to have an an option that names a window to use
* for this...).
* 2. The menu may not have been mapped yet, so its current size might be
* the default 1x1. To compute how much space it needs, use its
* requested size, not its actual size.
*/
Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
&vRootWidth, &vRootHeight);
vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
if (x > vRootX + vRootWidth) {
x = vRootX + vRootWidth;
}
if (x < vRootX) {
x = vRootX;
}
vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
if (y > vRootY + vRootHeight) {
y = vRootY + vRootHeight;
}
if (y < vRootY) {
y = vRootY;
}
Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
if (!Tk_IsMapped(menuPtr->tkwin)) {
Tk_MapWindow(menuPtr->tkwin);
}
TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpSetWindowMenuBar --
*
* Associates a given menu with a window.
|
︙ | | |
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
|
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
|
+
-
+
-
+
-
+
|
*--------------------------------------------------------------
*/
void
TkpComputeStandardMenuGeometry(
TkMenu *menuPtr) /* Structure describing menu. */
{
NSSize menuSize = [(NSMenu *)menuPtr->platformData size];
Tk_Font tkfont, menuFont;
Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr;
int modifierCharWidth, menuModifierCharWidth;
int x, y, modifierWidth, labelWidth, indicatorSpace;
int windowWidth, windowHeight, accelWidth;
int i, j, lastColumnBreak, maxWidth;
int i, maxWidth;
int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth;
TkMenuEntry *mePtr, *columnEntryPtr;
TkMenuEntry *mePtr;
int haveAccel = 0;
if (menuPtr->tkwin == NULL) {
return;
}
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
&borderWidth);
Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr,
&activeBorderWidth);
x = y = borderWidth;
windowHeight = maxWidth = lastColumnBreak = 0;
windowHeight = maxWidth = 0;
maxIndicatorSpace = 0;
/*
* On the Mac especially, getting font metrics can be quite slow, so we
* want to do it intelligently. We are going to precalculate them and pass
* them down to all of the measuring and drawing routines. We will measure
* the font metrics of the menu once. If an entry does not have its own
|
︙ | | |
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
|
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
|
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
-
-
+
-
+
+
+
-
|
haveAccel = 1;
break;
}
}
for (i = 0; i < menuPtr->numEntries; i++) {
mePtr = menuPtr->entries[i];
if (mePtr->type == TEAROFF_ENTRY) {
continue;
}
if (mePtr->fontPtr == NULL) {
tkfont = menuFont;
fmPtr = &menuMetrics;
modifierCharWidth = menuModifierCharWidth;
} else {
tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr);
Tk_GetFontMetrics(tkfont, &entryMetrics);
fmPtr = &entryMetrics;
modifierCharWidth = ModifierCharWidth(tkfont);
}
if ((i > 0) && mePtr->columnBreak) {
if (maxIndicatorSpace != 0) {
maxIndicatorSpace += 2;
}
for (j = lastColumnBreak; j < i; j++) {
columnEntryPtr = menuPtr->entries[j];
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ 2 * activeBorderWidth;
columnEntryPtr->x = x;
columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN;
}
x += maxIndicatorSpace + maxWidth + 2 * activeBorderWidth;
maxWidth = maxIndicatorSpace = 0;
lastColumnBreak = i;
y = borderWidth;
}
accelWidth = modifierWidth = indicatorSpace = 0;
if (mePtr->type == SEPARATOR_ENTRY || mePtr->type == TEAROFF_ENTRY) {
if (mePtr->type == SEPARATOR_ENTRY) {
mePtr->height = menuSeparatorHeight;
} else {
/*
* For each entry, compute the height required by that particular
* entry, plus three widths: the width of the label, the width to
* allow for an indicator to be displayed to the left of the label
* (if any), and the width of the accelerator to be displayed to
* the right of the label (if any). These sizes depend, of course,
* on the type of the entry.
*/
NSMenuItem *menuItem = (NSMenuItem *) mePtr->platformEntryData;
int haveImage = 0, width = 0, height = 0;
if (mePtr->image) {
Tk_SizeOfImage(mePtr->image, &width, &height);
haveImage = 1;
height += 2; /* tweak */
} else if (mePtr->bitmapPtr) {
Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin,
mePtr->bitmapPtr);
Tk_SizeOfBitmap(menuPtr->display, bitmap, &width, &height);
haveImage = 1;
height += 2; /* tweak */
}
if (!haveImage || (mePtr->compound != COMPOUND_NONE)) {
NSAttributedString *attrTitle = [menuItem attributedTitle];
NSSize size;
if (attrTitle) {
size = [attrTitle size];
} else {
size = [[menuItem title] sizeWithAttributes:
TkMacOSXNSFontAttributesForFont(tkfont)];
}
size.width += menuTextLeadingEdgeMargin +
size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
menuTextTrailingEdgeMargin;
if (size.height < fmPtr->linespace) {
size.height = fmPtr->linespace;
size.height -= 1; /* tweak */
}
if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
int margin = width + menuIconTrailingEdgeMargin;
if (margin > menuTextLeadingEdgeMargin) {
margin = menuTextLeadingEdgeMargin;
}
width += size.width + menuIconTrailingEdgeMargin - margin;
if (size.height > height) {
height = size.height;
}
} else {
width = size.width;
height = size.height;
}
}
else {
/* image only. */
}
labelWidth = width + menuItemExtraWidth;
mePtr->height = height + menuItemExtraHeight;
if (mePtr->type == CASCADE_ENTRY) {
modifierWidth = modifierCharWidth;
} else if (mePtr->accelLength == 0) {
if (haveAccel && !mePtr->hideMargin) {
modifierWidth = modifierCharWidth;
}
} else {
|
︙ | | |
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
|
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
|
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
|
if (indicatorSpace > maxIndicatorSpace) {
maxIndicatorSpace = indicatorSpace;
}
entryWidth = labelWidth + modifierWidth + accelWidth;
if (entryWidth > maxWidth) {
maxWidth = entryWidth;
}
menuPtr->entries[i]->width = entryWidth;
mePtr->height += 2 * activeBorderWidth;
}
mePtr->x = x;
mePtr->y = y;
y += menuPtr->entries[i]->height + borderWidth;
if (y > windowHeight) {
windowHeight = y;
}
}
}
for (j = lastColumnBreak; j < menuPtr->numEntries; j++) {
columnEntryPtr = menuPtr->entries[j];
columnEntryPtr->indicatorSpace = maxIndicatorSpace;
columnEntryPtr->width = maxIndicatorSpace + maxWidth
+ 2 * activeBorderWidth;
columnEntryPtr->x = x;
columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN;
}
windowWidth = x + maxIndicatorSpace + maxWidth
windowWidth = menuSize.width;
+ 2 * activeBorderWidth + borderWidth;
windowHeight += borderWidth;
if (windowWidth <= 0) {
windowWidth = 1;
}
windowHeight = menuSize.height;
if (windowHeight <= 0) {
windowHeight = 1;
}
menuPtr->totalWidth = windowWidth;
menuPtr->totalHeight = windowHeight;
}
|
︙ | | |
︙ | | |
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
-
+
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
|
ThemeButtonKind btnkind;
HIThemeButtonDrawInfo drawinfo;
HIThemeButtonDrawInfo lastdrawinfo;
DrawParams drawParams;
} MacMenuButton;
/*
* Forward declarations for procedures defined later in this file:
* Forward declarations for static functions defined later in this file:
*/
static void MenuButtonEventProc(ClientData clientData, XEvent *eventPtr);
static void MenuButtonBackgroundDrawCB ( MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
static void MenuButtonContentDrawCB ( ThemeButtonKind kind, const HIThemeButtonDrawInfo * info, MacMenuButton *ptr, SInt16 depth, Boolean isColorDev);
static void MenuButtonBackgroundDrawCB (MacMenuButton *ptr, SInt16 depth,
Boolean isColorDev);
static void MenuButtonContentDrawCB (ThemeButtonKind kind,
const HIThemeButtonDrawInfo * info,
MacMenuButton *ptr, SInt16 depth,
Boolean isColorDev);
static void MenuButtonEventProc ( ClientData clientData, XEvent *eventPtr);
static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo* drawinfo);
static int TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr, DrawParams * dpPtr);
static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr,
static void TkMacOSXComputeMenuButtonParams (TkMenuButton * butPtr,
ThemeButtonKind* btnkind,
HIThemeButtonDrawInfo* drawinfo);
static void TkMacOSXComputeMenuButtonDrawParams (TkMenuButton * butPtr,
DrawParams * dpPtr);
static void TkMacOSXDrawMenuButton (MacMenuButton *butPtr, GC gc, Pixmap pixmap);
GC gc, Pixmap pixmap);
static void DrawMenuButtonImageAndText(TkMenuButton* butPtr);
/*
* The structure below defines menubutton class behavior by means of
* procedures that can be invoked from generic window code.
*/
Tk_ClassProcs tkpMenubuttonClass = {
sizeof(Tk_ClassProcs), /* size */
TkMenuButtonWorldChanged, /* worldChangedProc */
};
/*
* We use Apple's Pop-Up Button widget to represent the Tk Menubutton.
* However, we do not use the NSPopUpButton class for this control. Instead we
* render the Pop-Up Button using the HITheme library. This imposes some
* constraints on what can be done. The HITheme renderer allows only specific
* dimensions for the button.
*
* The HITheme library allows drawing a Pop-Up Button with an arbitrary bounds
* rectangle. However the button is always drawn as a rounded box which is 22
* pixels high. If the bounds rectangle is less than 22 pixels high, the
* button is drawn at the top of the rectangle and the bottom of the button is
* clipped away. So we set a minimum height of 22 pixels for a Menubutton. If
* the bounds rectangle is more than 22 pixels high, then the button is drawn
* centered vertically in the bounds rectangle.
*
* The content rectangle of the button is inset by 14 pixels on the left and 28
* pixels on the right. The rightmost part of the button contains the blue
* double-arrow symbol which is 28 pixels wide.
*
* To maintain compatibility with code that runs on multiple operating systems,
* the width and height of the content rectangle includes the borderWidth, the
* highlightWidth and the padX and padY dimensions of the Menubutton. However,
* to be consistent with the standard Apple appearance, the content is always
* be drawn at the left side of the content rectangle. All of the excess space
* appears on the right side of the content, and the anchor property is
* ignored. The easiest way to comply with Apple's Human Interface Guidelines
* would be to set bd = highlightthickness = padx = 0 and to specify an
* explicit width for the button. Apple also recommends using the same width
* for all Pop-Up Buttons in a given window.
*/
#define LEFT_INSET 8
#define RIGHT_INSET 28
#define MIN_HEIGHT 22
/*
*----------------------------------------------------------------------
*
* TkpCreateMenuButton --
* TkpCreateMenuButton --
*
* Allocate a new TkMenuButton structure.
*
* Results:
* Returns a newly allocated TkMenuButton structure.
*
* Side effects:
* Registers an event handler for the widget.
*
*----------------------------------------------------------------------
*/
TkMenuButton *
TkpCreateMenuButton(
Tk_Window tkwin)
{
MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton));
Tk_CreateEventHandler(tkwin, ActivateMask,
MenuButtonEventProc, (ClientData) mbPtr);
Tk_CreateEventHandler(tkwin, ActivateMask, MenuButtonEventProc,
(ClientData) mbPtr);
mbPtr->flags = FIRST_DRAW;
mbPtr->btnkind = kThemePopupButton;
bzero(&mbPtr->drawinfo, sizeof(mbPtr->drawinfo));
bzero(&mbPtr->lastdrawinfo, sizeof(mbPtr->lastdrawinfo));
return (TkMenuButton *) mbPtr;
}
/*
*----------------------------------------------------------------------
*
* TkpDisplayMenuButton --
|
︙ | | |
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
+
-
+
|
/*
*----------------------------------------------------------------------
*
* TkpDestroyMenuButton --
*
* Free data structures associated with the menubutton control.
* This is a no-op on the Mac.
*
* Results:
* None.
*
* Side effects:
* Restores the default control state.
* None.
*
*----------------------------------------------------------------------
*/
void
TkpDestroyMenuButton(
TkMenuButton *mbPtr)
|
︙ | | |
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
-
-
-
-
+
-
+
-
-
-
+
+
-
-
-
+
|
*/
void
TkpComputeMenuButtonGeometry(butPtr)
register TkMenuButton *butPtr; /* Widget record for menu button. */
{
int width, height, avgWidth, haveImage = 0, haveText = 0;
MacMenuButton *mbPtr = (MacMenuButton*)butPtr;
int txtWidth, txtHeight;
Tk_FontMetrics fm;
DrawParams drawParams;
int paddingx = 0;
int paddingy = 0;
int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0;
/*
* First figure out the size of the contents of the button.
* First compute the size of the contents of the button.
*/
width = 0;
height = 0;
txtWidth = 0;
txtHeight = 0;
avgWidth = 0;
TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
if (butPtr->image != NULL) {
Tk_SizeOfImage(butPtr->image, &width, &height);
haveImage = 1;
} else if (butPtr->bitmap != None) {
Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
haveImage = 1;
}
if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) {
if (butPtr->text && strlen(butPtr->text) > 0) {
haveText = 1;
Tk_FreeTextLayout(butPtr->textLayout);
butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
butPtr->text, -1, butPtr->wrapLength,
butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight);
txtWidth = butPtr->textWidth;
txtHeight = butPtr->textHeight;
avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
Tk_GetFontMetrics(butPtr->tkfont, &fm);
haveText = (txtWidth != 0 && txtHeight != 0);
}
/*
* If the button is compound (ie, it shows both an image and text),
* the new geometry is a combination of the image and text geometry.
* We only honor the compound bit if the button has both text and an
* image, because otherwise it is not really a compound button.
*/
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
if (haveImage && haveText) {
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM: {
/*
* Image is above or below text
*/
|
︙ | | |
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
|
-
+
-
+
-
+
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
|
width = butPtr->width;
}
if (butPtr->height > 0) {
height = butPtr->height;
}
} else {
if (haveImage) {
if (haveImage) { /* Image only */
if (butPtr->width > 0) {
width = butPtr->width;
}
if (butPtr->height > 0) {
height = butPtr->height;
}
} else {
} else { /* Text only */
width = txtWidth;
height = txtHeight;
if (butPtr->width > 0) {
width = butPtr->width * avgWidth;
width = butPtr->width * avgWidth + 2*butPtr->padX;
}
if (butPtr->height > 0) {
height = butPtr->height * fm.linespace;
height = butPtr->height * fm.linespace + 2*butPtr->padY;
}
}
}
width += 2 * butPtr->padX - 2;
height += 2 * butPtr->padY - 2;
/*Add padding for button arrows.*/
width += 22;
/*
* Now figure out the size of the border decorations for the button.
*/
if (butPtr->highlightWidth < 0) {
butPtr->highlightWidth = 0;
}
butPtr->inset = 0;
butPtr->inset = highlightWidth + butPtr->borderWidth;
butPtr->inset += butPtr->highlightWidth;
width += LEFT_INSET + RIGHT_INSET + 2*butPtr->inset;
TkMacOSXComputeMenuButtonDrawParams(butPtr,&drawParams);
HIRect tmpRect;
HIRect contBounds;
tmpRect = CGRectMake(0, 0, width, height);
HIThemeGetButtonContentBounds(&tmpRect, &mbPtr->drawinfo, &contBounds);
/* If the content region has a minimum height, match it. */
if (height < contBounds.size.height) {
height = contBounds.size.height;
}
/* If the content region has a minimum width, match it. */
if (width < contBounds.size.width) {
width = contBounds.size.width;
}
/* Pad to fill difference between content bounds and button bounds. */
paddingx = tmpRect.origin.x - contBounds.origin.x;
paddingy = tmpRect.origin.y - contBounds.origin.y;
if (paddingx > 0) {
width += paddingx;
}
if (paddingy > 0) {
height += paddingy;
height += 2*butPtr->inset;
}
height = height < MIN_HEIGHT ? MIN_HEIGHT : height;
width += butPtr->inset*2;
height += butPtr->inset*2;
Tk_GeometryRequest(butPtr->tkwin, width, height);
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}
/*
*----------------------------------------------------------------------
*
|
︙ | | |
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
|
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
|
-
-
+
+
-
-
+
+
|
imageHeight = height;
if (mbPtr->drawinfo.state == kThemeStatePressed) {
/* Offset bitmaps by a bit when the button is pressed. */
pressed = 1;
}
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0);
if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) {
int x = 0;
int y = 0;
textXOffset = 0;
textYOffset = 0;
fullWidth = 0;
fullHeight = 0;
switch ((enum compound) butPtr->compound) {
case COMPOUND_TOP:
case COMPOUND_BOTTOM: {
/* Image is above or below text */
if (butPtr->compound == COMPOUND_TOP) {
textYOffset = height + butPtr->padY;
} else {
imageYOffset = butPtr->textHeight + butPtr->padY;
}
fullHeight = height + butPtr->textHeight + butPtr->padY;
fullWidth = (width > butPtr->textWidth ? width :
butPtr->textWidth);
fullWidth = (width > butPtr->textWidth ?
width : butPtr->textWidth);
textXOffset = (fullWidth - butPtr->textWidth)/2;
imageXOffset = (fullWidth - width)/2;
break;
}
case COMPOUND_LEFT:
case COMPOUND_RIGHT: {
/*
|
︙ | | |
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
|
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
|
-
-
+
+
-
+
|
imageYOffset = (fullHeight - height)/2;
break;
}
case COMPOUND_NONE: {break;}
}
TkComputeAnchor(butPtr->anchor, tkwin,
butPtr->padX + butPtr->borderWidth,
butPtr->padY + butPtr->borderWidth,
butPtr->padX + butPtr->inset,
butPtr->padY + butPtr->inset,
fullWidth, fullHeight, &x, &y);
imageXOffset += x;
imageXOffset = LEFT_INSET;
imageYOffset += y;
textYOffset -= 1;
if (butPtr->image != NULL) {
Tk_RedrawImage(butPtr->image, 0, 0, width,
height, pixmap, imageXOffset, imageYOffset);
} else {
|
︙ | | |
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
|
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
|
-
-
+
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
-
+
|
x + textXOffset, y + textYOffset, 0, -1);
Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc,
butPtr->textLayout,
x + textXOffset, y + textYOffset,
butPtr->underline);
} else {
if (haveImage) {
int x = 0;
int y;
int x, y;
TkComputeAnchor(butPtr->anchor, tkwin,
butPtr->padX + butPtr->borderWidth,
butPtr->padY + butPtr->borderWidth,
width, height, &x, &y);
imageXOffset += x;
imageYOffset += y;
imageXOffset = LEFT_INSET;
imageYOffset += y;
if (butPtr->image != NULL) {
Tk_RedrawImage(butPtr->image, 0, 0, width, height,
pixmap, imageXOffset, imageYOffset);
if (butPtr->image != NULL) {
Tk_RedrawImage(butPtr->image, 0, 0, width, height,
pixmap, imageXOffset, imageYOffset);
} else {
XSetClipOrigin(butPtr->display, dpPtr->gc, x, y);
XCopyPlane(butPtr->display, butPtr->bitmap,
pixmap, dpPtr->gc,
0, 0, (unsigned int) width,
(unsigned int) height,
imageXOffset, imageYOffset, 1);
pixmap, dpPtr->gc,
0, 0, (unsigned int) width,
(unsigned int) height,
imageXOffset, imageYOffset, 1);
XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0);
}
} else {
/*Move x back by eight pixels to give the menubutton arrows room.*/
int x = 0;
int y;
textXOffset = 8;
int x, y;
textXOffset = LEFT_INSET;
TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
butPtr->textWidth, butPtr->textHeight, &x, &y);
Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc,
butPtr->textLayout, x - textXOffset, y, 0, -1);
butPtr->textLayout, textXOffset, y, 0, -1);
y += butPtr->textHeight/2;
}
}
}
|
︙ | | |
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
|
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
|
-
-
-
+
+
-
-
+
|
static void
TkMacOSXDrawMenuButton(
MacMenuButton *mbPtr, /* Mac menubutton. */
GC gc, /* The GC we are drawing into - needed for
* the bevel button */
Pixmap pixmap) /* The pixmap we are drawing into - needed
* for the bevel button */
{
TkMenuButton * butPtr = ( TkMenuButton *)mbPtr;
TkWindow * winPtr;
HIRect cntrRect;
TkMacOSXDrawingContext dc;
DrawParams* dpPtr = &mbPtr->drawParams;
int useNewerHITools = 1;
winPtr = (TkWindow *)butPtr->tkwin;
TkMacOSXComputeMenuButtonParams(butPtr, &mbPtr->btnkind, &mbPtr->drawinfo);
cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff, Tk_Width(butPtr->tkwin),Tk_Height(butPtr->tkwin));
cntrRect = CGRectMake(winPtr->privatePtr->xOff, winPtr->privatePtr->yOff,
Tk_Width(butPtr->tkwin),
cntrRect = CGRectInset(cntrRect, butPtr->inset, butPtr->inset);
Tk_Height(butPtr->tkwin));
if (useNewerHITools == 1) {
HIRect contHIRec;
static HIThemeButtonDrawInfo hiinfo;
MenuButtonBackgroundDrawCB((MacMenuButton*) mbPtr, 32, true);
|
︙ | | |
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
|
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
|
-
-
+
+
-
-
+
+
-
-
|
hiinfo.value = mbPtr->drawinfo.value;
hiinfo.adornment = mbPtr->drawinfo.adornment;
hiinfo.animation.time.current = CFAbsoluteTimeGetCurrent();
if (hiinfo.animation.time.start == 0) {
hiinfo.animation.time.start = hiinfo.animation.time.current;
}
HIThemeDrawButton(&cntrRect, &hiinfo, dc.context, kHIThemeOrientationNormal, &contHIRec);
HIThemeDrawButton(&cntrRect, &hiinfo, dc.context,
kHIThemeOrientationNormal, &contHIRec);
TkMacOSXRestoreDrawingContext(&dc);
MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo, (MacMenuButton *)mbPtr, 32, true);
MenuButtonContentDrawCB( mbPtr->btnkind, &mbPtr->drawinfo,
(MacMenuButton *)mbPtr, 32, true);
} else {
if (!TkMacOSXSetupDrawingContext(pixmap, dpPtr->gc, 1, &dc)) {
return;
}
TkMacOSXRestoreDrawingContext(&dc);
}
mbPtr->lastdrawinfo = mbPtr->drawinfo;
}
/*
*--------------------------------------------------------------
|
︙ | | |
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
|
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
|
-
-
+
|
{
TkMenuButton *butPtr = (TkMenuButton *)ptr;
Tk_Window tkwin = butPtr->tkwin;
if (tkwin == NULL || !Tk_IsMapped(tkwin)) {
return;
}
DrawMenuButtonImageAndText( butPtr);
DrawMenuButtonImageAndText(butPtr);
}
/*
*--------------------------------------------------------------
*
* MenuButtonEventProc --
*
|
︙ | | |
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
|
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
|
-
+
+
+
+
-
+
-
+
-
-
+
-
-
-
|
* Side effects:
* Sets the btnkind and drawinfo parameters
*
*----------------------------------------------------------------------
*/
static void
TkMacOSXComputeMenuButtonParams(TkMenuButton * butPtr, ThemeButtonKind* btnkind, HIThemeButtonDrawInfo *drawinfo)
TkMacOSXComputeMenuButtonParams(
TkMenuButton * butPtr,
ThemeButtonKind* btnkind,
HIThemeButtonDrawInfo *drawinfo)
{
MacMenuButton *mbPtr = (MacMenuButton *)butPtr;
if (butPtr->image || butPtr->bitmap) {
if (butPtr->image || butPtr->bitmap || butPtr->text) {
/* TODO: allow for Small and Mini menubuttons. */
*btnkind = kThemePopupButton;
} else {
} else { /* This should never happen. */
if (!butPtr->text || !*butPtr->text) {
*btnkind = kThemeArrowButton;
*btnkind = kThemeArrowButton;
} else {
*btnkind = kThemePopupButton;
}
}
drawinfo->value = kThemeButtonOff;
if ((mbPtr->flags & FIRST_DRAW) != 0) {
mbPtr->flags &= ~FIRST_DRAW;
if (Tk_MacOSXIsAppInFront()) {
|
︙ | | |
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
|
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
|
-
-
+
+
-
-
+
-
+
-
-
+
+
+
+
-
-
+
+
-
-
|
}
/*
*----------------------------------------------------------------------
*
* TkMacOSXComputeMenuButtonDrawParams --
*
* This procedure computes the various parameters used
* when drawing a button
* This procedure selects an appropriate drawing context for
* drawing a menubutton.
* These are determined by the various tk button parameters
*
* Results:
* 1 if control will be used, 0 otherwise.
* None.
*
* Side effects:
* Sets the button draw parameters
* Sets the button draw parameters.
*
*----------------------------------------------------------------------
*/
static int
TkMacOSXComputeMenuButtonDrawParams(TkMenuButton * butPtr, DrawParams * dpPtr)
static void
TkMacOSXComputeMenuButtonDrawParams(
TkMenuButton * butPtr,
DrawParams * dpPtr)
{
dpPtr->hasImageOrBitmap = ((butPtr->image != NULL)
|| (butPtr->bitmap != None));
dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) ||
(butPtr->bitmap != None));
dpPtr->border = butPtr->normalBorder;
if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) {
dpPtr->gc = butPtr->disabledGC;
} else if (butPtr->state == STATE_ACTIVE) {
dpPtr->gc = butPtr->activeTextGC;
dpPtr->border = butPtr->activeBorder;
} else {
dpPtr->gc = butPtr->normalTextGC;
}
return 1;
}
/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
* fill-column: 79
* coding: utf-8
* End:
*/
|
︙ | | |
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
|
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
|
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
|
}
/*
*----------------------------------------------------------------------
*
* TkpPostMenu --
*
* Posts a menu on the screen
* Posts a menu on the screen so that the top left corner of the
* specified entry is located at the point (x, y) in screen coordinates.
* If the entry parameter is negative, the upper left corner of the
* menu itself is placed at the point.
*
* Results:
* None.
*
* Side effects:
* The menu is posted and handled.
*
*----------------------------------------------------------------------
*/
int
TkpPostMenu(
Tcl_Interp *interp,
TkMenu *menuPtr,
int x, int y)
int x, int y, int index)
{
HMENU winMenuHdl = (HMENU) menuPtr->platformData;
int result, flags;
RECT noGoawayRect;
POINT point;
Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin);
int oldServiceMode = Tcl_GetServiceMode();
ThreadSpecificData *tsdPtr =
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
tsdPtr->inPostMenu++;
CallPendingReconfigureImmediately(menuPtr);
result = TkPreprocessMenu(menuPtr);
if (result != TCL_OK) {
tsdPtr->inPostMenu--;
return result;
}
if (index >= menuPtr->numEntries) {
index = menuPtr->numEntries - 1;
}
if (index >= 0) {
y -= menuPtr->entries[index]->y;
}
/*
* The post commands could have deleted the menu, which means
* we are dead and should go away.
*/
if (menuPtr->tkwin == NULL) {
|
︙ | | |
833
834
835
836
837
838
839
840
841
842
843
844
845
846
|
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
Tk_PointerEvent(NULL, point.x, point.y);
if (tsdPtr->inPostMenu) {
tsdPtr->inPostMenu = 0;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpPostTearoffMenu --
*
* Posts a tearoff menu on the screen so that the top left corner of the
* specified entry is located at the point (x, y) in screen coordinates.
* If the index parameter is negative, the upper left corner of the menu
* itself is placed at the point. Adjusts the menu's position so that it
* fits on the screen, and maps and raises the menu.
*
* Results:
* Returns a standard Tcl Error.
*
* Side effects:
* The menu is posted.
*
*----------------------------------------------------------------------
*/
int
TkpPostTearoffMenu(
Tcl_Interp *interp, /* The interpreter of the menu */
TkMenu *menuPtr, /* The menu we are posting */
int x, int y, int index) /* The root X,Y coordinates where we are
* posting */
{
int vRootX, vRootY, vRootWidth, vRootHeight;
int result;
if (index >= menuPtr->numEntries) {
index = menuPtr->numEntries - 1;
}
if (index >= 0) {
y -= menuPtr->entries[index]->y;
}
TkActivateMenuEntry(menuPtr, -1);
TkRecomputeMenu(menuPtr);
result = TkPostCommand(menuPtr);
if (result != TCL_OK) {
return result;
}
/*
* The post commands could have deleted the menu, which means we are dead
* and should go away.
*/
if (menuPtr->tkwin == NULL) {
return TCL_OK;
}
/*
* Adjust the position of the menu if necessary to keep it visible on the
* screen. There are two special tricks to make this work right:
*
* 1. If a virtual root window manager is being used then the coordinates
* are in the virtual root window of menuPtr's parent; since the menu
* uses override-redirect mode it will be in the *real* root window for
* the screen, so we have to map the coordinates from the virtual root
* (if any) to the real root. Can't get the virtual root from the menu
* itself (it will never be seen by the wm) so use its parent instead
* (it would be better to have an an option that names a window to use
* for this...).
* 2. The menu may not have been mapped yet, so its current size might be
* the default 1x1. To compute how much space it needs, use its
* requested size, not its actual size.
*/
Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
&vRootWidth, &vRootHeight);
vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
if (x > vRootX + vRootWidth) {
x = vRootX + vRootWidth;
}
if (x < vRootX) {
x = vRootX;
}
vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
if (y > vRootY + vRootHeight) {
y = vRootY + vRootHeight;
}
if (y < vRootY) {
y = vRootY;
}
Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
if (!Tk_IsMapped(menuPtr->tkwin)) {
Tk_MapWindow(menuPtr->tkwin);
}
TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TkpMenuNewEntry --
*
* Adds a pointer to a new menu entry structure with the platform-
|
︙ | | |
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
|
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
|
-
|
GetMenuSeparatorGeometry(menuPtr, menuPtr->entries[i], tkfont,
fmPtr, &width, &height);
menuPtr->entries[i]->height = height;
} else if (menuPtr->entries[i]->type == TEAROFF_ENTRY) {
GetTearoffEntryGeometry(menuPtr, menuPtr->entries[i], tkfont,
fmPtr, &width, &height);
menuPtr->entries[i]->height = height;
} else {
/*
* For each entry, compute the height required by that particular
* entry, plus three widths: the width of the label, the width to
* allow for an indicator to be displayed to the left of the label
* (if any), and the width of the accelerator to be displayed to
* the right of the label (if any). These sizes depend, of course,
|
︙ | | |
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
|
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
|
-
-
|
menuPtr->entries[j]->width = indicatorSpace + labelWidth
+ accelWidth + 2 * activeBorderWidth;
menuPtr->entries[j]->x = x;
menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN;
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth
+ 2 * activeBorderWidth + borderWidth;
windowHeight += borderWidth;
/*
* The X server doesn't like zero dimensions, so round up to at least 1 (a
* zero-sized menu should never really occur, anyway).
*/
|
︙ | | |