Import Tk 8.6.10
This commit is contained in:
@@ -110,6 +110,11 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
|
||||
#pragma mark TKMenu
|
||||
|
||||
/*
|
||||
* This interface is not declared in tkMacOSXPrivate.h because it requires
|
||||
* tkMenu.h.
|
||||
*/
|
||||
|
||||
@interface TKMenu(TKMenuPrivate)
|
||||
- (id) initWithTkMenu: (TkMenu *) tkMenu;
|
||||
- (TkMenu *) tkMenu;
|
||||
@@ -117,10 +122,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) insertItem: (NSMenuItem *) newItem atTkIndex: (NSInteger) index;
|
||||
@end
|
||||
|
||||
#define TKMenu_NSMenuDelegate <NSMenuDelegate>
|
||||
@interface TKMenu(TKMenuDelegate) TKMenu_NSMenuDelegate
|
||||
@end
|
||||
|
||||
@implementation TKMenu
|
||||
- (void) setSpecial: (NSUInteger) special
|
||||
{
|
||||
@@ -192,10 +193,10 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) insertItem: (NSMenuItem *) newItem atIndex: (NSInteger) index
|
||||
{
|
||||
if (_tkMenu && index >= 0) {
|
||||
if ((NSUInteger)index <= _tkOffset) {
|
||||
if ((NSUInteger) index <= _tkOffset) {
|
||||
_tkOffset++;
|
||||
} else {
|
||||
NSAssert((NSUInteger)index >= _tkItemCount + _tkOffset,
|
||||
NSAssert((NSUInteger) index >= _tkItemCount + _tkOffset,
|
||||
@"Cannot insert in the middle of Tk menu");
|
||||
}
|
||||
}
|
||||
@@ -205,9 +206,9 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
- (void) removeItemAtIndex: (NSInteger) index
|
||||
{
|
||||
if (_tkMenu && index >= 0) {
|
||||
if ((NSUInteger)index < _tkOffset) {
|
||||
if ((NSUInteger) index < _tkOffset) {
|
||||
_tkOffset--;
|
||||
} else if ((NSUInteger)index < _tkItemCount + _tkOffset) {
|
||||
} else if ((NSUInteger) index < _tkItemCount + _tkOffset) {
|
||||
_tkItemCount--;
|
||||
}
|
||||
}
|
||||
@@ -220,20 +221,22 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
action:@selector(tkMenuItemInvoke:) keyEquivalent:@""];
|
||||
|
||||
[menuItem setTarget:self];
|
||||
[menuItem setTag:(NSInteger)mePtr];
|
||||
[menuItem setTag:(NSInteger) mePtr];
|
||||
return menuItem;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation TKMenu(TKMenuActions)
|
||||
// target methods
|
||||
|
||||
- (BOOL) validateMenuItem: (NSMenuItem *) menuItem
|
||||
{
|
||||
return [menuItem isEnabled];
|
||||
}
|
||||
|
||||
// Workaround for bug 3572016; leaves menu items enabled during modal dialog.
|
||||
/*
|
||||
* Workaround for bug 3572016; leave menu items enabled during modal dialog.
|
||||
*/
|
||||
|
||||
- (BOOL)worksWhenModal
|
||||
{
|
||||
return YES;
|
||||
@@ -243,22 +246,25 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
{
|
||||
/*
|
||||
* With the delegate matching key equivalents, when a menu action is sent
|
||||
* in response to a key equivalent, sender is the whole menu and not the
|
||||
* the specific menu item, use this to ignore key equivalents for our
|
||||
* in response to a key equivalent, the sender is the whole menu and not the
|
||||
* specific menu item. We use this to ignore key equivalents for Tk
|
||||
* menus (as Tk handles them directly via bindings).
|
||||
*/
|
||||
|
||||
if ([sender isKindOfClass:[NSMenuItem class]]) {
|
||||
NSMenuItem *menuItem = (NSMenuItem *)sender;
|
||||
TkMenu *menuPtr = (TkMenu *)_tkMenu;
|
||||
TkMenuEntry *mePtr = (TkMenuEntry *)[menuItem tag];
|
||||
NSMenuItem *menuItem = (NSMenuItem *) sender;
|
||||
TkMenu *menuPtr = (TkMenu *) _tkMenu;
|
||||
TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag];
|
||||
|
||||
if (menuPtr && mePtr) {
|
||||
Tcl_Interp *interp = menuPtr->interp;
|
||||
/*Add time for errors to fire if necessary. This is sub-optimal
|
||||
*but avoids issues with Tcl/Cocoa event loop integration.
|
||||
|
||||
/*
|
||||
* Add time for errors to fire if necessary. This is sub-optimal
|
||||
* but avoids issues with Tcl/Cocoa event loop integration.
|
||||
*/
|
||||
Tcl_Sleep(100);
|
||||
|
||||
//Tcl_Sleep(100);
|
||||
Tcl_Preserve(interp);
|
||||
Tcl_Preserve(menuPtr);
|
||||
|
||||
@@ -277,40 +283,55 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
@end
|
||||
|
||||
@implementation TKMenu(TKMenuDelegate)
|
||||
#define keyEquivModifiersMatch(km, m) (( \
|
||||
((km) & NSCommandKeyMask) != ((m) & NSCommandKeyMask) || \
|
||||
((km) & NSAlternateKeyMask) != ((m) & NSAlternateKeyMask) || \
|
||||
((km) & NSControlKeyMask) != ((m) & NSControlKeyMask) || \
|
||||
(((km) & NSShiftKeyMask) != ((m) & NSShiftKeyMask) && \
|
||||
((m) & NSFunctionKeyMask))) ? NO : YES)
|
||||
|
||||
- (BOOL) menuHasKeyEquivalent: (NSMenu *) menu forEvent: (NSEvent *) event
|
||||
target: (id *) target action: (SEL *) action
|
||||
{
|
||||
/*Use lowercaseString to keep "shift" from firing twice if bound to different procedure.*/
|
||||
/*
|
||||
* Use lowercaseString when comparing keyEquivalents since the notion of
|
||||
* a shifted upper case letter does not make much sense.
|
||||
*/
|
||||
|
||||
NSString *key = [[event charactersIgnoringModifiers] lowercaseString];
|
||||
NSUInteger modifiers = [event modifierFlags] &
|
||||
NSDeviceIndependentModifierFlagsMask;
|
||||
|
||||
if (modifiers == (NSCommandKeyMask | NSShiftKeyMask) &&
|
||||
[key compare:@"?"] == NSOrderedSame) {
|
||||
return NO;
|
||||
}
|
||||
/*
|
||||
* Command-Shift-? has not been allowed as a keyboard equivalent since
|
||||
* the first aqua port, for some mysterious reason.
|
||||
*/
|
||||
|
||||
// For command key, take input manager's word so things
|
||||
// like dvorak / qwerty layout work.
|
||||
if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
|
||||
key = [event characters];
|
||||
return NO;
|
||||
} else if (modifiers == (NSControlKeyMask | NSShiftKeyMask) &&
|
||||
[event keyCode] == 48) {
|
||||
/*
|
||||
* Starting with OSX 10.12 Control-Tab and Control-Shift-Tab are used
|
||||
* to select window tabs. But for some even more mysterious reason the
|
||||
* Control-Shift-Tab event has character 0x19 = NSBackTabCharacter
|
||||
* rather than 0x09 = NSTabCharacter. At the same time, the
|
||||
* keyEquivalent must be \0x09 in order for it to be displayed
|
||||
* correctly in the menu. This makes it impossible for the standard
|
||||
* "Select Previous Tab" to work correctly, unless we intervene.
|
||||
*/
|
||||
|
||||
key = @"\t";
|
||||
} else if (([event modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) {
|
||||
/*
|
||||
* If the command modifier is set, use the full character string so
|
||||
* things like the dvorak / qwerty layout will work.
|
||||
*/
|
||||
|
||||
key = [event characters];
|
||||
}
|
||||
|
||||
NSArray *itemArray = [self itemArray];
|
||||
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
if ([item isEnabled] && [[item keyEquivalent] compare:key] ==
|
||||
NSOrderedSame) {
|
||||
if ([item isEnabled] &&
|
||||
[[item keyEquivalent] compare:key] == NSOrderedSame) {
|
||||
NSUInteger keyEquivModifiers = [item keyEquivalentModifierMask];
|
||||
|
||||
if (keyEquivModifiersMatch(keyEquivModifiers, modifiers)) {
|
||||
if (keyEquivModifiers == modifiers) {
|
||||
*target = [item target];
|
||||
*action = [item action];
|
||||
return YES;
|
||||
@@ -367,10 +388,6 @@ static int ModifierCharWidth(Tk_Font tkfont);
|
||||
|
||||
#pragma mark TKApplication(TKMenu)
|
||||
|
||||
@interface NSApplication(TKMenu)
|
||||
- (void) setAppleMenu: (NSMenu *) menu;
|
||||
@end
|
||||
|
||||
@implementation TKApplication(TKMenu)
|
||||
|
||||
- (void) menuBeginTracking: (NSNotification *) notification
|
||||
@@ -611,6 +628,10 @@ TkpConfigureMenuEntry(
|
||||
&imageHeight);
|
||||
image = TkMacOSXGetNSImageWithBitmap(mePtr->menuPtr->display, bitmap,
|
||||
gc, imageWidth, imageHeight);
|
||||
if (gc->foreground == defaultFg) {
|
||||
// Use a semantic foreground color by default
|
||||
[image setTemplate:YES];
|
||||
}
|
||||
}
|
||||
[menuItem setImage:image];
|
||||
if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr &&
|
||||
@@ -633,7 +654,7 @@ TkpConfigureMenuEntry(
|
||||
gc->foreground!=defaultFg? gc->foreground:gc->background);
|
||||
|
||||
attributes = [[attributes mutableCopy] autorelease];
|
||||
[(NSMutableDictionary *)attributes setObject:color
|
||||
[(NSMutableDictionary *) attributes setObject:color
|
||||
forKey:NSForegroundColorAttributeName];
|
||||
}
|
||||
if (attributes) {
|
||||
@@ -673,21 +694,31 @@ TkpConfigureMenuEntry(
|
||||
[submenu setTitle:title];
|
||||
|
||||
if ([menuItem isEnabled]) {
|
||||
/* This menuItem might have been previously disabled (XXX:
|
||||
track this), which would have disabled entries; we must
|
||||
re-enable the entries here. */
|
||||
int i = 0;
|
||||
NSArray *itemArray = [submenu itemArray];
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
|
||||
/* Work around an apparent bug where itemArray can have
|
||||
more items than the menu's entries[] array. */
|
||||
if (i >= menuRefPtr->menuPtr->numEntries) break;
|
||||
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This menuItem might have been previously disabled (XXX:
|
||||
* track this), which would have disabled entries; we must
|
||||
* re-enable the entries here.
|
||||
*/
|
||||
|
||||
int i = 0;
|
||||
NSArray *itemArray = [submenu itemArray];
|
||||
|
||||
for (NSMenuItem *item in itemArray) {
|
||||
TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
|
||||
|
||||
/*
|
||||
* Work around an apparent bug where itemArray can have
|
||||
* more items than the menu's entries[] array.
|
||||
*/
|
||||
|
||||
if (i >= (int) menuRefPtr->menuPtr->numEntries) {
|
||||
break;
|
||||
}
|
||||
[item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,10 +769,13 @@ TkpDestroyMenuEntry(
|
||||
*
|
||||
* 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.
|
||||
@@ -753,54 +787,174 @@ 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)
|
||||
{
|
||||
|
||||
|
||||
/* Get the object that holds this Tk Window.*/
|
||||
Tk_Window root;
|
||||
root = Tk_MainWindow(interp);
|
||||
if (root == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Drawable d = Tk_WindowId(root);
|
||||
NSView *rootview = TkMacOSXGetRootControl(d);
|
||||
NSWindow *win = [rootview window];
|
||||
int result;
|
||||
Tk_Window realWin = menuPtr->tkwin;
|
||||
TkWindow *realWinPtr;
|
||||
NSView *realWinView;
|
||||
|
||||
while (1) {
|
||||
if (realWin == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Fix for bug 07cfc9f03e: use the view for the parent real (non-menu)
|
||||
* toplevel window, rather than always using the root window.
|
||||
* This allows menus to appear on a separate monitor than the root
|
||||
* window, and to use the appearance of their parent real window
|
||||
* rather than the appearance of the root window.
|
||||
*/
|
||||
realWinPtr = (TkWindow*) realWin;
|
||||
realWinView = TkMacOSXDrawableView(realWinPtr->privatePtr);
|
||||
if (realWinView != nil) {
|
||||
break;
|
||||
}
|
||||
realWin = Tk_Parent(realWin);
|
||||
}
|
||||
NSWindow *win = [realWinView window];
|
||||
NSView *view = [win contentView];
|
||||
NSMenu *menu = (NSMenu *) menuPtr->platformData;
|
||||
NSInteger itemIndex = index;
|
||||
NSInteger numItems = [menu numberOfItems];
|
||||
NSMenuItem *item = nil;
|
||||
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;
|
||||
}
|
||||
if (itemIndex >= 0) {
|
||||
item = [menu itemAtIndex:itemIndex];
|
||||
}
|
||||
|
||||
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
|
||||
NSView *view = [win contentView];
|
||||
NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1);
|
||||
/*
|
||||
* The post commands could have deleted the menu, which means we are dead
|
||||
* and should go away.
|
||||
*/
|
||||
|
||||
frame.origin = [view convertPoint:
|
||||
[win tkConvertPointFromScreen:frame.origin] fromView:nil];
|
||||
if (menuPtr->tkwin == NULL) {
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
NSMenu *menu = (NSMenu *) menuPtr->platformData;
|
||||
NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc]
|
||||
initTextCell:@"" pullsDown:NO];
|
||||
|
||||
[popUpButtonCell setAltersStateOfSelectedItem:NO];
|
||||
[popUpButtonCell setMenu:menu];
|
||||
[popUpButtonCell selectItem:nil];
|
||||
[popUpButtonCell performClickWithFrame:frame inView:view];
|
||||
[popUpButtonCell release];
|
||||
Tcl_SetServiceMode(oldMode);
|
||||
[menu popUpMenuPositioningItem:item
|
||||
atLocation:[win tkConvertPointFromScreen:location]
|
||||
inView:view];
|
||||
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 >= (int) 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;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -835,12 +989,12 @@ TkpSetWindowMenuBar(
|
||||
*
|
||||
* TkpSetMainMenubar --
|
||||
*
|
||||
* Puts the menu associated with a window into the menubar. Should only
|
||||
* be called when the window is in front.
|
||||
* Puts the menu associated with a window into the menubar. Should only be
|
||||
* called when the window is in front.
|
||||
*
|
||||
* This is a no-op on all other platforms. On OS X it is a no-op when
|
||||
* passed a NULL menuName or a nonexistent menuName, with an exception
|
||||
* for the first call in a new interpreter. In that special case, passing a
|
||||
* passed a NULL menuName or a nonexistent menuName, with an exception for
|
||||
* the first call in a new interpreter. In that special case, passing a
|
||||
* NULL menuName installs the default menu.
|
||||
*
|
||||
* Results:
|
||||
@@ -860,15 +1014,32 @@ TkpSetMainMenubar(
|
||||
{
|
||||
static Tcl_Interp *currentInterp = NULL;
|
||||
TKMenu *menu = nil;
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
|
||||
/*
|
||||
* We will be called when an embedded window receives an ActivationNotify
|
||||
* event, but we should not change the menubar in that case.
|
||||
*/
|
||||
|
||||
if (Tk_IsEmbedded(winPtr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (menuName) {
|
||||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||||
Tk_Window menubar = NULL;
|
||||
|
||||
if (winPtr->wmInfoPtr && winPtr->wmInfoPtr->menuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin &&
|
||||
!strcmp(menuName, Tk_PathName(
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin))) {
|
||||
if (winPtr->wmInfoPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr &&
|
||||
winPtr->wmInfoPtr->menuPtr->masterMenuPtr) {
|
||||
menubar = winPtr->wmInfoPtr->menuPtr->masterMenuPtr->tkwin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find the NSMenu directly. If that fails, ask Tk to find
|
||||
* it.
|
||||
*/
|
||||
|
||||
if (menubar != NULL && strcmp(menuName, Tk_PathName(menubar)) == 0) {
|
||||
menu = (TKMenu *) winPtr->wmInfoPtr->menuPtr->platformData;
|
||||
} else {
|
||||
TkMenuReferences *menuRefPtr = TkFindMenuReferences(interp,
|
||||
@@ -880,6 +1051,12 @@ TkpSetMainMenubar(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we couldn't find a menu, do nothing unless the window belongs to a
|
||||
* different application. In that case, install the default menubar.
|
||||
*/
|
||||
|
||||
if (menu || interp != currentInterp) {
|
||||
[NSApp tkSetMainMenu:menu];
|
||||
}
|
||||
@@ -892,8 +1069,8 @@ TkpSetMainMenubar(
|
||||
* CheckForSpecialMenu --
|
||||
*
|
||||
* Given a menu, check to see whether or not it is a cascade in a menubar
|
||||
* with one of the special names .apple, .help or .window If it is, the
|
||||
* entry that points to this menu will be marked.
|
||||
* with one of the special names ".apple", ".help" or ".window". If it is,
|
||||
* the entry that points to this menu will be marked.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1070,26 +1247,32 @@ void
|
||||
TkpComputeStandardMenuGeometry(
|
||||
TkMenu *menuPtr) /* Structure describing menu. */
|
||||
{
|
||||
NSSize menuSize;
|
||||
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) {
|
||||
/*
|
||||
* Do nothing if this menu is a clone.
|
||||
*/
|
||||
|
||||
if (menuPtr->tkwin == NULL || menuPtr->masterMenuPtr != menuPtr) {
|
||||
return;
|
||||
}
|
||||
|
||||
menuSize = [(NSMenu *) menuPtr->platformData size];
|
||||
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;
|
||||
|
||||
/*
|
||||
@@ -1097,16 +1280,16 @@ TkpComputeStandardMenuGeometry(
|
||||
* 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
|
||||
* font set, then we give the geometry/drawing routines the menu's font
|
||||
* and metrics. If an entry has its own font, we will measure that font
|
||||
* and give all of the geometry/drawing the entry's font and metrics.
|
||||
* font set, then we give the geometry/drawing routines the menu's font and
|
||||
* metrics. If an entry has its own font, we will measure that font and
|
||||
* give all of the geometry/drawing the entry's font and metrics.
|
||||
*/
|
||||
|
||||
menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
|
||||
Tk_GetFontMetrics(menuFont, &menuMetrics);
|
||||
menuModifierCharWidth = ModifierCharWidth(menuFont);
|
||||
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
mePtr = menuPtr->entries[i];
|
||||
if (mePtr->type == CASCADE_ENTRY || mePtr->accelLength > 0) {
|
||||
haveAccel = 1;
|
||||
@@ -1114,8 +1297,11 @@ TkpComputeStandardMenuGeometry(
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
mePtr = menuPtr->entries[i];
|
||||
if (mePtr->type == TEAROFF_ENTRY) {
|
||||
continue;
|
||||
}
|
||||
if (mePtr->fontPtr == NULL) {
|
||||
tkfont = menuFont;
|
||||
fmPtr = &menuMetrics;
|
||||
@@ -1126,26 +1312,8 @@ TkpComputeStandardMenuGeometry(
|
||||
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 {
|
||||
/*
|
||||
@@ -1163,12 +1331,14 @@ TkpComputeStandardMenuGeometry(
|
||||
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];
|
||||
@@ -1180,11 +1350,8 @@ TkpComputeStandardMenuGeometry(
|
||||
size = [[menuItem title] sizeWithAttributes:
|
||||
TkMacOSXNSFontAttributesForFont(tkfont)];
|
||||
}
|
||||
size.width += menuTextLeadingEdgeMargin +
|
||||
menuTextTrailingEdgeMargin;
|
||||
if (size.height < fmPtr->linespace) {
|
||||
size.height = fmPtr->linespace;
|
||||
}
|
||||
size.width += menuTextLeadingEdgeMargin + menuTextTrailingEdgeMargin;
|
||||
size.height -= 1; /* tweak */
|
||||
if (haveImage && (mePtr->compound != COMPOUND_NONE)) {
|
||||
int margin = width + menuIconTrailingEdgeMargin;
|
||||
|
||||
@@ -1200,9 +1367,11 @@ TkpComputeStandardMenuGeometry(
|
||||
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) {
|
||||
@@ -1233,30 +1402,18 @@ TkpComputeStandardMenuGeometry(
|
||||
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
|
||||
+ 2 * activeBorderWidth + borderWidth;
|
||||
windowHeight += borderWidth;
|
||||
|
||||
windowWidth = menuSize.width;
|
||||
if (windowWidth <= 0) {
|
||||
windowWidth = 1;
|
||||
}
|
||||
windowHeight = menuSize.height;
|
||||
if (windowHeight <= 0) {
|
||||
windowHeight = 1;
|
||||
}
|
||||
@@ -1290,7 +1447,7 @@ GenerateMenuSelectEvent(
|
||||
if (menuPtr) {
|
||||
int index = [menu tkIndexOfItem:menuItem];
|
||||
|
||||
if (index < 0 || index >= menuPtr->numEntries ||
|
||||
if (index < 0 || index >= (int) menuPtr->numEntries ||
|
||||
(menuPtr->entries[index])->state == ENTRY_DISABLED) {
|
||||
TkActivateMenuEntry(menuPtr, -1);
|
||||
} else {
|
||||
@@ -1369,7 +1526,7 @@ RecursivelyClearActiveMenu(
|
||||
int i;
|
||||
|
||||
TkActivateMenuEntry(menuPtr, -1);
|
||||
for (i = 0; i < menuPtr->numEntries; i++) {
|
||||
for (i = 0; i < (int) menuPtr->numEntries; i++) {
|
||||
TkMenuEntry *mePtr = menuPtr->entries[i];
|
||||
|
||||
if (mePtr->type == CASCADE_ENTRY
|
||||
@@ -1404,7 +1561,10 @@ TkMacOSXClearMenubarActive(void)
|
||||
if (mainMenu && [mainMenu isKindOfClass:[TKMenu class]]) {
|
||||
TkMenu *menuPtr = [(TKMenu *) mainMenu tkMenu];
|
||||
|
||||
if (menuPtr && menuPtr->numEntries && menuPtr->entries) {
|
||||
if (menuPtr &&
|
||||
!(menuPtr->menuFlags & MENU_DELETION_PENDING) &&
|
||||
menuPtr->numEntries > 0 &&
|
||||
menuPtr->entries != NULL) {
|
||||
RecursivelyClearActiveMenu(menuPtr);
|
||||
}
|
||||
}
|
||||
@@ -1464,10 +1624,10 @@ TkpMenuInit(void)
|
||||
#undef observe
|
||||
|
||||
[NSMenuItem setUsesUserKeyEquivalents:NO];
|
||||
tkColPtr = TkpGetColor(None, DEF_MENU_BG_COLOR);
|
||||
tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR);
|
||||
defaultBg = tkColPtr->color.pixel;
|
||||
ckfree(tkColPtr);
|
||||
tkColPtr = TkpGetColor(None, DEF_MENU_FG);
|
||||
tkColPtr = TkpGetColor(NULL, DEF_MENU_FG);
|
||||
defaultFg = tkColPtr->color.pixel;
|
||||
ckfree(tkColPtr);
|
||||
|
||||
@@ -1658,7 +1818,7 @@ TkMacOSXPreprocessMenu(void)
|
||||
* TkMacOSXUseID --
|
||||
*
|
||||
* Take the ID out of the available list for new menus. Used by the
|
||||
* default menu bar's menus so that they do not get created at the tk
|
||||
* default menu bar's menus so that they do not get created at the Tk
|
||||
* level. See TkMacOSXGetNewMenuID for more information.
|
||||
*
|
||||
* Results:
|
||||
@@ -1683,8 +1843,7 @@ TkMacOSXUseMenuID(
|
||||
*
|
||||
* TkMacOSXDispatchMenuEvent --
|
||||
*
|
||||
* Given a menu id and an item, dispatches the command associated with
|
||||
* it.
|
||||
* Given a menu id and an item, dispatches the command associated with it.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
@@ -1734,9 +1893,10 @@ TkMacOSXHandleTearoffMenu(void)
|
||||
*
|
||||
* TkMacOSXSetHelpMenuItemCount --
|
||||
*
|
||||
* Has to be called after the first call to InsertMenu. Sets up the
|
||||
* global variable for the number of items in the unmodified help menu.
|
||||
* NB. Nobody uses this any more, since you can get the number of system
|
||||
* Has to be called after the first call to InsertMenu. Sets up the global
|
||||
* variable for the number of items in the unmodified help menu.
|
||||
*
|
||||
* NB: Nobody uses this any more, since you can get the number of system
|
||||
* help items from HMGetHelpMenu trivially. But it is in the stubs
|
||||
* table...
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user