diff options
-rw-r--r-- | doc/text.n | 2 | ||||
-rw-r--r-- | generic/tkFont.c | 4 | ||||
-rw-r--r-- | generic/tkMenu.c | 7 | ||||
-rw-r--r-- | library/entry.tcl | 10 | ||||
-rw-r--r-- | macosx/tkMacOSXDraw.c | 86 | ||||
-rw-r--r-- | macosx/tkMacOSXMouseEvent.c | 50 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 1 | ||||
-rw-r--r-- | tests/entry.test | 8 | ||||
-rw-r--r-- | tests/event.test | 4 | ||||
-rw-r--r-- | tests/font.test | 2 | ||||
-rw-r--r-- | tests/menu.test | 9 |
11 files changed, 129 insertions, 54 deletions
@@ -2222,7 +2222,7 @@ after copying it to the clipboard. Control-t reverses the order of the two characters to the right of the insertion cursor. .IP [32] -Control-z undoes the last edit action if the \fB\-undo\fR option is +Control-z (undoes the last edit action if the \fB\-undo\fR option is true. Does nothing otherwise. .IP [33] Control-Z (or Control-y on Windows) reapplies the last undone edit 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/library/entry.tcl b/library/entry.tcl index 382cc88..c3e573d 100644 --- a/library/entry.tcl +++ b/library/entry.tcl @@ -373,12 +373,18 @@ proc ::tk::EntryMouseSelect {w x} { } } word { - if {$cur < [$w index anchor]} { + if {$cur < $anchor} { set before [tcl_wordBreakBefore [$w get] $cur] set after [tcl_wordBreakAfter [$w get] [expr {$anchor-1}]] - } else { + } elseif {$cur > $anchor} { set before [tcl_wordBreakBefore [$w get] $anchor] set after [tcl_wordBreakAfter [$w get] [expr {$cur - 1}]] + } else { + if {[$w index @$Priv(pressX)] < $anchor} { + incr anchor -1 + } + set before [tcl_wordBreakBefore [$w get] $anchor] + set after [tcl_wordBreakAfter [$w get] $anchor] } if {$before < 0} { set before 0 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/event.test b/tests/event.test index fa75610..95be5f4 100644 --- a/tests/event.test +++ b/tests/event.test @@ -705,7 +705,7 @@ test event-7.1(double-click) {A double click on a lone character set result } {1.3 A 1.3 A} test event-7.2(double-click) {A double click on a lone character\ - in an entry widget should select that character} {knownBug} { + in an entry widget should select that character} { destroy .t set t [toplevel .t] set e [entry $t.e] @@ -766,7 +766,7 @@ test event-7.2(double-click) {A double click on a lone character\ lappend result [_get_selection $e] set result -} {3 A 4 A} +} {4 A 4 A} # cleanup 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 |