summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorJoe Mistachkin <joe@mistachkin.com>2014-11-11 22:23:34 (GMT)
committerJoe Mistachkin <joe@mistachkin.com>2014-11-11 22:23:34 (GMT)
commitb15c525eedc93a453dfea94482bc1198e27748fc (patch)
tree49a88f59bc168351fe802d8aa68da6d853b823aa /macosx
parent07f85cd3c1b4934fb746ea36516ba2944b4eea11 (diff)
parentee9722cf78769c35f57383613f570b6e797e74bf (diff)
downloadtk-b15c525eedc93a453dfea94482bc1198e27748fc.zip
tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.gz
tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.bz2
Merge updates from core 8.5 branch.
Diffstat (limited to 'macosx')
-rw-r--r--macosx/README4
-rw-r--r--macosx/Wish-Info.plist.in2
-rw-r--r--macosx/tkMacOSXButton.c179
-rw-r--r--macosx/tkMacOSXClipboard.c2
-rw-r--r--macosx/tkMacOSXDialog.c65
-rw-r--r--macosx/tkMacOSXDraw.c271
-rw-r--r--macosx/tkMacOSXHLEvents.c8
-rw-r--r--macosx/tkMacOSXInit.c7
-rw-r--r--macosx/tkMacOSXInt.h3
-rw-r--r--macosx/tkMacOSXKeyEvent.c20
-rw-r--r--macosx/tkMacOSXMenu.c27
-rw-r--r--macosx/tkMacOSXMenubutton.c1
-rw-r--r--macosx/tkMacOSXPrivate.h11
-rw-r--r--macosx/tkMacOSXRegion.c64
-rw-r--r--macosx/tkMacOSXScale.c2
-rw-r--r--macosx/tkMacOSXScrlbr.c139
-rw-r--r--macosx/tkMacOSXSubwindows.c24
-rw-r--r--macosx/tkMacOSXWindowEvent.c253
-rw-r--r--macosx/tkMacOSXWm.c46
-rw-r--r--macosx/tkMacOSXXStubs.c113
-rw-r--r--macosx/ttkMacOSXTheme.c13
21 files changed, 772 insertions, 482 deletions
diff --git a/macosx/README b/macosx/README
index 8bd33d4..b992a2e 100644
--- a/macosx/README
+++ b/macosx/README
@@ -19,8 +19,8 @@ before asking on the list, many questions have already been answered).
http://wiki.tcl.tk/_/ref?N=3753
http://wiki.tcl.tk/_/ref?N=8361
-- Please report bugs with Tcl or Tk on Mac OS X to the sourceforge bug trackers:
- http://tcl.sourceforge.net/
+- Please report bugs with Tk on Mac OS X to the tracker:
+ http://core.tcl.tk/tk/reportlist
2. Using Tcl/Tk on Mac OS X
---------------------------
diff --git a/macosx/Wish-Info.plist.in b/macosx/Wish-Info.plist.in
index 90e00a4..78170f1 100644
--- a/macosx/Wish-Info.plist.in
+++ b/macosx/Wish-Info.plist.in
@@ -72,5 +72,7 @@ Copyright © 2001-2002 Jim Ingham &amp; Ian Reid</string>
<true/>
<key>OSAScriptingDefinition</key>
<string>Wish.sdef</string>
+ <key>NSHighResolutionCapable</key>
+ <string>True</string>
</dict>
</plist>
diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c
index f912b81..b9ee7a3 100644
--- a/macosx/tkMacOSXButton.c
+++ b/macosx/tkMacOSXButton.c
@@ -7,6 +7,7 @@
* Copyright (c) 1996-1997 by Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2014 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -23,9 +24,68 @@
#endif
*/
+static NSRect TkMacOSXGetButtonFrame(TkButton *butPtr);
+
+/*
+ * A subclass of NSButton with sanity checking:
+ * NSButtons created by Tk will have their tag set to a pointer to the TkButton
+ * which manages the NSButton. This allows a TkNSButton to be aware of the
+ * state of its Tk parent. This subclass overrides the drawRect method
+ * so that it will not draw itself unless the NSButton frame matches
+ * the frame which was installed by DisplayButton, and the TkButton is
+ * mapped. Also, it will not draw anything if the widget is completely
+ * outside of its container.
+ */
+
+@interface TkNSButton: NSButton
+
+@end
+
+@implementation TkNSButton
+
+ - (void)drawRect:(NSRect)dirtyRect
+ {
+ NSInteger tag = [self tag];
+ if ( tag != -1) {
+ TkButton *butPtr = (TkButton *)tag;
+ MacDrawable* macWin = (MacDrawable *)butPtr;
+ NSRect Tkframe = TkMacOSXGetButtonFrame(butPtr);
+ Tk_Window tkwin = butPtr->tkwin;
+ /* Do not draw if the widget is misplaced or unmapped. */
+ if ( NSIsEmptyRect(Tkframe) ||
+ ! macWin->winPtr->flags & TK_MAPPED ||
+ ! NSEqualRects(Tkframe, [self frame])
+ ) {
+ return;
+ }
+ /* Do not draw if the widget is completely outside of its parent, or within 20 pixels of the lower border; this prevents buttons from being drawn on peer widgets as scrolling occurs. */
+ if (tkwin) {
+ int parent_height = Tk_Height(Tk_Parent(tkwin));
+ int widget_height = Tk_Height(tkwin);
+ int y = Tk_Y(tkwin);
+ if ( y > parent_height - 20 || y + widget_height < 0 ) {
+ return;
+ }
+
+ /* Do not draw if the widget is completely outside of its parent, or within 50 pixels of the right border; this prevents buttons from being drawn on peer widgets as scrolling occurs. */
+ int parent_width = Tk_Width(Tk_Parent(tkwin));
+ int widget_width = Tk_Width(tkwin);
+ int x = Tk_X(tkwin);
+ if (x > parent_width - 50 || x < 0) {
+ return;
+ }
+
+ }
+ }
+ [super drawRect:dirtyRect];
+ }
+
+@end
+
+
typedef struct MacButton {
TkButton info;
- NSButton *button;
+ TkNSButton *button;
NSImage *image, *selectImage, *tristateImage;
#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
int fix;
@@ -135,9 +195,10 @@ TkpDestroyButton(
TkButton *butPtr)
{
MacButton *macButtonPtr = (MacButton *) butPtr;
+ [macButtonPtr->button setTag:(NSInteger)-1];
TkMacOSXMakeCollectableAndRelease(macButtonPtr->button);
- TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
+ TkMacOSXMakeCollectableAndRelease(macButtonPtr->image);
TkMacOSXMakeCollectableAndRelease(macButtonPtr->selectImage);
TkMacOSXMakeCollectableAndRelease(macButtonPtr->tristateImage);
}
@@ -186,6 +247,45 @@ TkpDisplayButton(
/*
*----------------------------------------------------------------------
*
+ * TkpShiftButton --
+ *
+ * Moves the frame of an NSButton (or TkNSButton) and in case the tag is
+ * set, also adjusts the xOff and yOff of the controlling TkButton's
+ * MacDrawable. This is used to avoid jitter when scrolling.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Moves the NSbutton after adjusting the associated MacDrawable.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TkpShiftButton(
+ NSButton *button,
+ NSPoint delta )
+ {
+ NSPoint origin = [button frame].origin;
+ NSInteger tag = [button tag];
+ if ( tag != -1) {
+ TkButton* butPtr = (TkButton *)tag;
+ TkWindow *winPtr = (TkWindow *) (butPtr->tkwin);
+ if (winPtr) {
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ macWin->xOff += delta.x;
+ macWin->yOff += delta.y;
+ }
+ }
+ origin.x += delta.x;
+ origin.y -= delta.y;
+ [button setFrameOrigin:origin];
+ }
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkpComputeButtonGeometry --
*
* After changes in a button's text or bitmap, this procedure
@@ -218,7 +318,8 @@ TkpComputeButtonGeometry(
case TYPE_CHECK_BUTTON:
case TYPE_RADIO_BUTTON:
if (!macButtonPtr->button) {
- NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
+ TkNSButton *button = [[TkNSButton alloc] initWithFrame:NSZeroRect];
+ [button setTag:(NSInteger)butPtr];
macButtonPtr->button = TkMacOSXMakeUncollectable(button);
}
ComputeNativeButtonGeometry(butPtr);
@@ -266,6 +367,52 @@ TkpButtonSetDefaults()
/*
*----------------------------------------------------------------------
*
+ * TkMacOSXGetButtonFrame --
+ *
+ * Computes a frame for an NSButton that will correspond to where
+ * Tk thinks the button is located.
+ *
+ * Results:
+ * Returns an NSRect describing a frame for an NSButton.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+NSRect TkMacOSXGetButtonFrame(
+ TkButton *butPtr)
+{
+ MacButton *macButtonPtr = (MacButton *) butPtr;
+ Tk_Window tkwin = butPtr->tkwin;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ if (tkwin) {
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ NSView *view = TkMacOSXDrawableView(macWin);
+ CGFloat viewHeight = [view bounds].size.height;
+ NSRect frame = NSMakeRect(macWin->xOff, macWin->yOff,
+ Tk_Width(tkwin), Tk_Height(tkwin));
+
+#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
+ if (tkMacOSXUseCompatibilityMetrics) {
+ BoundsFix boundsFix = boundsFixes[macButtonPtr->fix];
+ frame = NSOffsetRect(frame, boundsFix.offsetX, boundsFix.offsetY);
+ frame.size.height -= boundsFix.shrinkH + NATIVE_BUTTON_EXTRA_H;
+ frame = NSInsetRect(frame, boundsFix.inset + NATIVE_BUTTON_INSET,
+ boundsFix.inset + NATIVE_BUTTON_INSET);
+ }
+#endif
+
+ frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
+ return frame;
+ } else {
+ return NSZeroRect;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* DisplayNativeButton --
*
* This procedure is invoked to display a button widget. It is
@@ -286,7 +433,7 @@ DisplayNativeButton(
TkButton *butPtr)
{
MacButton *macButtonPtr = (MacButton *) butPtr;
- NSButton *button = macButtonPtr->button;
+ TkNSButton *button = macButtonPtr->button;
Tk_Window tkwin = butPtr->tkwin;
TkWindow *winPtr = (TkWindow *) tkwin;
MacDrawable *macWin = (MacDrawable *) winPtr->window;
@@ -349,21 +496,8 @@ DisplayNativeButton(
} else {
[button setKeyEquivalent:@""];
}
- frame = NSMakeRect(macWin->xOff, macWin->yOff, Tk_Width(tkwin),
- Tk_Height(tkwin));
-#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS
- if (tkMacOSXUseCompatibilityMetrics) {
- BoundsFix boundsFix = boundsFixes[macButtonPtr->fix];
- frame = NSOffsetRect(frame, boundsFix.offsetX, boundsFix.offsetY);
- frame.size.height -= boundsFix.shrinkH + NATIVE_BUTTON_EXTRA_H;
- frame = NSInsetRect(frame, boundsFix.inset + NATIVE_BUTTON_INSET,
- boundsFix.inset + NATIVE_BUTTON_INSET);
- }
-#endif
- frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
- if (!NSEqualRects(frame, [button frame])) {
- [button setFrame:frame];
- }
+ frame = TkMacOSXGetButtonFrame(butPtr);
+ [button setFrame:frame];
[button displayRectIgnoringOpacity:[button bounds]];
TkMacOSXRestoreDrawingContext(&dc);
#ifdef TK_MAC_DEBUG_BUTTON
@@ -396,7 +530,7 @@ ComputeNativeButtonGeometry(
TkButton *butPtr) /* Button whose geometry may have changed. */
{
MacButton *macButtonPtr = (MacButton *) butPtr;
- NSButton *button = macButtonPtr->button;
+ TkNSButton *button = macButtonPtr->button;
NSButtonCell *cell = [button cell];
NSButtonType type = -1;
NSBezelStyle style = 0;
@@ -429,7 +563,7 @@ ComputeNativeButtonGeometry(
}
break;
case TYPE_RADIO_BUTTON:
- case TYPE_CHECK_BUTTON:
+ case TYPE_CHECK_BUTTON:
if (!haveImage /*|| butPtr->indicatorOn*/) { // TODO: indicatorOn
type = butPtr->type == TYPE_RADIO_BUTTON ?
NSRadioButton : NSSwitchButton;
@@ -454,7 +588,7 @@ ComputeNativeButtonGeometry(
}
[button setButtonType:type];
if (style) {
- [button setBezelStyle:style];
+ [button setBezelStyle:style];
}
if (highlightsBy) {
[cell setHighlightsBy:highlightsBy|[cell highlightsBy]];
@@ -1169,6 +1303,7 @@ ComputeUnixButtonGeometry(
Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
}
+
/*
* Local Variables:
* mode: objc
diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c
index 7cd9c30..6ac7830 100644
--- a/macosx/tkMacOSXClipboard.c
+++ b/macosx/tkMacOSXClipboard.c
@@ -168,6 +168,7 @@ XSetSelectionOwner(
changeCount = [pb declareTypes:[NSArray array] owner:NSApp];
}
}
+ return Success;
}
/*
@@ -194,7 +195,6 @@ TkMacOSXSelDeadWindow(
if (winPtr && winPtr == (TkWindow *)clipboardOwner) {
clipboardOwner = NULL;
}
- return Success;
}
/*
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c
index d9e824a..bc11b96 100644
--- a/macosx/tkMacOSXDialog.c
+++ b/macosx/tkMacOSXDialog.c
@@ -14,6 +14,9 @@
#include "tkMacOSXPrivate.h"
#include "tkFileFilter.h"
+static int TkBackgroundEvalObjv(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv, int flags);
+
static const char *colorOptionStrings[] = {
"-initialcolor", "-parent", "-title", NULL
};
@@ -1057,6 +1060,68 @@ end:
}
/*
+ * ----------------------------------------------------------------------
+ *
+ * TkBackgroundEvalObjv --
+ *
+ * Evaluate a command while ensuring that we do not affect the
+ * interpreters state. This is important when evaluating script
+ * during background tasks.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side Effects:
+ * The interpreters variables and code may be modified by the script
+ * but the result will not be modified.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+int
+TkBackgroundEvalObjv(
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv,
+ int flags)
+{
+ Tcl_InterpState state;
+ int n, r = TCL_OK;
+
+ /*
+ * Record the state of the interpreter.
+ */
+
+ Tcl_Preserve(interp);
+ state = Tcl_SaveInterpState(interp, TCL_OK);
+
+ /*
+ * Evaluate the command and handle any error.
+ */
+
+ for (n = 0; n < objc; ++n) {
+ Tcl_IncrRefCount(objv[n]);
+ }
+ r = Tcl_EvalObjv(interp, objc, objv, flags);
+ for (n = 0; n < objc; ++n) {
+ Tcl_DecrRefCount(objv[n]);
+ }
+ if (r == TCL_ERROR) {
+ Tcl_AddErrorInfo(interp, "\n (background event handler)");
+ Tcl_BackgroundError(interp);
+ }
+
+ /*
+ * Restore the state of the interpreter.
+ */
+
+ (void) Tcl_RestoreInterpState(interp, state);
+ Tcl_Release(interp);
+
+ return r;
+}
+
+/*
* Local Variables:
* mode: objc
* c-basic-offset: 4
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 4eb4a88..d4b2c85 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -8,6 +8,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2014 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,6 +17,7 @@
#include "tkMacOSXPrivate.h"
#include "tkMacOSXDebug.h"
#include "xbytes.h"
+#include "tkButton.h"
/*
#ifdef TK_MAC_DEBUG
@@ -113,10 +115,79 @@ TkMacOSXInitCGDrawing(
/*
*----------------------------------------------------------------------
*
+ * BitmapRepFromDrawableRect
+ *
+ * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep.
+ *
+ * Results:
+ * Returns an autoreleased NSBitmapRep representing the image of the given
+ * rectangle of the given drawable.
+ *
+ * NOTE: The x,y coordinates should be relative to a coordinate system with
+ * origin at the top left, as used by XImage and CGImage, not bottom
+ * left as used by NSView.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+NSBitmapImageRep*
+BitmapRepFromDrawableRect(
+ Drawable drawable,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height)
+{
+ MacDrawable *mac_drawable = (MacDrawable *) drawable;
+ CGContextRef cg_context=NULL;
+ CGImageRef cg_image=NULL, sub_cg_image=NULL;
+ NSBitmapImageRep *bitmap_rep=NULL;
+ NSView *view=NULL;
+ if ( mac_drawable->flags & TK_IS_PIXMAP ) {
+ /*
+ This means that the MacDrawable is functioning as a Tk Pixmap, so its view
+ field is NULL. It's context field should point to a CGImage.
+ */
+ cg_context = GetCGContextForDrawable(drawable);
+ CGRect image_rect = CGRectMake(x, y, width, height);
+ cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context);
+ sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect);
+ if ( sub_cg_image ) {
+ bitmap_rep = [[NSBitmapImageRep alloc] autorelease];
+ [bitmap_rep initWithCGImage:sub_cg_image];
+ }
+ if ( cg_image ) {
+ CGImageRelease(cg_image);
+ }
+ } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) {
+ /* convert top-left coordinates to NSView coordinates */
+ int view_height = [view bounds].size.height;
+ NSRect view_rect = NSMakeRect(x + mac_drawable->xOff,
+ view_height - height - y - mac_drawable->yOff,
+ width,height);
+
+ if ( [view lockFocusIfCanDraw] ) {
+ bitmap_rep = [[NSBitmapImageRep alloc] autorelease];
+ bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect];
+ [view unlockFocus];
+ } else {
+ TkMacOSXDbgMsg("Could not lock focus on view.");
+ }
+
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ return bitmap_rep;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* XCopyArea --
*
- * Copies data from one drawable to another using block transfer
- * routines.
+ * Copies data from one drawable to another.
*
* Results:
* None.
@@ -143,76 +214,50 @@ XCopyArea(
{
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
+ NSBitmapImageRep *bitmap_rep = NULL;
+ CGImageRef img = NULL;
display->request++;
+
if (!width || !height) {
- /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
+ /* This happens all the time.
+ TkMacOSXDbgMsg("Drawing of empty area requested");
+ */
return;
}
- if (srcDraw->flags & TK_IS_PIXMAP) {
- if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
- return;
- }
- if (dc.context) {
- CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
- if (img) {
- DrawCGImage(dst, gc, dc.context, img, gc->foreground,
- gc->background, CGRectMake(0, 0,
- srcDraw->size.width, srcDraw->size.height),
- CGRectMake(src_x, src_y, width, height),
- CGRectMake(dest_x, dest_y, width, height));
- CFRelease(img);
- } else {
- TkMacOSXDbgMsg("Invalid source drawable");
+ if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
+ TkMacOSXDbgMsg("Failed to setup drawing context.");
+ }
+
+ if ( dc.context ) {
+ if (srcDraw->flags & TK_IS_PIXMAP) {
+ img = TkMacOSXCreateCGImageWithDrawable(src);
+ }else if (TkMacOSXDrawableWindow(src)) {
+ bitmap_rep = BitmapRepFromDrawableRect(src, src_x, src_y, width, height);
+ if ( bitmap_rep ) {
+ img = [bitmap_rep CGImage];
}
} else {
- TkMacOSXDbgMsg("Invalid destination drawable");
- }
- TkMacOSXRestoreDrawingContext(&dc);
- } else if (TkMacOSXDrawableWindow(src)) {
- NSView *view = TkMacOSXDrawableView(srcDraw);
- NSWindow *w = [view window];
- NSInteger gs = [w windowNumber] > 0 ? [w gState] : 0;
- /* // alternative using per-view gState:
- NSInteger gs = [view gState];
- if (!gs) {
- [view allocateGState];
- if ([view lockFocusIfCanDraw]) {
- [view unlockFocus];
- }
- gs = [view gState];
+ TkMacOSXDbgMsg("Invalid source drawable - neither window nor pixmap.");
}
- */
- if (!gs || !TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
- return;
- }
- if (dc.context) {
- NSGraphicsContext *gc = nil;
- CGFloat boundsH = [view bounds].size.height;
- NSRect srcRect = NSMakeRect(srcDraw->xOff + src_x, boundsH -
- height - (srcDraw->yOff + src_y), width, height);
-
- if (((MacDrawable *) dst)->flags & TK_IS_PIXMAP) {
- gc = [NSGraphicsContext graphicsContextWithGraphicsPort:
- dc.context flipped:NO];
- if (gc) {
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:gc];
- }
- }
- NSCopyBits(gs, srcRect, NSMakePoint(dest_x,
- dc.portBounds.size.height - dest_y));
- if (gc) {
- [NSGraphicsContext restoreGraphicsState];
- }
+
+ if (img) {
+ DrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background,
+ CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
+ CGRectMake(src_x, src_y, width, height),
+ CGRectMake(dest_x, dest_y, width, height));
+ CFRelease(img);
} else {
- TkMacOSXDbgMsg("Invalid destination drawable");
+ TkMacOSXDbgMsg("Failed to construct CGImage.");
}
- TkMacOSXRestoreDrawingContext(&dc);
+
} else {
- TkMacOSXDbgMsg("Invalid source drawable");
+ TkMacOSXDbgMsg("Invalid destination drawable - no context.");
+ return;
}
+
+ TkMacOSXRestoreDrawingContext(&dc);
}
/*
@@ -253,7 +298,7 @@ XCopyPlane(
display->request++;
if (!width || !height) {
- /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
+ /* TkMacOSXDbgMsg("Drawing of empty area requested"); */
return;
}
if (plane != 1) {
@@ -347,6 +392,7 @@ TkPutImage(
TkMacOSXDbgMsg("Invalid destination drawable");
}
TkMacOSXRestoreDrawingContext(&dc);
+ return Success;
}
/*
@@ -382,13 +428,7 @@ CreateCGImageWithXImage(
char *data = NULL;
CGDataProviderReleaseDataCallback releaseData = ReleaseData;
- if (image->obdata) {
- /*
- * Image from XGetImage
- */
-
- img = TkMacOSXCreateCGImageWithDrawable((Pixmap) image->obdata);
- } else if (image->bits_per_pixel == 1) {
+ if (image->bits_per_pixel == 1) {
/*
* BW image
*/
@@ -423,13 +463,13 @@ CreateCGImageWithXImage(
* Color image
*/
- CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
bitsPerComponent = 8;
bitsPerPixel = 32;
bitmapInfo = (image->byte_order == MSBFirst ?
kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) |
- kCGImageAlphaNoneSkipFirst;
+ kCGImageAlphaNoneSkipFirst;
data = memcpy(ckalloc(len), image->data + image->xoffset, len);
if (data) {
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
@@ -744,7 +784,6 @@ DrawCGImage(
} else {
TkMacOSXDbgMsg("Drawing of empty CGImage requested");
}
- return Success;
}
/*
@@ -1439,43 +1478,72 @@ TkScrollWindow(
int dx, int dy, /* Distance rectangle should be moved. */
TkRegion damageRgn) /* Region to accumulate damage in. */
{
- MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin);
+ Drawable drawable = Tk_WindowId(tkwin);
+ MacDrawable *macDraw = (MacDrawable *) drawable;
NSView *view = TkMacOSXDrawableView(macDraw);
- CGRect visRect, srcRect, dstRect;
- CGFloat boundsH;
- HIShapeRef dmgRgn, dstRgn;
+ CGRect srcRect, dstRect;
+ HIShapeRef dmgRgn = NULL, extraRgn;
+ NSRect bounds, visRect, scrollSrc, scrollDst;
+ NSPoint delta = NSMakePoint(dx, dy);
int result;
-
- if (view && !CGRectIsEmpty(visRect = NSRectToCGRect([view visibleRect]))) {
- boundsH = [view bounds].size.height;
- srcRect = CGRectMake(macDraw->xOff + x, boundsH - height -
- (macDraw->yOff + y), width, height);
- dstRect = CGRectIntersection(CGRectOffset(srcRect, dx, -dy), visRect);
- srcRect = CGRectIntersection(srcRect, visRect);
- if (!CGRectIsEmpty(srcRect) && !CGRectIsEmpty(dstRect)) {
- /*
- CGRect sRect = CGRectIntersection(CGRectOffset(dstRect, -dx, dy),
- srcRect);
- NSCopyBits(0, NSRectFromCGRect(sRect),
- NSPointFromCGPoint(CGRectOffset(sRect, dx, -dy).origin));
- */
- [view scrollRect:NSRectFromCGRect(srcRect) by:NSMakeSize(dx, -dy)];
- }
- srcRect.origin.y = boundsH - srcRect.size.height - srcRect.origin.y;
- dstRect.origin.y = boundsH - dstRect.size.height - dstRect.origin.y;
- srcRect = CGRectUnion(srcRect, dstRect);
- dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
- dstRgn = HIShapeCreateWithRect(&dstRect);
- ChkErr(HIShapeDifference, dmgRgn, dstRgn, (HIMutableShapeRef) dmgRgn);
- CFRelease(dstRgn);
- TkMacOSXInvalidateViewRegion(view, dmgRgn);
- } else {
- dmgRgn = HIShapeCreateEmpty();
+
+ if ( view ) {
+ /* Get the scroll area in NSView coordinates (origin at bottom left). */
+ bounds = [view bounds];
+ scrollSrc = NSMakeRect(
+ macDraw->xOff + x,
+ bounds.size.height - height - (macDraw->yOff + y),
+ width, height);
+ scrollDst = NSOffsetRect(scrollSrc, dx, -dy);
+ /* Limit scrolling to the window content area. */
+ visRect = [view visibleRect];
+ scrollSrc = NSIntersectionRect(scrollSrc, visRect);
+ scrollDst = NSIntersectionRect(scrollDst, visRect);
+
+ if ( !NSIsEmptyRect(scrollSrc) && !NSIsEmptyRect(scrollDst) ) {
+
+ /*
+ * Mark the difference between source and destination as damaged.
+ * This region is described in the Tk coordinate system.
+ */
+
+ srcRect = CGRectMake(x, y, width, height);
+ dstRect = CGRectOffset(srcRect, dx, dy);
+ dmgRgn = HIShapeCreateMutableWithRect(&srcRect);
+ extraRgn = HIShapeCreateWithRect(&dstRect);
+ ChkErr(HIShapeDifference, dmgRgn, extraRgn, (HIMutableShapeRef) dmgRgn);
+ CFRelease(extraRgn);
+
+ /* Scroll the rectangle. */
+ [view scrollRect:scrollSrc by:NSMakeSize(dx, -dy)];
+
+ /*
+ * Adjust the positions of the button subwindows that meet the scroll
+ * area.
+ */
+
+ for (NSView *subview in [view subviews] ) {
+ if ( [subview isKindOfClass:[NSButton class]] == YES ) {
+ NSRect subframe = [subview frame];
+ if ( NSIntersectsRect(scrollSrc, subframe) ||
+ NSIntersectsRect(scrollDst, subframe) ) {
+ TkpShiftButton((NSButton *)subview, delta );
+ }
+ }
+ }
+
+ /* Redisplay the scrolled area. */
+ [view displayRect:scrollDst];
+
+ }
+ }
+
+ if ( dmgRgn == NULL ) {
+ dmgRgn = HIShapeCreateEmpty();
}
TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
CFRelease(dmgRgn);
-
return result;
}
@@ -1688,6 +1756,7 @@ TkMacOSXRestoreDrawingContext(
{
if (dcPtr->context) {
CGContextSynchronize(dcPtr->context);
+ [[dcPtr->view window] setViewsNeedDisplay:YES];
[[dcPtr->view window] enableFlushWindow];
if (dcPtr->focusLocked) {
[dcPtr->view unlockFocus];
diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c
index 43117a1..9671ab9 100644
--- a/macosx/tkMacOSXHLEvents.c
+++ b/macosx/tkMacOSXHLEvents.c
@@ -222,7 +222,7 @@ OappHandler(
if (interp &&
Tcl_GetCommandInfo(interp, "::tk::mac::OpenApplication", &dummy)){
- int code = Tcl_GlobalEval(interp, "::tk::mac::OpenApplication");
+ int code = Tcl_EvalEx(interp, "::tk::mac::OpenApplication", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
@@ -259,7 +259,7 @@ RappHandler(
if (interp && Tcl_GetCommandInfo(interp,
"::tk::mac::ReopenApplication", &dummy)) {
- int code = Tcl_GlobalEval(interp, "::tk::mac::ReopenApplication");
+ int code = Tcl_EvalEx(interp, "::tk::mac::ReopenApplication", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK){
Tcl_BackgroundError(interp);
}
@@ -295,7 +295,7 @@ PrefsHandler(
if (interp &&
Tcl_GetCommandInfo(interp, "::tk::mac::ShowPreferences", &dummy)){
- int code = Tcl_GlobalEval(interp, "::tk::mac::ShowPreferences");
+ int code = Tcl_EvalEx(interp, "::tk::mac::ShowPreferences", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
Tcl_BackgroundError(interp);
}
@@ -625,7 +625,7 @@ ReallyKillMe(
Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp;
Tcl_CmdInfo dummy;
int quit = Tcl_GetCommandInfo(interp, "::tk::mac::Quit", &dummy);
- int code = Tcl_GlobalEval(interp, quit ? "::tk::mac::Quit" : "exit");
+ int code = Tcl_EvalEx(interp, quit ? "::tk::mac::Quit" : "exit", -1, TCL_EVAL_GLOBAL);
if (code != TCL_OK) {
/*
diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c
index 2bf1962..1d14990 100644
--- a/macosx/tkMacOSXInit.c
+++ b/macosx/tkMacOSXInit.c
@@ -225,11 +225,16 @@ TkpInit(
if (!uname(&name)) {
tkMacOSXMacOSXVersion = (strtod(name.release, NULL) + 96) * 10;
}
- if (tkMacOSXMacOSXVersion &&
+ /*Check for new versioning scheme on Yosemite (10.10) and later.*/
+ if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) {
+ tkMacOSXMacOSXVersion = MAC_OS_X_VERSION_MIN_REQUIRED/100;
+ }
+ if (tkMacOSXMacOSXVersion && MAC_OS_X_VERSION_MIN_REQUIRED < 100000 &&
tkMacOSXMacOSXVersion/10 < MAC_OS_X_VERSION_MIN_REQUIRED/10) {
Tcl_Panic("Mac OS X 10.%d or later required !",
(MAC_OS_X_VERSION_MIN_REQUIRED/10)-100);
}
+
#ifdef TK_FRAMEWORK
/*
diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h
index 813acce..249d5cf 100644
--- a/macosx/tkMacOSXInt.h
+++ b/macosx/tkMacOSXInt.h
@@ -24,6 +24,7 @@
#ifndef _TKMAC
#include "tkMacOSX.h"
+#import <Cocoa/Cocoa.h>
#endif
/*
@@ -196,7 +197,7 @@ MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x,
int y, int width, int height);
MODULE_SCOPE void TkpRetainRegion(TkRegion r);
MODULE_SCOPE void TkpReleaseRegion(TkRegion r);
-
+MODULE_SCOPE void TkpShiftButton(NSButton *button, NSPoint delta);
/*
* Include the stubbed internal platform-specific API.
*/
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c
index 1d24960..0cfb663 100644
--- a/macosx/tkMacOSXKeyEvent.c
+++ b/macosx/tkMacOSXKeyEvent.c
@@ -241,7 +241,7 @@ static unsigned isFunctionKey(unsigned int code);
finishedCompose = YES;
/* first, clear any working text */
- if (_workingText != nil)
+ if (privateWorkingText != nil)
[self deleteWorkingText];
/* now insert the string as keystrokes */
@@ -275,13 +275,13 @@ static unsigned isFunctionKey(unsigned int code);
NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
selRange.length, selRange.location);
- if (_workingText != nil)
+ if (privateWorkingText != nil)
[self deleteWorkingText];
if ([str length] == 0)
return;
processingCompose = YES;
- _workingText = [str copy];
+ privateWorkingText = [str copy];
//PENDING: insert workingText underlined
}
@@ -290,12 +290,12 @@ static unsigned isFunctionKey(unsigned int code);
/* delete display of composing characters [not in <NSTextInput>] */
- (void)deleteWorkingText
{
- if (_workingText == nil)
+ if (privateWorkingText == nil)
return;
if (NS_KEYLOG)
- NSLog(@"deleteWorkingText len = %d\n", [_workingText length]);
- [_workingText release];
- _workingText = nil;
+ NSLog(@"deleteWorkingText len = %d\n", [privateWorkingText length]);
+ [privateWorkingText release];
+ privateWorkingText = nil;
processingCompose = NO;
//PENDING: delete working text
@@ -304,14 +304,14 @@ static unsigned isFunctionKey(unsigned int code);
- (BOOL)hasMarkedText
{
- return _workingText != nil;
+ return privateWorkingText != nil;
}
- (NSRange)markedRange
{
- NSRange rng = _workingText != nil
- ? NSMakeRange (0, [_workingText length]) : NSMakeRange (NSNotFound, 0);
+ NSRange rng = privateWorkingText != nil
+ ? NSMakeRange (0, [privateWorkingText length]) : NSMakeRange (NSNotFound, 0);
if (NS_KEYLOG)
NSLog (@"markedRange request");
return rng;
diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c
index 2b4dbc8..e1cdc76 100644
--- a/macosx/tkMacOSXMenu.c
+++ b/macosx/tkMacOSXMenu.c
@@ -683,15 +683,18 @@ TkpConfigureMenuEntry(
int i = 0;
NSArray *itemArray = [submenu itemArray];
for (NSMenuItem *item in itemArray) {
- TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i];
- [item setEnabled: !(submePtr->state == ENTRY_DISABLED)];
- i++;
+ 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++;
}
}
-
}
}
}
+
[menuItem setSubmenu:submenu];
return TCL_OK;
@@ -754,11 +757,19 @@ TkpPostMenu(
* to be posted. */
int y) /* The global y-coordinate */
{
- NSWindow *win = [NSApp keyWindow];
- if (!win) {
+
+
+ /* 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];
+
inPostMenu = 1;
int oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
@@ -827,7 +838,7 @@ TkpSetWindowMenuBar(
*
*----------------------------------------------------------------------
*/
-
+
void
TkpSetMainMenubar(
Tcl_Interp *interp, /* The interpreter of the application */
diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c
index eaa444a..abb2c6e 100644
--- a/macosx/tkMacOSXMenubutton.c
+++ b/macosx/tkMacOSXMenubutton.c
@@ -127,6 +127,7 @@ TkpDestroyMenuButton(
TkMenuButton *mbPtr)
{
MacMenuButton *macButtonPtr = (MacMenuButton *) mbPtr;
+ [macButtonPtr->button setTag:(NSInteger)-1];
TkMacOSXMakeCollectableAndRelease(macButtonPtr->button);
}
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index 3ad0689..4855635 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -228,6 +228,8 @@ MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr);
MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr);
MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window);
MODULE_SCOPE EventModifiers TkMacOSXModifierState(void);
+MODULE_SCOPE NSBitmapImageRep* BitmapRepFromDrawableRect(Drawable drawable,
+ int x, int y, unsigned int width, unsigned int height);
MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc,
int useCG, TkMacOSXDrawingContext *dcPtr);
MODULE_SCOPE void TkMacOSXRestoreDrawingContext(
@@ -316,9 +318,12 @@ VISIBILITY_HIDDEN
VISIBILITY_HIDDEN
@interface TKContentView : NSView <NSTextInput> {
@private
+ /*Remove private API calls.*/
+ #if 0
id _savedSubviews;
BOOL _subviewsSetAside;
- NSString *_workingText;
+ #endif
+ NSString *privateWorkingText;
}
@end
@@ -358,9 +363,5 @@ VISIBILITY_HIDDEN
keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask;
@end
-/* From WebKit/WebKit/mac/WebCoreSupport/WebChromeClient.mm: */
-@interface NSWindow(TKGrowBoxRect)
-- (NSRect)_growBoxRect;
-@end
#endif /* _TKMACPRIV */
diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c
index 8432299..c716ab7 100644
--- a/macosx/tkMacOSXRegion.c
+++ b/macosx/tkMacOSXRegion.c
@@ -158,6 +158,29 @@ TkUnionRectWithRegion(
/*
*----------------------------------------------------------------------
*
+ * TkMacOSXIsEmptyRegion --
+ *
+ * Return native region for given tk region.
+ *
+ * Results:
+ * 1 if empty, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXIsEmptyRegion(
+ TkRegion r)
+{
+ return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkRectInRegion --
*
* Implements the equivelent of the X window function XRectInRegion. See
@@ -181,12 +204,14 @@ TkRectInRegion(
unsigned int width,
unsigned int height)
{
- int result;
- const CGRect r = CGRectMake(x, y, width, height);
-
- result = HIShapeIntersectsRect((HIShapeRef) region, &r) ?
+ if ( TkMacOSXIsEmptyRegion(region) ) {
+ return RectangleOut;
+ }
+ else {
+ const CGRect r = CGRectMake(x, y, width, height);
+ return HIShapeIntersectsRect((HIShapeRef) region, &r) ?
RectanglePart : RectangleOut;
- return result;
+ }
}
/*
@@ -332,12 +357,11 @@ TkpReleaseRegion(
{
CFRelease(r);
}
-#if 0
/*
*----------------------------------------------------------------------
*
- * TkMacOSXEmtpyRegion --
+ * TkMacOSXSetEmptyRegion --
*
* Set region to emtpy.
*
@@ -351,7 +375,7 @@ TkpReleaseRegion(
*/
void
-TkMacOSXEmtpyRegion(
+TkMacOSXSetEmptyRegion(
TkRegion r)
{
ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);
@@ -360,30 +384,6 @@ TkMacOSXEmtpyRegion(
/*
*----------------------------------------------------------------------
*
- * TkMacOSXIsEmptyRegion --
- *
- * Return native region for given tk region.
- *
- * Results:
- * 1 if empty, 0 otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TkMacOSXIsEmptyRegion(
- TkRegion r)
-{
- return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
* TkMacOSXGetNativeRegion --
*
* Return native region for given tk region.
diff --git a/macosx/tkMacOSXScale.c b/macosx/tkMacOSXScale.c
index e94763d..a37029c 100644
--- a/macosx/tkMacOSXScale.c
+++ b/macosx/tkMacOSXScale.c
@@ -145,7 +145,7 @@ TkpDisplayScale(
Tk_Window tkwin = scalePtr->tkwin;
Tcl_Interp *interp = scalePtr->interp;
int result;
- char string[PRINT_CHARS];
+ char string[TCL_DOUBLE_SPACE];
MacScale *macScalePtr = (MacScale *) clientData;
Rect r;
WindowRef windowRef;
diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c
index ff91ffd..e0a583d 100644
--- a/macosx/tkMacOSXScrlbr.c
+++ b/macosx/tkMacOSXScrlbr.c
@@ -21,13 +21,74 @@
#endif
*/
+NSRect TkMacOSXGetScrollFrame(TkScrollbar *scrlPtr);
+
+/*
+ * A subclass of NSScroller with sanity checking:
+ *
+ * NSScrollers created by Tk will have their tag set to a pointer to the
+ * TkScrollbar which manages the NSScroller. This allows an NSScroller to be
+ * aware of the state of its Tk parent. This subclass overrides the drawRect
+ * method so that it will not draw itself if the widget is completely outside
+ * of its container.
+ */
+
+@interface TkNSScroller: NSScroller
+-(void) drawRect:(NSRect)dirtyRect;
+
+@end
+
+@implementation TkNSScroller
+
+ - (void)drawRect:(NSRect)dirtyRect
+ {
+ NSInteger tag = [self tag];
+ if ( tag != -1) {
+ TkScrollbar *scrollPtr = (TkScrollbar *)tag;
+ MacDrawable* macWin = (MacDrawable *)scrollPtr;
+ Tk_Window tkwin = scrollPtr->tkwin;
+ NSRect Tkframe = TkMacOSXGetScrollFrame(scrollPtr);
+ /* Do not draw if the widget is misplaced or unmapped. */
+ if ( NSIsEmptyRect(Tkframe) ||
+ ! macWin->winPtr->flags & TK_MAPPED ||
+ ! NSEqualRects(Tkframe, [self frame])
+ ) {
+ return;
+ }
+
+ /*
+ * Do not draw if the widget is completely outside of its parent.
+ */
+ if (tkwin) {
+ int parent_height = Tk_Height(Tk_Parent(tkwin));
+ int widget_height = Tk_Height(tkwin);
+ int y = Tk_Y(tkwin);
+ if ( y > parent_height || y + widget_height < 0 ) {
+ return;
+ }
+
+ int parent_width = Tk_Width(Tk_Parent(tkwin));
+ int widget_width = Tk_Width(tkwin);
+ int x = Tk_X(tkwin);
+ if (x > parent_width || x + widget_width < 0) {
+ return;
+ }
+ }
+ }
+ [super drawRect:dirtyRect];
+ }
+
+@end
+
+
+
/*
* Declaration of Mac specific scrollbar structure.
*/
typedef struct MacScrollbar {
TkScrollbar info;
- NSScroller *scroller;
+ TkNSScroller *scroller;
int variant;
} MacScrollbar;
@@ -50,6 +111,7 @@ static void UpdateScrollbarMetrics(void);
static void ScrollbarEventProc(ClientData clientData,
XEvent *eventPtr);
+
/*
* The class procedure table for the scrollbar widget.
*/
@@ -66,7 +128,7 @@ Tk_ClassProcs tkpScrollbarProcs = {
#define NSAppleAquaScrollBarVariantChanged @"AppleAquaScrollBarVariantChanged"
@implementation TKApplication(TKScrlbr)
-- (void) tkScroller: (NSScroller *) scroller
+- (void) tkScroller: (TkNSScroller *) scroller
{
NSScrollerPart hitPart = [scroller hitPart];
TkScrollbar *scrollPtr = (TkScrollbar *)[scroller tag];
@@ -254,6 +316,8 @@ TkpDestroyScrollbar(
TkScrollbar *scrollPtr)
{
MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
+ TkNSScroller *scroller = macScrollPtr->scroller;
+ [scroller setTag:(NSInteger)-1];
TkMacOSXMakeCollectableAndRelease(macScrollPtr->scroller);
}
@@ -282,7 +346,7 @@ TkpDisplayScrollbar(
{
TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
- NSScroller *scroller = macScrollPtr->scroller;
+ TkNSScroller *scroller = macScrollPtr->scroller;
Tk_Window tkwin = scrollPtr->tkwin;
TkWindow *winPtr = (TkWindow *) tkwin;
MacDrawable *macWin = (MacDrawable *) winPtr->window;
@@ -329,38 +393,22 @@ TkpDisplayScrollbar(
frame = NSInsetRect(frame, scrollPtr->inset, scrollPtr->inset);
frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
- NSWindow *w = [view window];
-
- if ([w showsResizeIndicator]) {
- NSRect growBox = [view convertRect:[w _growBoxRect] fromView:nil];
-
- if (NSIntersectsRect(growBox, frame)) {
- if (scrollPtr->vertical) {
- CGFloat y = frame.origin.y;
-
- frame.origin.y = growBox.origin.y + growBox.size.height;
- frame.size.height -= frame.origin.y - y;
- } else {
- frame.size.width = growBox.origin.x - frame.origin.x;
- }
- TkMacOSXSetScrollbarGrow(winPtr, true);
- }
- }
if (!NSEqualRects(frame, [scroller frame])) {
[scroller setFrame:frame];
}
[scroller setEnabled:(knobProportion < 1.0 &&
(scrollPtr->vertical ? frame.size.height : frame.size.width) >
metrics[macScrollPtr->variant].minHeight)];
+ // [scroller setEnabled: YES];
[scroller setDoubleValue:scrollPtr->firstFraction / (1.0 - knobProportion)];
[scroller setKnobProportion:knobProportion];
[scroller displayRectIgnoringOpacity:[scroller bounds]];
TkMacOSXRestoreDrawingContext(&dc);
-#ifdef TK_MAC_DEBUG_SCROLLBAR
+ #ifdef TK_MAC_DEBUG_SCROLLBAR
TKLog(@"scroller %s frame %@ width %d height %d",
((TkWindow *)scrollPtr->tkwin)->pathName, NSStringFromRect(frame),
Tk_Width(tkwin), Tk_Height(tkwin));
-#endif
+ #endif
}
/*
@@ -388,7 +436,7 @@ TkpComputeScrollbarGeometry(
* changed. */
{
MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
- NSScroller *scroller = macScrollPtr->scroller;
+ TkNSScroller *scroller = macScrollPtr->scroller;
int width, height, variant, fieldLength;
if (scrollPtr->highlightWidth < 0) {
@@ -416,7 +464,7 @@ TkpComputeScrollbarGeometry(
}
if (!scroller) {
if ((width > height) ^ !scrollPtr->vertical) {
- /* -[NSScroller initWithFrame:] determines horizonalness for the
+ /* -[NSScroller initWithFrame:] determines horizontalness for the
* lifetime of the scroller via isHoriz = (width > height) */
if (scrollPtr->vertical) {
width = height;
@@ -427,7 +475,7 @@ TkpComputeScrollbarGeometry(
width = 2;
}
}
- scroller = [[NSScroller alloc] initWithFrame:
+ scroller = [[TkNSScroller alloc] initWithFrame:
NSMakeRect(0, 0, width, height)];
macScrollPtr->scroller = TkMacOSXMakeUncollectable(scroller);
[scroller setAction:@selector(tkScroller:)];
@@ -548,7 +596,7 @@ TkpScrollbarPosition(
/* Scrollbar widget record. */
int x, int y) /* Coordinates within scrollPtr's window. */
{
- NSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
+ TkNSScroller *scroller = ((MacScrollbar *) scrollPtr)->scroller;
MacDrawable *macWin = (MacDrawable *)
((TkWindow *) scrollPtr->tkwin)->window;
NSView *view = TkMacOSXDrawableView(macWin);
@@ -609,6 +657,45 @@ ScrollbarEventProc(
TkScrollbarEventProc(clientData, eventPtr);
}
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetScrollFrame --
+ *
+ * Computes a frame for an NSScroller that will correspond to where
+ * Tk thinks the scroller is located.
+ *
+ * Results:
+ * Returns an NSRect describing a frame for an NSScrollbar.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+NSRect TkMacOSXGetScrollFrame(
+ TkScrollbar *scrlPtr)
+{
+ MacScrollbar *macscrlPtr = (MacScrollbar *) scrlPtr;
+ Tk_Window tkwin = scrlPtr->tkwin;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ if (tkwin) {
+ MacDrawable *macWin = (MacDrawable *) winPtr->window;
+ NSView *view = TkMacOSXDrawableView(macWin);
+ CGFloat viewHeight = [view bounds].size.height;
+ NSRect frame = NSMakeRect(macWin->xOff, macWin->yOff,
+ Tk_Width(tkwin), Tk_Height(tkwin));
+
+ frame.origin.y = viewHeight - (frame.origin.y + frame.size.height);
+ return frame;
+ } else {
+ return NSZeroRect;
+ }
+}
+
+
/*
* Local Variables:
diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c
index c235cbf..d557db3 100644
--- a/macosx/tkMacOSXSubwindows.c
+++ b/macosx/tkMacOSXSubwindows.c
@@ -651,7 +651,7 @@ XConfigureWindow(
*
* TkMacOSXUpdateClipRgn --
*
- * This function updates the cliping regions for a given window and all of
+ * This function updates the clipping regions for a given window and all of
* its children. Once updated the TK_CLIP_INVALID flag in the subwindow
* data structure is unset. The TK_CLIP_INVALID flag should always be
* unset before any drawing is attempted.
@@ -741,14 +741,6 @@ TkMacOSXUpdateClipRgn(
} else if (winPtr->wmInfoPtr->attributes &
kWindowResizableAttribute) {
NSWindow *w = TkMacOSXDrawableWindow(winPtr->window);
-
- if (w) {
- bounds = NSRectToCGRect([w _growBoxRect]);
- bounds.origin.y = [w contentRectForFrameRect:
- [w frame]].size.height - bounds.size.height -
- bounds.origin.y;
- ChkErr(TkMacOSHIShapeDifferenceWithRect, rgn, &bounds);
- }
}
macWin->aboveVisRgn = HIShapeCreateCopy(rgn);
@@ -825,7 +817,7 @@ TkMacOSXUpdateClipRgn(
*
* TkMacOSXVisableClipRgn --
*
- * This function returns the Macintosh cliping region for the given
+ * This function returns the Macintosh clipping region for the given
* window. The caller is responsible for disposing of the returned
* region via TkDestroyRegion().
*
@@ -920,7 +912,7 @@ TkMacOSXInvalidateWindow(
* TK_PARENT_WINDOW */
{
#ifdef TK_MAC_DEBUG_CLIP_REGIONS
- TkMacOSXDbgMsg("%s", winPtr->pathName);
+ TkMacOSXDbgMsg("%s", macWin->winPtr->pathName);
#endif
if (macWin->flags & TK_CLIP_INVALID) {
TkMacOSXUpdateClipRgn(macWin->winPtr);
@@ -1078,7 +1070,7 @@ TkMacOSXGetRootControl(
* None.
*
* Side effects:
- * The cliping regions for the window and its children are mark invalid.
+ * The clipping regions for the window and its children are marked invalid.
* (Make sure they are valid before drawing.)
*
*----------------------------------------------------------------------
@@ -1097,6 +1089,10 @@ TkMacOSXInvalClipRgns(
* be marked.
*/
+#ifdef TK_MAC_DEBUG_CLIP_REGIONS
+ TkMacOSXDbgMsg("%s", winPtr->pathName);
+#endif
+
if (!macWin || macWin->flags & TK_CLIP_INVALID) {
return;
}
@@ -1277,7 +1273,7 @@ UpdateOffsets(
* Returns a handle to a new pixmap.
*
* Side effects:
- * Allocates a new Macintosh GWorld.
+ * Allocates a new CGBitmapContext.
*
*----------------------------------------------------------------------
*/
@@ -1323,7 +1319,7 @@ Tk_GetPixmap(
* None.
*
* Side effects:
- * Deletes the Macintosh GWorld created by Tk_GetPixmap.
+ * Deletes the CGBitmapContext created by Tk_GetPixmap.
*
*----------------------------------------------------------------------
*/
diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c
index 6ced470..c4780c8 100644
--- a/macosx/tkMacOSXWindowEvent.c
+++ b/macosx/tkMacOSXWindowEvent.c
@@ -357,11 +357,12 @@ GenerateUpdates(
event.xexpose.width = damageBounds.size.width;
event.xexpose.height = damageBounds.size.height;
event.xexpose.count = 0;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
-#ifdef TK_MAC_DEBUG_DRAWING
- TKLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
+ Tk_HandleEvent(&event);
+
+ #ifdef TK_MAC_DEBUG_DRAWING
+ NSLog(@"Expose %p {{%d, %d}, {%d, %d}}", event.xany.window, event.xexpose.x,
event.xexpose.y, event.xexpose.width, event.xexpose.height);
-#endif
+ #endif
/*
* Generate updates for the children of this window
@@ -388,7 +389,7 @@ GenerateUpdates(
/*
* TODO: Here we should handle out of process embedding.
*/
- }
+ }
return 1;
}
@@ -701,7 +702,7 @@ TkWmProtocolEventProc(
Tcl_Preserve(protPtr);
interp = protPtr->interp;
Tcl_Preserve(interp);
- result = Tcl_GlobalEval(interp, protPtr->command);
+ result = Tcl_EvalEx(interp, protPtr->command, -1, TCL_EVAL_GLOBAL);
if (result != TCL_OK) {
Tcl_AddErrorInfo(interp, "\n (command for \"");
Tcl_AddErrorInfo(interp,
@@ -764,15 +765,14 @@ Tk_MacOSXIsAppInFront(void)
* Custom content view for Tk NSWindows, containing standard NSView subviews.
* The goal is to emulate X11-style drawing in response to Expose events:
* during the normal AppKit drawing cycle, we supress drawing of all subviews
- * (using a technique adapted from WebKit's WebHTMLView) and instead send
- * Expose events about the subviews that would be redrawn. Tk Expose event
- * handling and drawing handlers then draw the subviews manually via their
- * -displayRectIgnoringOpacity:
+ * and instead send Expose events about the subviews that would be redrawn.
*/
@interface TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect;
- (void) generateExposeEvents: (HIMutableShapeRef) shape;
+- (void) viewDidEndLiveResize;
+- (void) viewWillDraw;
- (BOOL) isOpaque;
- (BOOL) wantsDefaultClipping;
- (BOOL) acceptsFirstResponder;
@@ -782,6 +782,17 @@ Tk_MacOSXIsAppInFront(void)
@implementation TKContentView
@end
+double drawTime;
+
+/*
+ * Set a minimum time for drawing to render. With removal of private NSView API's, default drawing
+ * is slower and less responsive. This number, which seems feasible after some experimentatation, skips
+ * some drawing to avoid lag.
+ */
+
+#define MAX_DYNAMIC_TIME .000000001
+
+/*Restrict event processing to Expose events.*/
static Tk_RestrictAction
ExposeRestrictProc(
ClientData arg,
@@ -791,6 +802,7 @@ ExposeRestrictProc(
? TK_PROCESS_EVENT : TK_DEFER_EVENT);
}
+
@implementation TKContentView(TKWindowEvent)
- (void) drawRect: (NSRect) rect
@@ -806,15 +818,10 @@ ExposeRestrictProc(
NSCompositeSourceOver);
#endif
- NSWindow *w = [self window];
-
- if ([self isOpaque] && [w showsResizeIndicator]) {
- NSRect bounds = [self convertRect:[w _growBoxRect] fromView:nil];
+ NSDate *beginTime=[NSDate date];
- if ([self needsToDrawRect:bounds]) {
- NSEraseRect(bounds);
- }
- }
+ /*Skip drawing during live resize if redraw is too slow.*/
+ if([self inLiveResize] && drawTime>MAX_DYNAMIC_TIME) return;
CGFloat height = [self bounds].size.height;
HIMutableShapeRef drawShape = HIShapeCreateMutable();
@@ -835,44 +842,64 @@ ExposeRestrictProc(
nil]];
}
CFRelease(drawShape);
+ drawTime=-[beginTime timeIntervalSinceNow];
}
+/*At conclusion of resize event, send notification and set view for redraw if earlier drawing was skipped because of lagginess.*/
+- (void)viewDidEndLiveResize
+{
+ if(drawTime>MAX_DYNAMIC_TIME) {
+ [self setNeedsDisplay:YES];
+ [super viewDidEndLiveResize];
+ }
+}
+
+-(void) viewWillDraw {
+ [self setNeedsDisplay:YES];
+ }
+
- (void) generateExposeEvents: (HIMutableShapeRef) shape
{
+
TkWindow *winPtr = TkMacOSXGetTkWindow([self window]);
unsigned long serial;
CGRect updateBounds;
if (!winPtr) {
- return;
+ return;
}
+
HIShapeGetBounds(shape, &updateBounds);
serial = LastKnownRequestProcessed(Tk_Display(winPtr));
if (GenerateUpdates(shape, &updateBounds, winPtr) &&
- ![[NSRunLoop currentRunLoop] currentMode] &&
- Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
- /*
- * Ensure there are no pending idle-time redraws that could prevent the
- * just posted Expose events from generating new redraws.
- */
+ ![[NSRunLoop currentRunLoop] currentMode] &&
+ Tcl_GetServiceMode() != TCL_SERVICE_NONE) {
+ /*
+ * Ensure there are no pending idle-time redraws that could prevent the
+ * just posted Expose events from generating new redraws.
+ */
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
- /*
- * For smoother drawing, process Expose events and resulting redraws
- * immediately instead of at idle time.
- */
+ /*
+ * For smoother drawing, process Expose events and resulting redraws
+ * immediately instead of at idle time.
+ */
- ClientData oldArg;
- Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
- UINT2PTR(serial), &oldArg);
+ ClientData oldArg;
+ Tk_RestrictProc *oldProc = Tk_RestrictEvents(ExposeRestrictProc,
+ UINT2PTR(serial), &oldArg);
- while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
- Tk_RestrictEvents(oldProc, oldArg, &oldArg);
- while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
- }
+ while (Tcl_ServiceEvent(TCL_WINDOW_EVENTS)) {}
+
+ Tk_RestrictEvents(oldProc, oldArg, &oldArg);
+ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS|TCL_DONT_WAIT)) {}
+
+ }
+
}
+/*This is no-op on 10.7 and up because Apple has removed this widget, but leaving here for backwards compatibility.*/
- (void) tkToolbarButton: (id) sender
{
#ifdef TK_MAC_DEBUG_EVENTS
@@ -900,21 +927,15 @@ ExposeRestrictProc(
Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL);
}
-#ifdef TK_MAC_DEBUG_DRAWING
- (void) setFrameSize: (NSSize) newSize
{
- TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
- NSStringFromSize(newSize));
[super setFrameSize:newSize];
}
- (void) setNeedsDisplayInRect: (NSRect) invalidRect
{
- TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
- NSStringFromRect(invalidRect));
[super setNeedsDisplayInRect:invalidRect];
}
-#endif
- (BOOL) isOpaque
{
@@ -947,153 +968,7 @@ ExposeRestrictProc(
}
@end
-
-#pragma mark TKContentViewPrivate
-/*
- * Technique adapted from WebKit/WebKit/mac/WebView/WebHTMLView.mm to supress
- * normal AppKit subview drawing and make all drawing go through us.
- * Overrides NSView internals.
- */
-
-@interface TKContentView(TKContentViewPrivate)
-- (id) initWithFrame: (NSRect) frame;
-- (void) _setAsideSubviews;
-- (void) _restoreSubviews;
-@end
-
-@interface NSView(TKContentViewPrivate)
-- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect
- isVisibleRect: (BOOL) isVisibleRect
- rectIsVisibleRectForView: (NSView *) visibleView
- topView: (BOOL) topView;
-- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus
- visRect: (NSRect) visRect;
-- (void) _recursive: (BOOL) recurse
- displayRectIgnoringOpacity: (NSRect) displayRect
- inContext: (NSGraphicsContext *) context topView: (BOOL) topView;
-- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect;
-- (BOOL) _drawRectIfEmpty;
-- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip;
-- (void) _setDrawsOwnDescendants: (BOOL) drawsOwnDescendants;
-@end
-
-@implementation TKContentView(TKContentViewPrivate)
-
-- (id) initWithFrame: (NSRect) frame
-{
- self = [super initWithFrame:frame];
- if (self) {
- _savedSubviews = nil;
- _subviewsSetAside = NO;
- [self _setDrawsOwnDescendants:YES];
- }
- return self;
-}
-
-- (void) _setAsideSubviews
-{
-#ifdef TK_MAC_DEBUG
- if (_subviewsSetAside || _savedSubviews) {
- Tcl_Panic("TKContentView _setAsideSubviews called incorrectly");
- }
-#endif
- _savedSubviews = _subviews;
- _subviews = nil;
- _subviewsSetAside = YES;
-}
-
-- (void) _restoreSubviews
-{
-#ifdef TK_MAC_DEBUG
- if (!_subviewsSetAside || _subviews) {
- Tcl_Panic("TKContentView _restoreSubviews called incorrectly");
- }
-#endif
- _subviews = _savedSubviews;
- _savedSubviews = nil;
- _subviewsSetAside = NO;
-}
-
-- (void) _recursiveDisplayRectIfNeededIgnoringOpacity: (NSRect) rect
- isVisibleRect: (BOOL) isVisibleRect
- rectIsVisibleRectForView: (NSView *) visibleView
- topView: (BOOL) topView
-{
- [self _setAsideSubviews];
- [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect
- isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView
- topView:topView];
- [self _restoreSubviews];
-}
-
-- (void) _recursiveDisplayAllDirtyWithLockFocus: (BOOL) needsLockFocus
- visRect: (NSRect) visRect
-{
- BOOL needToSetAsideSubviews = !_subviewsSetAside;
-
- if (needToSetAsideSubviews) {
- [self _setAsideSubviews];
- }
- [super _recursiveDisplayAllDirtyWithLockFocus:needsLockFocus
- visRect:visRect];
- if (needToSetAsideSubviews) {
- [self _restoreSubviews];
- }
-}
-
-- (void) _recursive: (BOOL) recurse
- displayRectIgnoringOpacity: (NSRect) displayRect
- inContext: (NSGraphicsContext *) context topView: (BOOL) topView
-{
- [self _setAsideSubviews];
- [super _recursive:recurse
- displayRectIgnoringOpacity:displayRect inContext:context
- topView:topView];
- [self _restoreSubviews];
-}
-
-- (void) _lightWeightRecursiveDisplayInRect: (NSRect) visRect
-{
- BOOL needToSetAsideSubviews = !_subviewsSetAside;
-
- if (needToSetAsideSubviews) {
- [self _setAsideSubviews];
- }
- [super _lightWeightRecursiveDisplayInRect:visRect];
- if (needToSetAsideSubviews) {
- [self _restoreSubviews];
- }
-}
-
-- (BOOL) _drawRectIfEmpty
-{
- /*
- * Our -drawRect manages subview drawing directly, so it needs to be called
- * even if the area to be redrawn is completely obscured by subviews.
- */
-
- return YES;
-}
-
-- (void) _drawRect: (NSRect) inRect clip: (BOOL) clip
-{
-#ifdef TK_MAC_DEBUG_DRAWING
- TKLog(@"-[%@(%p) %s%@]", [self class], self, _cmd,
- NSStringFromRect(inRect));
-#endif
- BOOL subviewsWereSetAside = _subviewsSetAside;
-
- if (subviewsWereSetAside) {
- [self _restoreSubviews];
- }
- [super _drawRect:inRect clip:clip];
- if (subviewsWereSetAside) {
- [self _setAsideSubviews];
- }
-}
-
-@end
/*
* Local Variables:
diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c
index 45f0fd5..b834766 100644
--- a/macosx/tkMacOSXWm.c
+++ b/macosx/tkMacOSXWm.c
@@ -20,6 +20,7 @@
#include "tkMacOSXWm.h"
#include "tkMacOSXEvent.h"
#include "tkMacOSXDebug.h"
+#include <Carbon/Carbon.h>
/*
#ifdef TK_MAC_DEBUG
@@ -321,6 +322,10 @@ static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr,
static void RemapWindows(TkWindow *winPtr,
MacDrawable *parentWin);
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+#define TK_GOT_AT_LEAST_SNOW_LEOPARD 1
+#endif
+
#pragma mark TKWindow(TKWm)
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
@@ -347,6 +352,7 @@ static void RemapWindows(TkWindow *winPtr,
kHelpWindowClass || winPtr->wmInfoPtr->attributes &
kWindowNoActivatesAttribute)) ? NO : YES;
}
+
@end
#pragma mark -
@@ -665,7 +671,7 @@ TkWmMapWindow(
wmPtr->flags |= WM_ABOUT_TO_MAP;
if (wmPtr->flags & WM_UPDATE_PENDING) {
- Tk_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
}
UpdateGeometryInfo(winPtr);
wmPtr->flags &= ~WM_ABOUT_TO_MAP;
@@ -769,7 +775,7 @@ TkWmDeadWindow(
ckfree(wmPtr->clientMachine);
}
if (wmPtr->flags & WM_UPDATE_PENDING) {
- Tk_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
}
/*
@@ -4396,7 +4402,7 @@ Tk_MoveToplevelWindow(
if (!(wmPtr->flags & WM_NEVER_MAPPED)) {
if (wmPtr->flags & WM_UPDATE_PENDING) {
- Tk_CancelIdleCall(UpdateGeometryInfo, winPtr);
+ Tcl_CancelIdleCall(UpdateGeometryInfo, winPtr);
}
UpdateGeometryInfo(winPtr);
}
@@ -4539,7 +4545,7 @@ TkWmAddToColormapWindows(
* add the toplevel itself as the last element of the list.
*/
- newPtr = ckalloc((count+2) * sizeof(TkWindow *));
+ newPtr = (TkWindow**)ckalloc((count+2) * sizeof(TkWindow *));
if (count > 0) {
memcpy(newPtr, oldPtr, count * sizeof(TkWindow *));
}
@@ -5183,6 +5189,7 @@ WmWinStyle(
{ "brown", NULL },
{ "clear", NULL },
{ "opacity", NULL },
+ { "fullscreen", NULL },
{ NULL }
};
@@ -5438,10 +5445,14 @@ TkMacOSXMakeRealWindowExist(
/* Set background color and opacity of window if those flags are set. */
if (colorName != NULL) {
[window setBackgroundColor: colorName];
- }
+ }
if (opaqueTag != NULL) {
+#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
[window setOpaque: opaqueTag];
+#else
+ [window setOpaque: YES];
+#endif
}
[window setDocumentEdited:NO];
@@ -5942,7 +5953,7 @@ TkWmStackorderToplevel(
Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS);
WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table);
- windows = ckalloc((table.numEntries+1) * sizeof(TkWindow *));
+ windows = (TkWindow**)ckalloc((table.numEntries+1) * sizeof(TkWindow *));
/*
* Special cases: If zero or one toplevels were mapped there is no need to
@@ -5967,7 +5978,7 @@ TkWmStackorderToplevel(
} else {
window_ptr = windows + table.numEntries;
*window_ptr-- = NULL;
- windowNumbers = ckalloc(windowCount * sizeof(NSInteger));
+ windowNumbers = (NSInteger*)ckalloc(windowCount * sizeof(NSInteger));
NSWindowList(windowCount, windowNumbers);
for (NSInteger index = 0; index < windowCount; index++) {
NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]];
@@ -6286,7 +6297,9 @@ TkMacOSXMakeFullscreen(
WmInfo *wmPtr = winPtr->wmInfoPtr;
int result = TCL_OK, wasFullscreen = (wmPtr->flags & WM_FULLSCREEN);
+#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
static unsigned long prevMask = 0, prevPres = 0;
+#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
if (fullscreen) {
int screenWidth = WidthOfScreen(Tk_Screen(winPtr));
@@ -6310,7 +6323,7 @@ TkMacOSXMakeFullscreen(
NSRect bounds = [window contentRectForFrameRect:[window frame]];
NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight);
- if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) {
+ if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) {
wmPtr->configX = wmPtr->x;
wmPtr->configY = wmPtr->y;
wmPtr->configAttributes = wmPtr->attributes;
@@ -6319,21 +6332,34 @@ TkMacOSXMakeFullscreen(
wmPtr->configAttributes, wmPtr->flags, 1, 0);
wmPtr->flags |= WM_SYNC_PENDING;
[window setFrame:[window frameRectForContentRect:
- screenBounds] display:YES];
+ screenBounds] display:YES];
+
wmPtr->flags &= ~WM_SYNC_PENDING;
}
wmPtr->flags |= WM_FULLSCREEN;
}
+#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
+ /*
+ * We can't set these features on Leopard or earlier, as they don't
+ * exist (neither options nor API that uses them). This formally means
+ * that there's a bug with full-screen windows with Tk on old OSX, but
+ * it isn't worth blocking a build just for this.
+ */
+
prevMask = [window styleMask];
prevPres = [NSApp presentationOptions];
[window setStyleMask: NSBorderlessWindowMask];
[NSApp setPresentationOptions: NSApplicationPresentationAutoHideDock
- | NSApplicationPresentationAutoHideMenuBar];
+ | NSApplicationPresentationAutoHideMenuBar];
+
+#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
} else {
wmPtr->flags &= ~WM_FULLSCREEN;
+#ifdef TK_GOT_AT_LEAST_SNOW_LEOPARD
[NSApp setPresentationOptions: prevPres];
[window setStyleMask: prevMask];
+#endif /*TK_GOT_AT_LEAST_SNOW_LEOPARD*/
}
if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) {
diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c
index 9594cd3..c227cd6 100644
--- a/macosx/tkMacOSXXStubs.c
+++ b/macosx/tkMacOSXXStubs.c
@@ -9,6 +9,7 @@
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001-2009, Apple Inc.
* Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright 2014 Marc Culler.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -809,7 +810,6 @@ XCreateImage(
int bytes_per_line)
{
XImage *ximage;
-
display->request++;
ximage = (XImage *) ckalloc(sizeof(XImage));
@@ -819,6 +819,7 @@ XCreateImage(
ximage->xoffset = offset;
ximage->format = format;
ximage->data = data;
+ ximage->obdata = NULL;
if (format == ZPixmap) {
ximage->bits_per_pixel = 32;
@@ -850,7 +851,6 @@ XCreateImage(
ximage->red_mask = 0x00FF0000;
ximage->green_mask = 0x0000FF00;
ximage->blue_mask = 0x000000FF;
- ximage->obdata = NULL;
ximage->f.create_image = NULL;
ximage->f.destroy_image = DestroyImage;
ximage->f.get_pixel = ImageGetPixel;
@@ -869,8 +869,9 @@ XCreateImage(
* This function copies data from a pixmap or window into an XImage.
*
* Results:
- * Returns a newly allocated image containing the data from the given
- * rectangle of the given drawable.
+ * Returns a newly allocated XImage containing the data from the given
+ * rectangle of the given drawable, or NULL if the XImage could not be
+ * constructed.
*
* Side effects:
* None.
@@ -889,60 +890,70 @@ XGetImage(
unsigned long plane_mask,
int format)
{
- MacDrawable *macDraw = (MacDrawable *) d;
- XImage * imagePtr = NULL;
- Pixmap pixmap = (Pixmap) NULL;
- Tk_Window win = (Tk_Window) macDraw->winPtr;
- GC gc;
- char * data = NULL;
- int depth = 32;
- int offset = 0;
- int bitmap_pad = 0;
- int bytes_per_line = 0;
-
+ NSBitmapImageRep *bitmap_rep;
+ XImage * imagePtr = NULL;
+ char * bitmap = NULL;
+ char * image_data=NULL;
+ int depth = 32;
+ int offset = 0;
+ int bitmap_pad = 0;
+ int bytes_per_row = 4*width;
+ int size;
+ TkMacOSXDbgMsg("XGetImage");
if (format == ZPixmap) {
- if (width > 0 && height > 0) {
- /*
- * Tk_GetPixmap fails for zero width or height.
- */
-
- pixmap = Tk_GetPixmap(display, d, width, height, depth);
+ if (width == 0 || height == 0) {
+ /* This happens all the time.
+ TkMacOSXDbgMsg("XGetImage: empty image requested");
+ */
+ return NULL;
}
- if (win) {
- XGCValues values;
- gc = Tk_GetGC(win, 0, &values);
- } else {
- gc = XCreateGC(display, pixmap, 0, NULL);
+ bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height);
+
+ if ( bitmap_rep == Nil ||
+ [bitmap_rep bitmapFormat] != 0 ||
+ [bitmap_rep samplesPerPixel] != 4 ||
+ [bitmap_rep isPlanar] != 0 ) {
+ TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep");
+ return NULL;
}
- if (pixmap) {
- CGContextRef context;
-
- XCopyArea(display, d, pixmap, gc, x, y, width, height, 0, 0);
- context = ((MacDrawable *) pixmap)->context;
- if (context) {
- data = CGBitmapContextGetData(context);
- bytes_per_line = CGBitmapContextGetBytesPerRow(context);
+
+ NSSize image_size = NSMakeSize(width, height);
+ NSImage* ns_image = [[NSImage alloc]initWithSize:image_size];
+ [ns_image addRepresentation:bitmap_rep];
+
+ /* Assume premultiplied nonplanar data with 4 bytes per pixel and alpha last.*/
+ if ( [bitmap_rep bitmapFormat] == 0 &&
+ [bitmap_rep isPlanar ] == 0 &&
+ [bitmap_rep samplesPerPixel] == 4 ) {
+ bytes_per_row = [bitmap_rep bytesPerRow];
+ size = bytes_per_row*height;
+ image_data = (char*)[bitmap_rep bitmapData];
+ if ( image_data ) {
+ int row, n, m;
+ bitmap = ckalloc(size);
+ /*
+ Oddly enough, the bitmap has the top row at the beginning,
+ and the pixels are in BGRA format.
+ */
+ for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
+ for (m=n; m<n+bytes_per_row; m+=4) {
+ *(bitmap+m) = *(image_data+m+2);
+ *(bitmap+m+1) = *(image_data+m+1);
+ *(bitmap+m+2) = *(image_data+m);
+ *(bitmap+m+3) = *(image_data+m+3);
+ }
+ }
}
}
- if (data) {
+ if (bitmap) {
imagePtr = XCreateImage(display, NULL, depth, format, offset,
- data, width, height, bitmap_pad, bytes_per_line);
-
- /*
- * Track Pixmap underlying the XImage in the unused obdata field
- * so that we can treat XImages coming from XGetImage specially.
- */
-
- imagePtr->obdata = (XPointer) pixmap;
- } else if (pixmap) {
- Tk_FreePixmap(display, pixmap);
- }
- if (!win) {
- XFreeGC(display, gc);
+ (char*)bitmap, width, height, bitmap_pad, bytes_per_row);
+ [ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/
+ [ns_image release];
}
} else {
- TkMacOSXDbgMsg("Invalid image format");
+ TkMacOSXDbgMsg("Could not extract image from drawable.");
}
return imagePtr;
}
@@ -968,9 +979,7 @@ DestroyImage(
XImage *image)
{
if (image) {
- if (image->obdata) {
- Tk_FreePixmap((Display*) gMacDisplay, (Pixmap) image->obdata);
- } else if (image->data) {
+ if (image->data) {
ckfree(image->data);
}
ckfree((char*) image);
diff --git a/macosx/ttkMacOSXTheme.c b/macosx/ttkMacOSXTheme.c
index 5752fb1..64b96cb 100644
--- a/macosx/ttkMacOSXTheme.c
+++ b/macosx/ttkMacOSXTheme.c
@@ -294,14 +294,21 @@ static Ttk_StateTable TabPositionTable[] = {
* TP30000359-TPXREF116>
*/
-static const int TAB_HEIGHT = 10;
-static const int TAB_OVERLAP = 10;
+int TAB_HEIGHT = 0;
+int TAB_OVERLAP = 0;
static void TabElementSize(
void *clientData, void *elementRecord, Tk_Window tkwin,
int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
{
- *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1;
+ TAB_HEIGHT = 10;
+ TAB_OVERLAP = 10;
+ /*Different metrics on 10.10/Yosemite.*/
+ if (MAC_OS_X_VERSION_MIN_REQUIRED > 100000) {
+ TAB_OVERLAP = 5;
+ }
+ *heightPtr = TAB_HEIGHT + TAB_OVERLAP - 1;
+
}
static void TabElementDraw(