summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
Diffstat (limited to 'macosx')
-rw-r--r--macosx/README6
-rw-r--r--macosx/tkMacOSXClipboard.c23
-rw-r--r--macosx/tkMacOSXDraw.c37
-rw-r--r--macosx/tkMacOSXFont.c29
-rw-r--r--macosx/tkMacOSXInit.c6
-rw-r--r--macosx/tkMacOSXKeyEvent.c301
-rw-r--r--macosx/tkMacOSXKeyboard.c9
-rw-r--r--macosx/tkMacOSXMenus.c2
-rw-r--r--macosx/tkMacOSXMouseEvent.c32
-rw-r--r--macosx/tkMacOSXPrivate.h12
-rw-r--r--macosx/tkMacOSXScrlbr.c12
-rw-r--r--macosx/tkMacOSXServices.c131
-rw-r--r--macosx/tkMacOSXTest.c30
-rw-r--r--macosx/tkMacOSXWindowEvent.c22
-rw-r--r--macosx/tkMacOSXWm.c88
-rw-r--r--macosx/ttkMacOSXTheme.c19
16 files changed, 436 insertions, 323 deletions
diff --git a/macosx/README b/macosx/README
index c2dabae..4989ec7 100644
--- a/macosx/README
+++ b/macosx/README
@@ -49,8 +49,8 @@ brings up the Tk console window at startup. This is the case when double
clicking Wish in the Finder (or using 'open Wish.app' from the Terminal).
- Tcl extensions can be installed in any of:
- $HOME/Library/Tcl /Library/Tcl /System/Library/Tcl
- $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+ $HOME/Library/Tcl /Library/Tcl
+ $HOME/Library/Frameworks /Library/Frameworks
(searched in that order).
Given a potential package directory $pkg, Tcl on OSX checks for the file
$pkg/Resources/Scripts/pkgIndex.tcl as well as the usual $pkg/pkgIndex.tcl.
@@ -65,7 +65,7 @@ No nroff manpages are installed by default by the GNUmakefile.
- The Tcl and Tk frameworks can be installed in any of the system's standard
framework directories:
- $HOME/Library/Frameworks /Library/Frameworks /System/Library/Frameworks
+ $HOME/Library/Frameworks /Library/Frameworks
- ${prefix}/bin/wish8.x is a script that calls a copy of 'Wish' contained in
Tk.framework/Resources
diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c
index 452b32f..6717afa 100644
--- a/macosx/tkMacOSXClipboard.c
+++ b/macosx/tkMacOSXClipboard.c
@@ -130,6 +130,7 @@ TkSelGetSelection(
&& selection == dispPtr->clipboardAtom
&& (target == XA_STRING || target == dispPtr->utf8Atom)) {
NSString *string = nil;
+ NSString *clean;
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSString *type = [pb availableTypeFromArray:[NSArray arrayWithObject:
NSStringPboardType]];
@@ -137,7 +138,27 @@ TkSelGetSelection(
if (type) {
string = [pb stringForType:type];
}
- result = proc(clientData, interp, string ? [string UTF8String] : "");
+ if (string) {
+ /*
+ * Replace all non-BMP characters by the replacement character 0xfffd.
+ * This is a workaround until Tcl supports TCL_UTF_MAX > 3.
+ */
+ int i, j, len = [string length];
+ CFRange all = CFRangeMake(0, len);
+ UniChar *buffer = ckalloc(len*sizeof(UniChar));
+ CFStringGetCharacters((CFStringRef) string, all, buffer);
+ for (i = 0, j = 0 ; j < len ; i++, j++) {
+ if (CFStringIsSurrogateHighCharacter(buffer[j])) {
+ buffer[i] = 0xfffd;
+ j++;
+ } else {
+ buffer[i] = buffer[j];
+ }
+ }
+ clean = (NSString *)CFStringCreateWithCharacters(NULL, buffer, i);
+ ckfree(buffer);
+ result = proc(clientData, interp, [clean UTF8String]);
+ }
} else {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"%s selection doesn't exist or form \"%s\" not defined",
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index af0cc05..724f637 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -501,9 +501,12 @@ TkMacOSXGetNSImageWithTkImage(
int width,
int height)
{
- Pixmap pixmap = Tk_GetPixmap(display, None, width, height, 0);
+ Pixmap pixmap;
NSImage *nsImage;
-
+ if (width == 0 || height == 0) {
+ return nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0,0)];
+ }
+ pixmap = Tk_GetPixmap(display, None, width, height, 0);
Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0);
nsImage = CreateNSImageWithPixmap(pixmap, width, height);
Tk_FreePixmap(display, pixmap);
@@ -1611,16 +1614,36 @@ TkMacOSXSetupDrawingContext(
* a view's drawRect or setFrame methods. The isDrawing attribute
* tells us whether we are being called from one of those methods.
*
- * If the CGContext is not valid, or belongs to a different View, then
- * we mark our view as needing display and return failure. It should
- * get drawn in a later call to drawRect.
+ * If the CGContext is not valid then we mark our view as needing
+ * display in the bounding rectangle of the clipping region and
+ * return failure. That rectangle should get drawn in a later call
+ * to drawRect.
+ *
+ * As an exception to the above, if mouse buttons are pressed at the
+ * moment when we fail to obtain a valid context we schedule the entire
+ * view for a redraw rather than just the clipping region. The purpose
+ * of this is to make sure that scrollbars get updated correctly.
*/
- if (view != [NSView focusView]) {
- [view setNeedsDisplay:YES];
+ if (![NSApp isDrawing] || view != [NSView focusView]) {
+ NSRect bounds = [view bounds];
+ NSRect dirtyNS = bounds;
+ if ([NSEvent pressedMouseButtons]) {
+ [view setNeedsDisplay:YES];
+ } else {
+ CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0,
+ .ty = dirtyNS.size.height};
+ if (dc.clipRgn) {
+ CGRect dirtyCG = NSRectToCGRect(dirtyNS);
+ HIShapeGetBounds(dc.clipRgn, &dirtyCG);
+ dirtyNS = NSRectToCGRect(CGRectApplyAffineTransform(dirtyCG, t));
+ }
+ [view setNeedsDisplayInRect:dirtyNS];
+ }
canDraw = false;
goto end;
}
+
dc.view = view;
dc.context = GET_CGCONTEXT;
dc.portBounds = NSRectToCGRect([view bounds]);
diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c
index 7659163..41da390 100644
--- a/macosx/tkMacOSXFont.c
+++ b/macosx/tkMacOSXFont.c
@@ -128,11 +128,11 @@ GetTkFontAttributesForNSFont(
{
NSFontTraitMask traits = [[NSFontManager sharedFontManager]
traitsOfFont:nsFont];
-
faPtr->family = Tk_GetUid([[nsFont familyName] UTF8String]);
faPtr->size = [nsFont pointSize];
faPtr->weight = (traits & NSBoldFontMask ? TK_FW_BOLD : TK_FW_NORMAL);
faPtr->slant = (traits & NSItalicFontMask ? TK_FS_ITALIC : TK_FS_ROMAN);
+
}
/*
@@ -176,6 +176,18 @@ FindNSFont(
size = [defaultFont pointSize];
}
nsFont = [fm fontWithFamily:family traits:traits weight:weight size:size];
+
+ /*
+ * A second bug in NSFontManager that Apple created for the Catalina OS
+ * causes requests as above to sometimes return fonts with additional
+ * traits that were not requested, even though fonts without those unwanted
+ * traits exist on the system. See bug [90d555e088]. As a workaround
+ * we ask the font manager to remove any unrequested traits.
+ */
+
+ if (nsFont) {
+ nsFont = [fm convertFont:nsFont toNotHaveTrait:~traits];
+ }
if (!nsFont) {
NSArray *availableFamilies = [fm availableFontFamilies];
NSString *caseFamily = nil;
@@ -394,10 +406,25 @@ TkpFontPkgInit(
systemFont++;
}
TkInitFontAttributes(&fa);
+#if 0
+
+ /*
+ * In macOS 10.15.1 Apple introduced a bug in NSFontManager which caused
+ * it to not recognize the familyName ".SF NSMono" which is the familyName
+ * of the default fixed pitch system fault on that system. See bug [855049e799].
+ * As a workaround we call [NSFont userFixedPitchFontOfSize:11] instead.
+ * This returns a user font in the "Menlo" family.
+ */
+
nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL);
+#else
+ nsFont = [NSFont userFixedPitchFontOfSize:11];
+#endif
if (nsFont) {
GetTkFontAttributesForNSFont(nsFont, &fa);
+#if 0
CFRelease(nsFont);
+#endif
} else {
fa.family = Tk_GetUid("Monaco");
fa.size = 11;
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index a787e13..3d15442 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -413,8 +413,7 @@ TkpInit(
/*
* Initialize the NSServices object here. Apple's docs say to do this
* in applicationDidFinishLaunching, but the Tcl interpreter is not
- * initialized until this function call. Only the main interpreter
- * is allowed to provide services.
+ * initialized until this function call.
*/
TkMacOSXServices_Init(interp);
@@ -435,9 +434,6 @@ TkpInit(
TkMacOSXIconBitmapObjCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath",
TkMacOSXGetAppPathCmd, NULL, NULL);
- Tcl_CreateObjCommand(interp, "::tk::mac::registerServiceWidget",
- TkMacOSXRegisterServiceWidgetObjCmd, NULL, NULL);
-
return TCL_OK;
}
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index b1c1689..e3aed98 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -7,7 +7,7 @@
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
* Copyright (c) 2012 Adrian Robert.
- * Copyright 2015 Marc Culler.
+ * Copyright 2015-2019 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -31,13 +31,12 @@ static NSWindow *keyboardGrabNSWindow = nil;
* window. */
static NSModalSession modalSession = nil;
static BOOL processingCompose = NO;
-static BOOL finishedCompose = NO;
+static Tk_Window composeWin = NULL;
static int caret_x = 0, caret_y = 0, caret_height = 0;
-static void setupXEvent(XEvent *xEvent, NSWindow *w,
- unsigned int state);
-static unsigned isFunctionKey(unsigned int code);
+static unsigned short releaseCode;
-unsigned short releaseCode;
+static void setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state);
+static unsigned isFunctionKey(unsigned int code);
#pragma mark TKApplication(TKKeyEvent)
@@ -137,9 +136,9 @@ unsigned short releaseCode;
}
/*
- * Events are only received for the front Window on the Macintosh. So
+ * Key events are only received for the front Window on the Macintosh. So
* to build an XEvent we look up the Tk window associated to the Front
- * window. If a different window has a local grab we ignore the event.
+ * window.
*/
TkWindow *winPtr = TkMacOSXGetTkWindow(w);
@@ -148,11 +147,18 @@ unsigned short releaseCode;
if (tkwin) {
TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr;
- if (grabWinPtr
- && grabWinPtr != winPtr
- && !winPtr->dispPtr->grabFlags /* this means the grab is local. */
- && grabWinPtr->mainPtr == winPtr->mainPtr) {
- return theEvent;
+ /*
+ * If a local grab is in effect, key events for windows in the
+ * grabber's application are redirected to the grabber. Key events
+ * for other applications are delivered normally. If a global
+ * grab is in effect all key events are redirected to the grabber.
+ */
+
+ if (grabWinPtr) {
+ if (winPtr->dispPtr->grabFlags || /* global grab */
+ grabWinPtr->mainPtr == winPtr->mainPtr){ /* same appl. */
+ tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ }
}
} else {
tkwin = (Tk_Window) winPtr->dispPtr->focusPtr;
@@ -202,18 +208,6 @@ unsigned short releaseCode;
xEvent.xany.type = KeyPress;
}
- /*
- * For command key, take input manager's word so things like
- * dvorak / qwerty layout work.
- */
-
- if ((modifiers & NSCommandKeyMask) == NSCommandKeyMask
- && (modifiers & NSAlternateKeyMask) != NSAlternateKeyMask
- && len > 0 && !isFunctionKey(code)) {
- // head off keycode-based translation in tkMacOSXKeyboard.c
- xEvent.xkey.nbytes = [characters length]; //len
- }
-
if ([characters length] > 0) {
xEvent.xkey.keycode = (keyCode << 16) |
(UInt16) [characters characterAtIndex:0];
@@ -235,7 +229,7 @@ unsigned short releaseCode;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
savedModifiers = modifiers;
return theEvent;
- } /* if send straight to TK */
+ } /* if this is a function key or has modifiers */
} /* if not processing compose */
if (type == NSKeyDown) {
@@ -243,12 +237,29 @@ unsigned short releaseCode;
TKLog(@"keyDown: %s compose sequence.\n",
processingCompose == YES ? "Continue" : "Begin");
}
- processingCompose = YES;
- [nsEvArray addObject: theEvent];
- [[w contentView] interpretKeyEvents: nsEvArray];
- [nsEvArray removeObject: theEvent];
- }
+ /*
+ * Call the interpretKeyEvents method to interpret composition key
+ * strokes. When it detects a complete composition sequence it will
+ * call our implementation of insertText: replacementRange, which
+ * generates a key down XEvent with the appropriate character. In IME
+ * when multiple characters have the same composition sequence and the
+ * chosen character is not the default it may be necessary to hit the
+ * enter key multiple times before the character is accepted and
+ * rendered. We send enter key events until inputText has cleared
+ * the processingCompose flag.
+ */
+
+ processingCompose = YES;
+ while(processingCompose) {
+ [nsEvArray addObject: theEvent];
+ [[w contentView] interpretKeyEvents: nsEvArray];
+ [nsEvArray removeObject: theEvent];
+ if ([theEvent keyCode] != 36) {
+ break;
+ }
+ }
+ }
savedModifiers = modifiers;
return theEvent;
}
@@ -265,25 +276,34 @@ unsigned short releaseCode;
return self;
}
-/* <NSTextInput> implementation (called through interpretKeyEvents:]). */
+/*
+ * Implementation of the NSTextInputClient protocol.
+ */
-/* <NSTextInput>: called when done composing;
- NOTE: also called when we delete over working text, followed immed.
- by doCommandBySelector: deleteBackward: */
+/* [NSTextInputClient inputText: replacementRange:] is called by
+ * interpretKeyEvents when a composition sequence is complete. It is also
+ * called when we delete over working text. In that case the call is followed
+ * immediately by doCommandBySelector: deleteBackward:
+ */
- (void)insertText: (id)aString
+ replacementRange: (NSRange)repRange
{
- int i, len = [(NSString *) aString length];
+ int i, len;
XEvent xEvent;
+ NSString *str;
+
+ str = ([aString isKindOfClass: [NSAttributedString class]]) ?
+ [aString string] : aString;
+ len = [str length];
if (NS_KEYLOG) {
TKLog(@"insertText '%@'\tlen = %d", aString, len);
}
processingCompose = NO;
- finishedCompose = YES;
/*
- * First, clear any working text.
+ * Clear any working text.
*/
if (privateWorkingText != nil) {
@@ -291,32 +311,104 @@ unsigned short releaseCode;
}
/*
- * Now insert the string as keystrokes.
+ * Insert the string as a sequence of keystrokes.
*/
setupXEvent(&xEvent, [self window], 0);
xEvent.xany.type = KeyPress;
- for (i =0; i<len; i++) {
- xEvent.xkey.keycode = (UInt16) [aString characterAtIndex: i];
- [[aString substringWithRange: NSMakeRange(i,1)]
- getCString: xEvent.xkey.trans_chars
- maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
- xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+ /*
+ * Apple evidently sets location to 0 to signal that an accented letter has
+ * been selected from the accent menu. An unaccented letter has already
+ * been displayed and we need to erase it before displaying the accented
+ * letter.
+ */
+
+ if (repRange.location == 0) {
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
+ }
+
+ /*
+ * NSString represents a non-BMP character as a string of length 2 where
+ * the first character is the high surrogate and the second character is
+ * the low surrogate. We could record this in the XEvent by setting the
+ * keycode to the unicode code point and setting the trans_chars to the
+ * 4-byte UTF-8 string. However, that will not help as long as TCL_UTF_MAX
+ * is set to 3. Until that changes, we just replace non-BMP characters by
+ * the "replacement character" U+FFFD.
+ */
+
+ for (i = 0; i < len; i++) {
+ UniChar nextChar = [str characterAtIndex: i];
+ if (CFStringIsSurrogateHighCharacter(nextChar)) {
+#if 0
+ UniChar lowChar = [str characterAtIndex: ++i];
+ xEvent.xkey.keycode = CFStringGetLongCharacterForSurrogatePair(
+ nextChar, lowChar);
+ xEvent.xkey.nbytes = TkUniCharToUtf(xEvent.xkey.keycode,
+ &xEvent.xkey.trans_chars);
+#else
+ i++;
+ xEvent.xkey.keycode = 0xfffd;
+ strcpy(xEvent.xkey.trans_chars, "\xef\xbf\xbd");
+ xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+#endif
+ } else {
+ xEvent.xkey.keycode = (int) nextChar;
+ [[str substringWithRange: NSMakeRange(i,1)]
+ getCString: xEvent.xkey.trans_chars
+ maxLength: XMaxTransChars encoding: NSUTF8StringEncoding];
+ xEvent.xkey.nbytes = strlen(xEvent.xkey.trans_chars);
+ }
xEvent.xany.type = KeyPress;
- releaseCode = (UInt16) [aString characterAtIndex: 0];
+ releaseCode = (UInt16) nextChar;
Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
}
- releaseCode = (UInt16) [aString characterAtIndex: 0];
+ releaseCode = (UInt16) [str characterAtIndex: 0];
+}
+
+/*
+ * This required method is allowed to return nil.
+ */
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)theRange
+ actualRange:(NSRangePointer)thePointer
+{
+ return nil;
}
+/*
+ * This method is supposed to insert (or replace selected text with) the string
+ * argument. If the argument is an NSString, it should be displayed with a
+ * distinguishing appearance, e.g underlined.
+ */
-/* <NSTextInput>: inserts display of composing characters */
-- (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
+- (void)setMarkedText: (id)aString
+ selectedRange: (NSRange)selRange
+ replacementRange: (NSRange)repRange
{
- NSString *str = [aString respondsToSelector: @selector (string)] ?
- [aString string] : aString;
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ NSString *temp;
+ NSString *str;
+
+ str = ([aString isKindOfClass: [NSAttributedString class]]) ?
+ [aString string] : aString;
+
+ if (focusWin) {
+
+ /*
+ * Remember the widget where the composition is happening, in case it
+ * gets defocussed during the composition.
+ */
+
+ composeWin = focusWin;
+ } else {
+ return;
+ }
if (NS_KEYLOG) {
TKLog(@"setMarkedText '%@' len =%lu range %lu from %lu", str,
(unsigned long) [str length], (unsigned long) selRange.length,
@@ -326,17 +418,23 @@ unsigned short releaseCode;
if (privateWorkingText != nil) {
[self deleteWorkingText];
}
+
if ([str length] == 0) {
return;
}
- processingCompose = YES;
- privateWorkingText = [str copy];
+ /*
+ * Use our insertText method to display the marked text.
+ */
- //PENDING: insert workingText underlined
+ TkSendVirtualEvent(focusWin, "TkStartIMEMarkedText", NULL);
+ temp = [str copy];
+ [self insertText: temp replacementRange:repRange];
+ privateWorkingText = temp;
+ processingCompose = YES;
+ TkSendVirtualEvent(focusWin, "TkEndIMEMarkedText", NULL);
}
-
- (BOOL)hasMarkedText
{
return privateWorkingText != nil;
@@ -355,23 +453,35 @@ unsigned short releaseCode;
return rng;
}
+- (void)cancelComposingText
+{
+ if (NS_KEYLOG) {
+ TKLog(@"cancelComposingText");
+ }
+ [self deleteWorkingText];
+ processingCompose = NO;
+}
- (void)unmarkText
{
if (NS_KEYLOG) {
- TKLog(@"unmark (accept) text");
+ TKLog(@"unmarkText");
}
[self deleteWorkingText];
processingCompose = NO;
}
-/* used to position char selection windows, etc. */
+/*
+ * Called by the system to get a position for popup character selection windows
+ * such as a Character Palette, or a selection menu for IME.
+ */
+
- (NSRect)firstRectForCharacterRange: (NSRange)theRange
+ actualRange: (NSRangePointer)thePointer
{
NSRect rect;
NSPoint pt;
-
pt.x = caret_x;
pt.y = caret_y;
@@ -380,18 +490,16 @@ unsigned short releaseCode;
pt.y -= caret_height;
rect.origin = pt;
- rect.size.width = caret_height;
+ rect.size.width = 0;
rect.size.height = caret_height;
return rect;
}
-
- (NSInteger)conversationIdentifier
{
return (NSInteger) self;
}
-
- (void)doCommandBySelector: (SEL)aSelector
{
if (NS_KEYLOG) {
@@ -399,54 +507,41 @@ unsigned short releaseCode;
}
processingCompose = NO;
if (aSelector == @selector (deleteBackward:)) {
- /*
- * Happens when user backspaces over an ongoing composition:
- * throw a 'delete' into the event queue.
- */
-
- XEvent xEvent;
-
- setupXEvent(&xEvent, [self window], 0);
- xEvent.xany.type = KeyPress;
- xEvent.xkey.nbytes = 1;
- xEvent.xkey.keycode = (0x33 << 16) | 0x7F;
- xEvent.xkey.trans_chars[0] = 0x7F;
- xEvent.xkey.trans_chars[1] = 0x0;
- Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL);
+ TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
+ Tk_Window focusWin = (Tk_Window) winPtr->dispPtr->focusPtr;
+ TkSendVirtualEvent(focusWin, "TkAccentBackspace", NULL);
}
}
-
- (NSArray *)validAttributesForMarkedText
{
static NSArray *arr = nil;
-
if (arr == nil) {
- arr = [NSArray new];
+ arr = [[NSArray alloc] initWithObjects:
+ NSUnderlineStyleAttributeName,
+ NSUnderlineColorAttributeName,
+ nil];
+ [arr retain];
}
- /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
return arr;
}
-
- (NSRange)selectedRange
{
if (NS_KEYLOG) {
TKLog(@"selectedRange request");
}
- return NSMakeRange(NSNotFound, 0);
+ return NSMakeRange(0, 0);
}
-
- (NSUInteger)characterIndexForPoint: (NSPoint)thePoint
{
if (NS_KEYLOG) {
TKLog(@"characterIndexForPoint request");
}
- return 0;
+ return NSNotFound;
}
-
- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
{
static NSAttributedString *str = nil;
@@ -458,34 +553,44 @@ unsigned short releaseCode;
}
return str;
}
-/* End <NSTextInput> impl. */
+/* End of NSTextInputClient implementation. */
@synthesize needsRedisplay = _needsRedisplay;
@end
@implementation TKContentView(TKKeyEvent)
-/* delete display of composing characters [not in <NSTextInput>] */
+
+/*
+ * Tell the widget to erase the displayed composing characters. This
+ * is not part of the NSTextInputClient protocol.
+ */
+
- (void)deleteWorkingText
{
if (privateWorkingText == nil) {
return;
- }
- if (NS_KEYLOG) {
- TKLog(@"deleteWorkingText len = %lu\n",
- (unsigned long)[privateWorkingText length]);
- }
- [privateWorkingText release];
- privateWorkingText = nil;
- processingCompose = NO;
+ } else {
- //PENDING: delete working text
+ if (NS_KEYLOG) {
+ TKLog(@"deleteWorkingText len = %lu\n",
+ (unsigned long)[privateWorkingText length]);
+ }
+
+ [privateWorkingText release];
+ privateWorkingText = nil;
+ processingCompose = NO;
+ if (composeWin) {
+ TkSendVirtualEvent(composeWin, "TkClearIMEMarkedText", NULL);
+ }
+ }
}
@end
/*
* Set up basic fields in xevent for keyboard input.
*/
+
static void
setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
{
@@ -498,17 +603,15 @@ setupXEvent(XEvent *xEvent, NSWindow *w, unsigned int state)
memset(xEvent, 0, sizeof(XEvent));
xEvent->xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin));
- xEvent->xany.send_event = false;
xEvent->xany.display = Tk_Display(tkwin);
xEvent->xany.window = Tk_WindowId(tkwin);
xEvent->xkey.root = XRootWindow(Tk_Display(tkwin), 0);
- xEvent->xkey.subwindow = None;
xEvent->xkey.time = TkpGetMS();
xEvent->xkey.state = state;
xEvent->xkey.same_screen = true;
- xEvent->xkey.trans_chars[0] = 0;
- xEvent->xkey.nbytes = 0;
+ /* No need to initialize other fields implicitly here,
+ * because of the memset() above. */
}
#pragma mark -
diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c
index 3272657..e91dfe2 100644
--- a/macosx/tkMacOSXKeyboard.c
+++ b/macosx/tkMacOSXKeyboard.c
@@ -443,8 +443,11 @@ TkpGetString(
* result. */
{
(void) winPtr; /*unused*/
+ int ch;
+
Tcl_DStringInit(dsPtr);
- return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
+ return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars,
+ TkUtfToUniChar(eventPtr->xkey.trans_chars, &ch));
}
/*
@@ -717,7 +720,7 @@ TkpSetKeycodeAndState(
}
if (keysym <= LATIN1_MAX) {
- int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
+ int done = TkUniCharToUtf(keysym, eventPtr->xkey.trans_chars);
eventPtr->xkey.trans_chars[done] = 0;
} else {
@@ -803,7 +806,7 @@ TkpGetKeySym(
/* If nbytes has been set, it's not a function key, but a regular key that
has been translated in tkMacOSXKeyEvent.c; just use that. */
if (eventPtr->xkey.nbytes) {
- return eventPtr->xkey.keycode & 0xFFFF;
+ return eventPtr->xkey.keycode;
}
/*
diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c
index 99c1191..82bcda7 100644
--- a/macosx/tkMacOSXMenus.c
+++ b/macosx/tkMacOSXMenus.c
@@ -70,7 +70,7 @@ static Tcl_Obj * GetWidgetDemoPath(Tcl_Interp *interp);
[NSMenuItem itemWithTitle:
[NSString stringWithFormat:@"About %@", aboutName]
action:@selector(orderFrontStandardAboutPanel:)] atIndex:0];
- _defaultFileMenuItems =
+ _defaultFileMenuItems =
[[NSArray arrayWithObjects:
[NSMenuItem itemWithTitle:
[NSString stringWithFormat:@"Source%C", 0x2026]
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 89cdf1b..b18b4ef 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -130,7 +130,8 @@ enum {
}
/*
- * Make sure tkwin is the toplevel which should receive the event.
+ * If we still don't have a window, try using the toplevel that
+ * manages the NSWindow.
*/
if (!tkwin) {
@@ -138,10 +139,15 @@ enum {
tkwin = (Tk_Window) winPtr;
}
if (!tkwin) {
+
+ /*
+ * We can't find a window for this event. We have to ignore it.
+ */
+
#ifdef TK_MAC_DEBUG_EVENTS
TkMacOSXDbgMsg("tkwin == NULL");
#endif
- return theEvent; /* Give up. No window for this event. */
+ return theEvent;
}
/*
@@ -174,13 +180,25 @@ enum {
* coordinates.
*/
- local.x -= winPtr->wmInfoPtr->xInParent;
- local.y -= winPtr->wmInfoPtr->yInParent;
+ if (Tk_IsEmbedded(winPtr)) {
+ TkWindow *contPtr = TkpGetOtherWindow(winPtr);
+ if (Tk_IsTopLevel(contPtr)) {
+ local.x -= contPtr->wmInfoPtr->xInParent;
+ local.y -= contPtr->wmInfoPtr->yInParent;
+ } else {
+ TkWindow *topPtr = TkMacOSXGetHostToplevel(winPtr)->winPtr;
+ local.x -= (topPtr->wmInfoPtr->xInParent + contPtr->changes.x);
+ local.y -= (topPtr->wmInfoPtr->yInParent + contPtr->changes.y);
+ }
+ } else {
+ local.x -= winPtr->wmInfoPtr->xInParent;
+ local.y -= winPtr->wmInfoPtr->yInParent;
+ }
/*
- * Find the containing Tk window, and convert local into the coordinates
- * of the Tk window. (The converted local coordinates are only needed
- * for scrollwheel events.)
+ * Use the toplevel coordinates to find the containing Tk window. Then
+ * convert local into the coordinates of that window. (The converted
+ * local coordinates are only needed for scrollwheel events.)
*/
int win_x, win_y;
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index cb80dd8..7aa6840 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -340,7 +340,12 @@ VISIBILITY_HIDDEN
@end
VISIBILITY_HIDDEN
-@interface TKContentView : NSView <NSTextInput>
+/*
+ * Subclass TKContentView from NSTextInputClient to enable composition and
+ * input from the Character Palette.
+ */
+
+@interface TKContentView : NSView <NSTextInputClient>
{
@private
NSString *privateWorkingText;
@@ -354,13 +359,8 @@ VISIBILITY_HIDDEN
@end
@interface TKContentView(TKWindowEvent)
-- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIShapeRef) shape;
- (void) tkToolbarButton: (id) sender;
-- (BOOL) isOpaque;
-- (BOOL) wantsDefaultClipping;
-- (BOOL) acceptsFirstResponder;
-- (void) keyDown: (NSEvent *) theEvent;
@end
@interface NSWindow(TKWm)
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index 66619c2..dff6cc9 100644
--- a/macosx/tkMacOSXScrlbr.c
+++ b/macosx/tkMacOSXScrlbr.c
@@ -214,12 +214,20 @@ static void drawMacScrollbar(
CGContextStrokeLineSegments(context, outer, 2);
/*
- * Do not display the thumb unless scrolling is possible.
+ * Do not display the thumb unless scrolling is possible, in accordance
+ * with macOS behavior.
+ *
+ * Native scrollbars and Ttk scrollbars are always 15 pixels wide, but we
+ * allow Tk scrollbars to have any width, even if it looks bad. To prevent
+ * sporadic assertion errors when drawing skinny thumbs we must make sure
+ * the radius is at most half the width.
*/
if (scrollPtr->firstFraction > 0.0 || scrollPtr->lastFraction < 1.0) {
CGRect thumbBounds = {thumbOrigin, thumbSize};
- path = CGPathCreateWithRoundedRect(thumbBounds, 4, 4, NULL);
+ int width = scrollPtr->vertical ? thumbSize.width : thumbSize.height;
+ int radius = width >= 8 ? 4 : width >> 1;
+ path = CGPathCreateWithRoundedRect(thumbBounds, radius, radius, NULL);
CGContextBeginPath(context);
CGContextAddPath(context, path);
if (msPtr->info.trackInfo.scrollbar.pressState != 0) {
diff --git a/macosx/tkMacOSXServices.c b/macosx/tkMacOSXServices.c
index f1e5951..e92158f 100644
--- a/macosx/tkMacOSXServices.c
+++ b/macosx/tkMacOSXServices.c
@@ -4,20 +4,18 @@
* This file allows the integration of Tk and the Cocoa NSServices API.
*
* Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC.
+ * Copyright (c) 2019 Marc Culler.
* Copyright (c) 2010 Adrian Robert.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
-#include <CoreServices/CoreServices.h>
#include <tkInt.h>
#include <tkMacOSXInt.h>
-static Tcl_Interp *ServicesInterp;
-
/*
- * Event proc which calls the PerformService procedure
+ * Event proc which calls the PerformService procedure.
*/
static int
@@ -25,22 +23,28 @@ ServicesEventProc(
Tcl_Event *event,
int flags)
{
- Tcl_GlobalEval(ServicesInterp, "::tk::mac::PerformService");
+ TkMainInfo *info = TkGetMainInfoList();
+ Tcl_GlobalEval(info->interp, "::tk::mac::PerformService");
return 1;
}
/*
- * Class declarations for TkService class.
+ * The Wish application can send the current selection in the Tk clipboard
+ * to other applications which accept messages of type NSString. The TkService
+ * object provides this service via its provideService method. (The method
+ * must be specified in the application's Info.plist file for this to work.)
*/
-@interface TkService : NSView {
+@interface TkService : NSObject {
}
+ (void) initialize;
-- (void)provideService:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error;
-- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType;
-- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard types:(NSArray *)types;
+- (void) provideService:(NSPasteboard *)pboard
+ userData:(NSString *)data
+ error:(NSString **)error;
+- (BOOL) writeSelectionToPasteboard:(NSPasteboard *)pboard
+ types:(NSArray *)types;
@end
@@ -57,32 +61,8 @@ ServicesEventProc(
return;
}
-
-- (id)validRequestorForSendType:(NSString *)sendType
- returnType:(NSString *)returnType
-{
- if ([sendType isEqualToString:@"NSStringPboardType"] ||
- [sendType isEqualToString:@"NSPasteboardTypeString"]) {
- return self;
- }
- return [super validRequestorForSendType:sendType returnType:returnType];
-}
-
-/*
- * Make sure the view accepts events.
- */
-
-- (BOOL)acceptsFirstResponder
-{
- return YES;
-}
-- (BOOL)becomeFirstResponder
-{
- return YES;
-}
-
/*
- * Get selected text, copy to pasteboard.
+ * Get the current Tk selection and copy it to the system pasteboard.
*/
- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pboard
@@ -90,6 +70,7 @@ ServicesEventProc(
{
NSArray *typesDeclared = nil;
NSString *pboardType = nil;
+ TkMainInfo *info = TkGetMainInfoList();
for (NSString *typeString in types) {
if ([typeString isEqualToString:@"NSStringPboardType"] ||
@@ -102,9 +83,9 @@ ServicesEventProc(
if (!typesDeclared) {
return NO;
}
- Tcl_Eval(ServicesInterp, "selection get");
+ Tcl_Eval(info->interp, "selection get");
- char *copystring = Tcl_GetString(Tcl_GetObjResult(ServicesInterp));
+ char *copystring = Tcl_GetString(Tcl_GetObjResult(info->interp));
NSString *writestring = [NSString stringWithUTF8String:copystring];
[pboard declareTypes:typesDeclared owner:nil];
@@ -112,8 +93,8 @@ ServicesEventProc(
}
/*
- * This is the method that actually calls the Tk service; this is the method
- * that must be defined in info.plist.
+ * This is the method that actually calls the Tk service; it must be specified
+ * in Info.plist.
*/
- (void)provideService:(NSPasteboard *)pboard
@@ -125,8 +106,8 @@ ServicesEventProc(
Tcl_Event *event;
/*
- * Get string from private pasteboard, write to general pasteboard to make
- * available to Tcl service.
+ * Get a string from the private pasteboard and copy it to the general
+ * pasteboard to make it available to other applications.
*/
for (NSString *typeString in types) {
@@ -150,69 +131,9 @@ ServicesEventProc(
@end
/*
- * Register a specific widget to access the Services menu.
- */
-
-int
-TkMacOSXRegisterServiceWidgetObjCmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
-{
- /*
- * Need proper number of args.
- */
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "path?");
- return TCL_ERROR;
- }
- /*
- * Get the object that holds this Tk Window...
- */
-
- Rect bounds;
- NSRect frame;
- Tk_Window path = Tk_NameToWindow(interp,
- Tcl_GetString(objv[1]), Tk_MainWindow(interp));
-
- if (path == NULL) {
- return TCL_ERROR;
- }
-
- Tk_MakeWindowExist(path);
- Tk_MapWindow(path);
- Drawable d = Tk_WindowId(path);
-
- /*
- * Get NSView from Tk window and add subview.
- */
-
- TkService *serviceview = [[TkService alloc] init];
- NSView *view = TkMacOSXGetRootControl(d);
-
- if ([serviceview superview] != view) {
- [view addSubview:serviceview];
- }
- TkMacOSXWinBounds((TkWindow*)path, &bounds);
-
- /*
- * Hack to make sure subview is set to take up entire geometry of window.
- */
-
- frame = NSMakeRect(bounds.left, bounds.top, 100000, 100000);
- frame.origin.y = 0;
- if (!NSEqualRects(frame, [serviceview frame])) {
- [serviceview setFrame:frame];
- }
- [serviceview release];
- return TCL_OK;
-}
-
-/*
- * Initalize the package in the Tcl interpreter, create Tcl commands.
+ * Instantiate a TkService object and register it with the NSApplication.
+ * This is called exactly one time from TkpInit.
*/
int
@@ -220,12 +141,10 @@ TkMacOSXServices_Init(
Tcl_Interp *interp)
{
/*
- * Initialize instance of TclServices to provide service functionality.
+ * Initialize an instance of TkService and register it with the NSApp.
*/
TkService *service = [[TkService alloc] init];
-
- ServicesInterp = interp;
[NSApp setServicesProvider:service];
return TCL_OK;
}
diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c
index 09736e6..c353efe 100644
--- a/macosx/tkMacOSXTest.c
+++ b/macosx/tkMacOSXTest.c
@@ -161,7 +161,7 @@ PressButtonObjCmd(
if (screens && [screens count]) {
ScreenHeight = [[screens objectAtIndex:0] frame].size.height;
}
-
+
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "x y");
return TCL_ERROR;
@@ -186,34 +186,34 @@ PressButtonObjCmd(
loc.y = ScreenHeight - y;
wNum = 0;
CGWarpMouseCursorPosition(pt);
- motion = [NSEvent mouseEventWithType:NSMouseMoved
+ motion = [NSEvent mouseEventWithType:NSMouseMoved
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:0
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:motion atStart:NO];
- press = [NSEvent mouseEventWithType:NSLeftMouseDown
+ press = [NSEvent mouseEventWithType:NSLeftMouseDown
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:1
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:press atStart:NO];
release = [NSEvent mouseEventWithType:NSLeftMouseUp
location:loc
- modifierFlags:0
- timestamp:GetCurrentEventTime()
+ modifierFlags:0
+ timestamp:GetCurrentEventTime()
windowNumber:wNum
- context:nil
+ context:nil
eventNumber:2
- clickCount:1
+ clickCount:1
pressure:0.0];
[NSApp postEvent:release atStart:NO];
return TCL_OK;
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 2666939..fe6981d 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -1186,6 +1186,11 @@ RedisplayView(
return YES;
}
+/*
+ * This keyDown method does nothing, which is a huge improvement over the
+ * default keyDown method which beeps every time a key is pressed.
+ */
+
- (void) keyDown: (NSEvent *) theEvent
{
#ifdef TK_MAC_DEBUG_EVENTS
@@ -1193,6 +1198,23 @@ RedisplayView(
#endif
}
+/*
+ * When the services menu is opened this is called for each Responder in
+ * the Responder chain until a service provider is found. The TkContentView
+ * should be the first (and generally only) Responder in the chain. We
+ * return the TkServices object that was created in TkpInit.
+ */
+
+- (id)validRequestorForSendType:(NSString *)sendType
+ returnType:(NSString *)returnType
+{
+ if ([sendType isEqualToString:@"NSStringPboardType"] ||
+ [sendType isEqualToString:@"NSPasteboardTypeString"]) {
+ return [NSApp servicesProvider];
+ }
+ return [super validRequestorForSendType:sendType returnType:returnType];
+}
+
@end
/*
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 70e9cd9..4e53282 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -2518,6 +2518,7 @@ WmIconphotoCmd(
{
Tk_Image tk_icon;
int width, height, isDefault = 0;
+ NSImage *newIcon = NULL;
if (objc < 4) {
Tcl_WrongNumArgs(interp, 2, objv,
@@ -2563,12 +2564,16 @@ WmIconphotoCmd(
return TCL_ERROR;
}
- NSImage *newIcon;
Tk_SizeOfImage(tk_icon, &width, &height);
- newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
- width, height);
+ if (width != 0 && height != 0) {
+ newIcon = TkMacOSXGetNSImageWithTkImage(winPtr->display, tk_icon,
+ width, height);
+ }
Tk_FreeImage(tk_icon);
if (newIcon == NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "failed to create an iconphoto with image \"%s\"", icon));
+ Tcl_SetErrorCode(interp, "TK", "WM", "ICONPHOTO", "IMAGE", NULL);
return TCL_ERROR;
}
[NSApp setApplicationIconImage: newIcon];
@@ -3311,18 +3316,18 @@ WmStackorderCmd(
if (objc == 3) {
windows = TkWmStackorderToplevel(winPtr);
- if (windows == NULL) {
- Tcl_Panic("TkWmStackorderToplevel failed");
- }
-
- resultObj = Tcl_NewObj();
- for (windowPtr = windows; *windowPtr ; windowPtr++) {
- Tcl_ListObjAppendElement(NULL, resultObj,
+ if (windows != NULL) {
+ resultObj = Tcl_NewObj();
+ for (windowPtr = windows; *windowPtr ; windowPtr++) {
+ Tcl_ListObjAppendElement(NULL, resultObj,
TkNewWindowObj((Tk_Window) *windowPtr));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ ckfree(windows);
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
}
- Tcl_SetObjResult(interp, resultObj);
- ckfree(windows);
- return TCL_OK;
} else {
TkWindow *winPtr2;
int index1 = -1, index2 = -1, result;
@@ -6623,7 +6628,7 @@ WmStackorderToplevelWrapperMap(
Tcl_HashEntry *hPtr;
int newEntry;
- if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)
+ if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) && !Tk_IsEmbedded(winPtr)
&& (winPtr->display == display)) {
hPtr = Tcl_CreateHashEntry(table,
(char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry);
@@ -6644,8 +6649,8 @@ WmStackorderToplevelWrapperMap(
* This procedure returns the stack order of toplevel windows.
*
* Results:
- * An array of pointers to tk window objects in stacking order or else
- * NULL if there was an error.
+ * A NULL terminated array of pointers to tk window objects in stacking
+ * order or else NULL if there was an error.
*
* Side effects:
* None.
@@ -6660,57 +6665,24 @@ TkWmStackorderToplevel(
TkWindow *childWinPtr, **windows, **windowPtr;
Tcl_HashTable table;
Tcl_HashEntry *hPtr;
- Tcl_HashSearch search;
-
- /*
- * Map mac windows to a TkWindow of the wrapped toplevel.
- */
-
- Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
- WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
-
- windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
-
- /*
- * Special cases: If zero or one toplevels were mapped there is no need to
- * enumerate Windows.
- */
-
- switch (table.numEntries) {
- case 0:
- windows[0] = NULL;
- goto done;
- case 1:
- hPtr = Tcl_FirstHashEntry(&table, &search);
- windows[0] = Tcl_GetHashValue(hPtr);
- windows[1] = NULL;
- goto done;
- }
-
NSArray *macWindows = [NSApp orderedWindows];
+ NSArray* backToFront = [[macWindows reverseObjectEnumerator] allObjects];
NSInteger windowCount = [macWindows count];
- if (!windowCount) {
- ckfree(windows);
- windows = NULL;
- } else {
- windowPtr = windows + table.numEntries;
- *windowPtr-- = NULL;
- for (NSWindow *w in macWindows) {
+ windows = windowPtr = ckalloc((windowCount + 1) * sizeof(TkWindow *));
+ if (windows != NULL) {
+ Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
+ WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
+ for (NSWindow *w in backToFront) {
hPtr = Tcl_FindHashEntry(&table, (char*) w);
if (hPtr != NULL) {
childWinPtr = Tcl_GetHashValue(hPtr);
- *windowPtr-- = childWinPtr;
+ *windowPtr++ = childWinPtr;
}
}
- if (windowPtr != windows-1) {
- Tcl_Panic("num matched toplevel windows does not equal num "
- "children");
- }
+ *windowPtr = NULL;
+ Tcl_DeleteHashTable(&table);
}
-
- done:
- Tcl_DeleteHashTable(&table);
return windows;
}
diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c
index 3d88ef7..52534ce 100644
--- a/macosx/ttkMacOSXTheme.c
+++ b/macosx/ttkMacOSXTheme.c
@@ -1409,8 +1409,10 @@ static void ButtonElementDraw(
} else if (info.kind == kThemePushButton &&
(state & TTK_STATE_PRESSED)) {
bounds.size.height += 2;
- GradientFillRoundedRectangle(dc.context, bounds, 4,
- pressedPushButtonGradient, 2);
+ if ([NSApp macMinorVersion] > 8) {
+ GradientFillRoundedRectangle(dc.context, bounds, 4,
+ pressedPushButtonGradient, 2);
+ }
} else {
/*
@@ -1859,18 +1861,17 @@ static void ComboboxElementDraw(
BEGIN_DRAWING(d)
bounds.origin.y += 1;
if (TkMacOSXInDarkMode(tkwin)) {
- bounds.size.height += 1;
+ bounds.size.height += 1;
DrawDarkButton(bounds, info.kind, state, dc.context);
- } else if ([NSApp macMinorVersion] > 8) {
- if ((state & TTK_STATE_BACKGROUND) &&
- !(state & TTK_STATE_DISABLED)) {
+ } else if ([NSApp macMinorVersion] > 8) {
+ if ((state & TTK_STATE_BACKGROUND) &&
+ !(state & TTK_STATE_DISABLED)) {
NSColor *background = [NSColor textBackgroundColor];
CGRect innerBounds = CGRectInset(bounds, 1, 2);
SolidFillRoundedRectangle(dc.context, innerBounds, 4, background);
}
- ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation,
- NULL);
}
+ ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
END_DRAWING
}
@@ -2095,7 +2096,7 @@ static void TrackElementDraw(
Tcl_GetDoubleFromObj(NULL, elem->fromObj, &from);
Tcl_GetDoubleFromObj(NULL, elem->toObj, &to);
Tcl_GetDoubleFromObj(NULL, elem->valueObj, &value);
- factor = RangeToFactor(to - from);
+ factor = RangeToFactor(to);
HIThemeTrackDrawInfo info = {
.version = 0,