summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkFont.c4
-rw-r--r--generic/tkMenu.c7
-rw-r--r--macosx/tkMacOSXDraw.c86
-rw-r--r--macosx/tkMacOSXMouseEvent.c50
-rw-r--r--macosx/tkMacOSXPrivate.h1
-rw-r--r--tests/entry.test8
-rw-r--r--tests/font.test2
-rw-r--r--tests/menu.test9
8 files changed, 118 insertions, 49 deletions
diff --git a/generic/tkFont.c b/generic/tkFont.c
index 5d2ad43..7ff1ae9 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -2069,14 +2069,14 @@ Tk_ComputeTextLayout(
NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX,
baseline)->numDisplayChars = -1;
start++;
+ curX = newX;
+ flags &= ~TK_AT_LEAST_ONE;
if ((start < end) &&
((wrapLength <= 0) || (newX <= wrapLength))) {
/*
* More chars can still fit on this line.
*/
- curX = newX;
- flags &= ~TK_AT_LEAST_ONE;
continue;
}
} else {
diff --git a/generic/tkMenu.c b/generic/tkMenu.c
index 49b5935..b35be24 100644
--- a/generic/tkMenu.c
+++ b/generic/tkMenu.c
@@ -934,9 +934,14 @@ MenuWidgetObjCmd(
* Tearoff menus are posted differently on Mac and Windows than
* non-tearoffs. TkpPostMenu does not actually map the menu's window
* on those platforms, and popup menus have to be handled specially.
+ * Also, menubar menues are not intended to be posted (bug 1567681,
+ * 2160206).
*/
- if (menuPtr->menuType != TEAROFF_MENU) {
+ if (menuPtr->menuType == MENUBAR) {
+ Tcl_AppendResult(interp, "a menubar menu cannot be posted", NULL);
+ return TCL_ERROR;
+ } else if (menuPtr->menuType != TEAROFF_MENU) {
result = TkpPostMenu(interp, menuPtr, x, y);
} else {
result = TkPostTearoffMenu(interp, menuPtr, x, y);
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c
index 3f51d00..7ec7b90 100644
--- a/macosx/tkMacOSXDraw.c
+++ b/macosx/tkMacOSXDraw.c
@@ -141,7 +141,7 @@ BitmapRepFromDrawableRect(
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.
+ field is NULL.
*/
cg_context = GetCGContextForDrawable(drawable);
CGRect image_rect = CGRectMake(x, y, width, height);
@@ -199,10 +199,10 @@ XCopyArea(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
+ unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y)
@@ -282,10 +282,10 @@ XCopyPlane(
Display *display, /* Display. */
Drawable src, /* Source drawable. */
Drawable dst, /* Destination drawable. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
int src_x, /* X & Y, width & height */
int src_y, /* define the source rectangle */
- unsigned int width, /* that will be copied. */
+ unsigned int width, /* that will be copied. */
unsigned int height,
int dest_x, /* Dest X & Y on dest rect. */
int dest_y,
@@ -293,6 +293,7 @@ XCopyPlane(
{
TkMacOSXDrawingContext dc;
MacDrawable *srcDraw = (MacDrawable *) src;
+ MacDrawable *dstDraw = (MacDrawable *) dst;
display->request++;
if (!width || !height) {
@@ -306,33 +307,47 @@ XCopyPlane(
if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
return;
}
- if (dc.context) {
+ CGContextRef context = dc.context;
+ if (context) {
CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);
-
if (img) {
TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
unsigned long imageBackground = gc->background;
-
- if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP &&
- clipPtr->value.pixmap == src) {
- imageBackground = TRANSPARENT_PIXEL << 24;
+ if (clipPtr && clipPtr->type == TKP_CLIP_PIXMAP){
+ CGImageRef mask = TkMacOSXCreateCGImageWithDrawable(clipPtr->value.pixmap);
+ CGRect rect = CGRectMake(dest_x, dest_y, width, height);
+ rect = CGRectOffset(rect, dstDraw->xOff, dstDraw->yOff);
+ CGContextSaveGState(context);
+ /* Move the origin of the destination to top left. */
+ CGContextTranslateCTM(context, 0, rect.origin.y + CGRectGetMaxY(rect));
+ CGContextScaleCTM(context, 1, -1);
+ /* Fill with the background color, clipping to the mask. */
+ CGContextClipToMask(context, rect, mask);
+ TkMacOSXSetColorInContext(gc, gc->background, dc.context);
+ CGContextFillRect(dc.context, rect);
+ /* Fill with the foreground color, clipping to the intersection of img and mask. */
+ CGContextClipToMask(context, rect, img);
+ TkMacOSXSetColorInContext(gc, gc->foreground, context);
+ CGContextFillRect(context, rect);
+ CGContextRestoreGState(context);
+ CGImageRelease(mask);
+ CGImageRelease(img);
+ } else {
+ DrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground,
+ CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height),
+ CGRectMake(src_x, src_y, width, height),
+ CGRectMake(dest_x, dest_y, width, height));
+ CGImageRelease(img);
}
- DrawCGImage(dst, gc, dc.context, img, gc->foreground,
- imageBackground, 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 {
+ } else { /* no image */
TkMacOSXDbgMsg("Invalid source drawable");
}
} else {
- TkMacOSXDbgMsg("Invalid destination drawable");
+ TkMacOSXDbgMsg("Invalid destination drawable - could not get a bitmap context.");
}
TkMacOSXRestoreDrawingContext(&dc);
- } else {
- XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x,
- dest_y);
+ } else { /* source drawable is a window, not a Pixmap */
+ XCopyArea(display, src, dst, gc, src_x, src_y, width, height, dest_x, dest_y);
}
}
@@ -356,16 +371,16 @@ XCopyPlane(
int
TkPutImage(
unsigned long *colors, /* Unused on Macintosh. */
- int ncolors, /* Unused on Macintosh. */
+ int ncolors, /* Unused on Macintosh. */
Display* display, /* Display. */
Drawable d, /* Drawable to place image on. */
- GC gc, /* GC to use. */
+ GC gc, /* GC to use. */
XImage* image, /* Image to place. */
int src_x, /* Source X & Y. */
int src_y,
int dest_x, /* Destination X & Y. */
int dest_y,
- unsigned int width, /* Same width & height for both */
+ unsigned int width, /* Same width & height for both */
unsigned int height) /* distination and source. */
{
TkMacOSXDrawingContext dc;
@@ -431,11 +446,12 @@ CreateCGImageWithXImage(
* BW image
*/
+ /* Reverses the sense of the bits */
static const CGFloat decodeWB[2] = {1, 0};
+ decode = decodeWB;
bitsPerComponent = 1;
bitsPerPixel = 1;
- decode = decodeWB;
if (image->bitmap_bit_order != MSBFirst) {
char *srcPtr = image->data + image->xoffset;
char *endPtr = srcPtr + len;
@@ -445,22 +461,20 @@ CreateCGImageWithXImage(
*destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))];
}
} else {
- data = memcpy(ckalloc(len), image->data + image->xoffset,
- len);
+ data = memcpy(ckalloc(len), image->data + image->xoffset, len);
}
if (data) {
provider = CGDataProviderCreateWithData(data, data, len, releaseData);
}
if (provider) {
img = CGImageMaskCreate(image->width, image->height, bitsPerComponent,
- bitsPerPixel, image->bytes_per_line,
- provider, decode, 0);
+ bitsPerPixel, image->bytes_per_line, provider, decode, 0);
}
} else if (image->format == ZPixmap && image->bits_per_pixel == 32) {
/*
* Color image
*/
-
+
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
bitsPerComponent = 8;
@@ -476,6 +490,7 @@ CreateCGImageWithXImage(
img = CGImageCreate(image->width, image->height, bitsPerComponent,
bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo,
provider, decode, 0, kCGRenderingIntentDefault);
+ CFRelease(provider);
}
if (colorspace) {
CFRelease(colorspace);
@@ -483,10 +498,6 @@ CreateCGImageWithXImage(
} else {
TkMacOSXDbgMsg("Unsupported image type");
}
- if (provider) {
- CFRelease(provider);
- }
-
return img;
}
@@ -660,8 +671,7 @@ GetCGContextForDrawable(
kCGBitmapByteOrderDefault;
#endif
char *data;
- CGRect bounds = CGRectMake(0, 0, macDraw->size.width,
- macDraw->size.height);
+ CGRect bounds = CGRectMake(0, 0, macDraw->size.width, macDraw->size.height);
if (macDraw->flags & TK_IS_BW_PIXMAP) {
bitsPerPixel = 8;
@@ -738,6 +748,7 @@ DrawCGImage(
if (CGImageIsMask(image)) {
/*CGContextSaveGState(context);*/
if (macDraw->flags & TK_IS_BW_PIXMAP) {
+ /* Set fill color to black, background comes from the context, or is transparent. */
if (imageBackground != TRANSPARENT_PIXEL << 24) {
CGContextClearRect(context, dstBounds);
}
@@ -750,6 +761,7 @@ DrawCGImage(
TkMacOSXSetColorInContext(gc, imageForeground, context);
}
}
+
#ifdef TK_MAC_DEBUG_IMAGE_DRAWING
CGContextSaveGState(context);
CGContextSetLineWidth(context, 1.0);
diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c
index 10a615e..6481fbd 100644
--- a/macosx/tkMacOSXMouseEvent.c
+++ b/macosx/tkMacOSXMouseEvent.c
@@ -34,6 +34,18 @@ enum {
NSWindowWillMoveEventType = 20
};
+/*
+ * In OS X 10.6 an NSEvent of type NSMouseMoved would always have a non-Nil
+ * window attribute when the mouse was inside a window. As of 10.8 this
+ * behavior had changed. The new behavior was that if the mouse were ever
+ * moved outside of a window, all subsequent NSMouseMoved NSEvents would have a
+ * Nil window attribute. To work around this we remember which window the
+ * mouse is in by saving the window attribute of each NSEvent of type
+ * NSMouseEntered. If an NSEvent has a Nil window attribute we use our saved
+ * window. It may be the case that the mouse has actually left the window, but
+ * this is harmless since Tk will ignore the event in that case.
+ */
+
@implementation TKApplication(TKMouseEvent)
- (NSEvent *)tkProcessMouseEvent:(NSEvent *)theEvent {
#ifdef TK_MAC_DEBUG_EVENTS
@@ -48,12 +60,11 @@ enum {
switch (type) {
case NSMouseEntered:
+ /* Remember which window has the mouse. */
+ _windowWithMouse = [theEvent window];
+ break;
case NSMouseExited:
case NSCursorUpdate:
-#if 0
- trackingArea = [theEvent trackingArea];
- /* fall through */
-#endif
case NSLeftMouseDown:
case NSLeftMouseUp:
case NSRightMouseDown:
@@ -83,13 +94,36 @@ enum {
/* Create an Xevent to add to the Tk queue. */
win = [theEvent window];
NSPoint global, local = [theEvent locationInWindow];
- if (win) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ /* convertBaseToScreen and convertScreenToBase were deprecated in 10.7. */
+ NSRect pointrect;
+ pointrect.origin = local;
+ pointrect.size.width = 0;
+ pointrect.size.height = 0;
+#endif
+ if (win) { /* local will be in window coordinates. */
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ global = [win convertRectToScreen:pointrect].origin;
+#else
global = [win convertBaseToScreen:local];
+#endif
local.y = [win frame].size.height - local.y;
global.y = tkMacOSXZeroScreenHeight - global.y;
- } else {
- local.y = tkMacOSXZeroScreenHeight - local.y;
- global = local;
+ } else { /* local will be in screen coordinates. */
+ if (_windowWithMouse ) {
+ win = _windowWithMouse;
+ global = local;
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
+ local = [win convertRectFromScreen:pointrect].origin;
+#else
+ local = [win convertScreenToBase:local];
+#endif
+ local.y = [win frame].size.height - local.y;
+ global.y = tkMacOSXZeroScreenHeight - global.y;
+ } else { /* We have no window. Use the screen???*/
+ local.y = tkMacOSXZeroScreenHeight - local.y;
+ global = local;
+ }
}
Window window = TkMacOSXGetXWindow(win);
diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h
index b93fa18..ff3577d 100644
--- a/macosx/tkMacOSXPrivate.h
+++ b/macosx/tkMacOSXPrivate.h
@@ -272,6 +272,7 @@ VISIBILITY_HIDDEN
TKMenu *_defaultMainMenu, *_defaultApplicationMenu;
NSArray *_defaultApplicationMenuItems, *_defaultWindowsMenuItems;
NSArray *_defaultHelpMenuItems;
+ NSWindow *_windowWithMouse;
}
@end
@interface TKApplication(TKInit)
diff --git a/tests/entry.test b/tests/entry.test
index ffdbf45..27acfc1 100644
--- a/tests/entry.test
+++ b/tests/entry.test
@@ -778,6 +778,14 @@ test entry-6.11 {EntryComputeGeometry procedure} win {
[expr 8+5*[font measure {helvetica 12} .]] \
[expr 8+5*[font measure {helvetica 12} X]] \
[expr 8+[font measure {helvetica 12} 12345]]]
+test entry-6.12 {EntryComputeGeometry procedure} {fonts} {
+ catch {destroy .e}
+ entry .e -font $fixed -bd 2 -relief raised -width 20
+ pack .e
+ .e insert end "012\t456\t"
+ update
+ list [.e index @81] [.e index @82] [.e index @116] [.e index @117]
+} {6 7 7 8}
catch {destroy .e}
entry .e -width 10 -font $fixed -textvariable contents -xscrollcommand scroll
diff --git a/tests/font.test b/tests/font.test
index a02cc2e..9ed24dc 100644
--- a/tests/font.test
+++ b/tests/font.test
@@ -829,7 +829,7 @@ test font-24.10 {Tk_ComputeTextLayout: tab caused break} {
lappend x [getsize]
.b.l config -wrap 0
set x
-} "{[expr $ax*3] $ay} {[expr $ax*3] [expr $ay*2]}"
+} "{[expr $ax*8] $ay} {[expr $ax*8] [expr $ay*2]}"
test font-24.11 {Tk_ComputeTextLayout: absorb spaces at eol} {
set x {}
.b.l config -text "000 000" -wrap [expr $ax*5]
diff --git a/tests/menu.test b/tests/menu.test
index cfe00b9..c797281 100644
--- a/tests/menu.test
+++ b/tests/menu.test
@@ -2566,6 +2566,15 @@ test menu-36.1 {menu -underline string overruns Bug 1599877} {} {
tk::TraverseToMenu . "e"
} {}
+test menu-37.1 {menubar menues cannot be posted - bug 2160206} {} {
+ # On Linux the following used to panic
+ # It now returns an error (on all platforms)
+ catch {destroy .m}
+ menu .m -type menubar
+ list [catch ".m post 1 1" msg] $msg
+} {1 {a menubar menu cannot be posted}}
+
+
# cleanup
deleteWindows
cleanupTests