From 72df3089578116c1b9fdfb15a1c9b1e20a66dc2a Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 18 Oct 2015 21:24:57 +0000 Subject: Proposed fix for [2160206fff] - Panic (Linux) when posting a menu of type menubar --- generic/tkMenu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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); -- cgit v0.12 From 4b830288d02e49fa96ed7b5d20bf8170297abcba Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 25 Oct 2015 19:22:38 +0000 Subject: Make compile with later Visual Studio versions (backported from Tk 8.6) --- win/ttkWinXPTheme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c index 80b616d..6359891 100644 --- a/win/ttkWinXPTheme.c +++ b/win/ttkWinXPTheme.c @@ -25,7 +25,7 @@ int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd) { return TCL_OK; } #include #include -#ifdef HAVE_VSSYM32_H +#if defined(HAVE_VSSYM32_H) || _MSC_VER > 1500 # include #else # include -- cgit v0.12 From 2fb7c126ab1a68f237aee91ecd26b5f2eb6e074d Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 25 Oct 2015 19:58:08 +0000 Subject: Added new test to check for error triggering when posting a menu of type menubar --- tests/menu.test | 9 +++++++++ 1 file changed, 9 insertions(+) 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 -- cgit v0.12 From 6517ea57da28dce9742a12980122acc1c59a5671 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 25 Oct 2015 22:00:54 +0000 Subject: Fix [477949]: option readfile cannot use multibytes. Implementation adopted from AndroWish, but added support for UTF-8 BOM and added test-case. --- generic/tkOption.c | 13 +++++++++++-- tests/option.file3 | 18 ++++++++++++++++++ tests/option.test | 11 +++++++---- 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100755 tests/option.file3 diff --git a/generic/tkOption.c b/generic/tkOption.c index 91a6cc0..bff799b 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -1086,7 +1086,7 @@ ReadOptionFile( char *buffer; int result, bufferSize; Tcl_Channel chan; - Tcl_DString newName; + Tcl_DString newName, optString; /* * Prevent file system access in a safe interpreter. @@ -1136,7 +1136,16 @@ ReadOptionFile( } Tcl_Close(NULL, chan); buffer[bufferSize] = 0; - result = AddFromString(interp, tkwin, buffer, priority); + if ((bufferSize>2) && !memcmp(buffer, "\357\273\277", 3)) { + /* File starts with UTF-8 BOM */ + result = AddFromString(interp, tkwin, buffer+3, priority); + } else { + Tcl_DStringInit(&optString); + Tcl_ExternalToUtfDString(NULL, buffer, bufferSize, &optString); + result = AddFromString(interp, tkwin, Tcl_DStringValue(&optString), + priority); + Tcl_DStringFree(&optString); + } ckfree(buffer); return result; } diff --git a/tests/option.file3 b/tests/option.file3 new file mode 100755 index 0000000..87f41ae --- /dev/null +++ b/tests/option.file3 @@ -0,0 +1,18 @@ +! This file is a sample option (resource) database used to test +! Tk's option-handling capabilities. + +! Comment line \ + with a backslash-newline sequence embedded in it. + +*x1: blue + tktest.x2 : green +*\ +x3 \ + : pur\ +ple +*x 4: brówn +# More comments, this time delimited by hash-marks. + # Comment-line with space. +*x6: +*x9: \ \ \\\101\n +# comment line as last line of file. diff --git a/tests/option.test b/tests/option.test index 1bfcb7c..4668771 100644 --- a/tests/option.test +++ b/tests/option.test @@ -187,6 +187,7 @@ test option-14.12 {error conditions} { set option1 [file join [testsDirectory] option.file1] set option2 [file join [testsDirectory] option.file2] +set option3 [file join [testsDirectory] option.file3] test option-15.1 {database files} { list [catch {option read non-existent} msg] $msg @@ -207,16 +208,18 @@ test option-15.9 {database files} {option get . x3 color} burgundy test option-15.10 {database files} { list [catch {option read $option2} msg] $msg } {1 {missing colon on line 2}} +option read $option3 +test option-15.11 {database files} {option get . {x 4} color} br\xf3wn test option-16.1 {ReadOptionFile} { - set option3 [makeFile {} option.file3] - set file [open $option3 w] + set option4 [makeFile {} option.file3] + set file [open $option4 w] fconfigure $file -translation crlf puts $file "*x7: true\n*x8: false" close $file - option read $option3 userDefault + option read $option4 userDefault set result [list [option get . x7 color] [option get . x8 color]] - removeFile $option3 + removeFile $option4 set result } {true false} -- cgit v0.12 From ac5d8bfc752d831b0fabdbacb052749a8824edc9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 25 Oct 2015 22:54:53 +0000 Subject: Re-generate "configure" --- unix/configure | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unix/configure b/unix/configure index 10e2b48..afd5bff 100755 --- a/unix/configure +++ b/unix/configure @@ -10008,7 +10008,7 @@ ac_x_header_dirs=' /usr/openwin/share/include' if test "$ac_x_includes" = no; then - # Guess where to find include files, by looking for Intrinsic.h. + # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -10016,7 +10016,7 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -10043,7 +10043,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Intrinsic.h"; then + if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi @@ -10057,18 +10057,18 @@ if test "$ac_x_libraries" = no; then # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lXt $LIBS" + LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include int main () { -XtMalloc (0) +XrmInitialize () ; return 0; } -- cgit v0.12 From a4d07a64e85a1e1f59c15c6faf27e569b267473e Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Mon, 26 Oct 2015 11:31:06 +0000 Subject: Fix for PNG rendering on OS X 10.11; thanks to Stephan Meier for patch --- macosx/tkMacOSXXStubs.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 0be5416..59c6a56 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -890,6 +890,7 @@ XGetImage( int format) { NSBitmapImageRep *bitmap_rep; + NSUInteger bitmap_fmt; XImage * imagePtr = NULL; char * bitmap = NULL; char * image_data=NULL; @@ -908,9 +909,10 @@ XGetImage( } bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height); + bitmap_fmt = [bitmap_rep bitmapFormat]; if ( bitmap_rep == Nil || - [bitmap_rep bitmapFormat] != 0 || + (bitmap_fmt != 0 && bitmap_fmt != 1) || [bitmap_rep samplesPerPixel] != 4 || [bitmap_rep isPlanar] != 0 ) { TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); @@ -921,9 +923,8 @@ XGetImage( 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 && +/* Assume premultiplied nonplanar data with 4 bytes per pixel.*/ + if ( [bitmap_rep isPlanar ] == 0 && [bitmap_rep samplesPerPixel] == 4 ) { bytes_per_row = [bitmap_rep bytesPerRow]; size = bytes_per_row*height; @@ -933,18 +934,30 @@ XGetImage( bitmap = ckalloc(size); /* Oddly enough, the bitmap has the top row at the beginning, - and the pixels are in BGRA format. + and the pixels are in BGRA or ABGR format. */ - for (row=0, n=0; row Date: Tue, 27 Oct 2015 20:14:29 +0000 Subject: Added missing word in man event --- doc/event.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/event.n b/doc/event.n index 0a5ced5..85033e9 100644 --- a/doc/event.n +++ b/doc/event.n @@ -424,7 +424,7 @@ the physical event. .PP Bindings on a virtual event may be created before the virtual event exists. Indeed, the virtual event never actually needs to be defined, for instance, -on platforms where the specific virtual event would meaningless or +on platforms where the specific virtual event would be meaningless or ungeneratable. .PP When a definition of a virtual event changes at run time, all windows -- cgit v0.12 From ead20630da62cb8674fea88a385281fd05a0bcd4 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 29 Oct 2015 20:19:21 +0000 Subject: Fixed bug [220854fff] - Trailing tab characters in entry widgets are not displayed --- generic/tkFont.c | 4 ++-- tests/entry.test | 8 ++++++++ tests/font.test | 2 +- 3 files changed, 11 insertions(+), 3 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/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] -- cgit v0.12 From 55fc97d827d04fb3bc87f34f5aba3ded5a7471eb Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 31 Oct 2015 20:30:27 +0000 Subject: Fixed bug [e51941c1b9] - text-9.2.47 fails sometimes --- tests/text.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/text.test b/tests/text.test index 0909d2f..7c1731d 100644 --- a/tests/text.test +++ b/tests/text.test @@ -745,6 +745,10 @@ test text-9.2.47 {TextWidgetCmd procedure, "count" option} -setup { .t tag configure hidden -elide true .t tag add hidden 5.7 11.0 update + # next line to be fully sure that asynchronous line heights calculation is + # up-to-date otherwise this test may fail (depending on the computer + # performance), especially when the . toplevel has small height + .t count -update -ypixels 1.0 end set y1 [lindex [.t yview] 1] .t count -displaylines 5.0 11.0 set y2 [lindex [.t yview] 1] -- cgit v0.12 From f265ae7f9741d5710decdabc637b2fa3ac105a0d Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 3 Nov 2015 10:45:05 +0000 Subject: Fixed entry part of bug [542199fff] - Double click on a lone character in an entry does not work --- library/entry.tcl | 10 ++++++++-- tests/event.test | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) 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/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 -- cgit v0.12 From 79468c974649ac8235e35f8b07d862476c72695e Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 5 Nov 2015 07:06:01 +0000 Subject: Fixed bug [297442da29] - tk_strictMotif not correctly taken into account --- doc/text.n | 5 ++--- library/tk.tcl | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/text.n b/doc/text.n index 3633703..2e9bffc 100644 --- a/doc/text.n +++ b/doc/text.n @@ -2222,9 +2222,8 @@ 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 (and Control-underscore on UNIX when \fBtk_strictMotif\fR is -true) undoes the last edit action if the \fB\-undo\fR option is true. -Does nothing otherwise. +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 action if the \fB\-undo\fR option is true. Does nothing otherwise. diff --git a/library/tk.tcl b/library/tk.tcl index a9db8cb..d045222 100644 --- a/library/tk.tcl +++ b/library/tk.tcl @@ -308,7 +308,6 @@ proc ::tk::EventMotifBindings {n1 dummy dummy} { event $op <> event $op <> event $op <> - event $op <> } #---------------------------------------------------------------------- -- cgit v0.12 From e8a7079f69245ef6d172654bac53c15d27c81c56 Mon Sep 17 00:00:00 2001 From: fvogel Date: Fri, 6 Nov 2015 17:49:38 +0000 Subject: Fixed bug [3601604fff] - [listbox $path -takefocus 0] steals focus --- doc/listbox.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/listbox.n b/doc/listbox.n index b2e8e38..642e1f0 100644 --- a/doc/listbox.n +++ b/doc/listbox.n @@ -414,7 +414,7 @@ In \fBbrowse\fR mode it is also possible to drag the selection with button 1. .VS 8.5 On button 1, the listbox will also take focus if it has a \fBnormal\fR -state and \fB\-takefocus\fR is true. +state. .VE 8.5 .PP If the selection mode is \fBmultiple\fR or \fBextended\fR, -- cgit v0.12 From 509e52d9d0542fdf3883f95edf264045eba9ba5a Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Sat, 7 Nov 2015 18:52:25 +0000 Subject: Fix for issues with bitmap rendering and mouse events in Tk-Cocoa; thanks to Marc Culler for patches --- macosx/tkMacOSXDraw.c | 86 ++++++++++++++++++++++++++------------------- macosx/tkMacOSXMouseEvent.c | 50 +++++++++++++++++++++----- macosx/tkMacOSXPrivate.h | 1 + 3 files changed, 92 insertions(+), 45 deletions(-) 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) -- cgit v0.12 From 65696b5bb7348609c6187600bf18b0d38ffdd219 Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Sun, 8 Nov 2015 22:02:34 +0000 Subject: Cleanup of last patch to Tk-Cocoa --- macosx/tkMacOSXDraw.c | 2 +- macosx/tkMacOSXKeyEvent.c | 36 +++++++++++----------- macosx/tkMacOSXMouseEvent.c | 73 ++++++++++++++++++++++++++++++++------------ macosx/tkMacOSXPrivate.h | 20 ++++++++++-- macosx/tkMacOSXSubwindows.c | 3 -- macosx/tkMacOSXWindowEvent.c | 15 --------- macosx/tkMacOSXWm.c | 34 ++++++++++----------- macosx/tkMacOSXXStubs.c | 21 +++++++------ 8 files changed, 119 insertions(+), 85 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 7ec7b90..33c2ef9 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1491,7 +1491,7 @@ TkScrollWindow( { Drawable drawable = Tk_WindowId(tkwin); MacDrawable *macDraw = (MacDrawable *) drawable; - NSView *view = TkMacOSXDrawableView(macDraw); + TKContentView *view = (TKContentView *)TkMacOSXDrawableView(macDraw); CGRect srcRect, dstRect; HIShapeRef dmgRgn = NULL, extraRgn = NULL; NSRect bounds, visRect, scrollSrc, scrollDst; diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 8e278f7..d21389b 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -227,7 +227,7 @@ static unsigned isFunctionKey(unsigned int code); -@implementation TKContentView(TKKeyEvent) +@implementation TKContentView /* implementation (called through interpretKeyEvents:]). */ /* : called when done composing; @@ -293,22 +293,6 @@ static unsigned isFunctionKey(unsigned int code); } -/* delete display of composing characters [not in ] */ -- (void)deleteWorkingText -{ - if (privateWorkingText == nil) - return; - if (NS_KEYLOG) - NSLog(@"deleteWorkingText len = %lu\n", - (unsigned long)[privateWorkingText length]); - [privateWorkingText release]; - privateWorkingText = nil; - processingCompose = NO; - - //PENDING: delete working text -} - - - (BOOL)hasMarkedText { return privateWorkingText != nil; @@ -418,6 +402,24 @@ static unsigned isFunctionKey(unsigned int code); @end +@implementation TKContentView(TKKeyEvent) +/* delete display of composing characters [not in ] */ +- (void)deleteWorkingText +{ + if (privateWorkingText == nil) + return; + if (NS_KEYLOG) + NSLog(@"deleteWorkingText len = %lu\n", + (unsigned long)[privateWorkingText length]); + [privateWorkingText release]; + privateWorkingText = nil; + processingCompose = NO; + + //PENDING: delete working text +} +@end + + /* * Set up basic fields in xevent for keyboard input. diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index 6481fbd..2b9d0bf 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -28,12 +28,53 @@ static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, UInt32 keyModifiers); +#pragma mark NSWindow(TKMouseEvent) + +/* Conversion of coordinates between window and screen */ +@interface NSWindow(TKWm) +- (NSPoint) convertPointToScreen:(NSPoint)point; +- (NSPoint) convertPointFromScreen:(NSPoint)point; +@end + +@implementation NSWindow(TKMouseEvent) +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 +- (NSPoint) convertPointToScreen: (NSPoint) point +{ + return [self convertBaseToScreen:point]; +} +- (NSPoint) convertPointFromScreen: (NSPoint)point +{ + return [self convertScreenToBase:point]; +} +@end +#else +- (NSPoint) convertPointToScreen: (NSPoint)point +{ + NSRect pointrect; + pointrect.origin = point; + pointrect.size.width = 0; + pointrect.size.height = 0; + return [self convertRectToScreen:pointrect].origin; +} +- (NSPoint) convertPointFromScreen: (NSPoint)point +{ + NSRect pointrect; + pointrect.origin = point; + pointrect.size.width = 0; + pointrect.size.height = 0; + return [self convertRectFromScreen:pointrect].origin; +} +@end +#endif + +#pragma mark - + + #pragma mark TKApplication(TKMouseEvent) 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 @@ -51,8 +92,8 @@ enum { #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); #endif - id win; - NSEventType type = [theEvent type]; + id win; + NSEventType type = [theEvent type]; #if 0 NSTrackingArea *trackingArea = nil; NSInteger eventNumber, clickCount, buttonNumber; @@ -61,7 +102,13 @@ enum { switch (type) { case NSMouseEntered: /* Remember which window has the mouse. */ + if (_windowWithMouse) { + [_windowWithMouse release]; + } _windowWithMouse = [theEvent window]; + if (_windowWithMouse) { + [_windowWithMouse retain]; + } break; case NSMouseExited: case NSCursorUpdate: @@ -93,31 +140,17 @@ enum { /* Create an Xevent to add to the Tk queue. */ win = [theEvent window]; + NSWindow *nswindow = (NSWindow *)win; NSPoint global, local = [theEvent locationInWindow]; -#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 + global = [nswindow convertPointToScreen: local]; local.y = [win frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } 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 = [nswindow convertPointFromScreen: local]; local.y = [win frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } else { /* We have no window. Use the screen???*/ diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index ff3577d..4f96f64 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -299,10 +299,10 @@ VISIBILITY_HIDDEN @interface TKContentView : NSView { @private /*Remove private API calls.*/ - #if 0 +#if 0 id _savedSubviews; BOOL _subviewsSetAside; - #endif +#endif NSString *privateWorkingText; } @end @@ -311,6 +311,18 @@ VISIBILITY_HIDDEN - (void) deleteWorkingText; @end +@interface TKContentView(TKWindowEvent) +- (void) drawRect: (NSRect) rect; +- (void) generateExposeEvents: (HIShapeRef) shape; +- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly; +- (void) viewDidEndLiveResize; +- (void) tkToolbarButton: (id) sender; +- (BOOL) isOpaque; +- (BOOL) wantsDefaultClipping; +- (BOOL) acceptsFirstResponder; +- (void) keyDown: (NSEvent *) theEvent; +@end + VISIBILITY_HIDDEN @interface TKWindow : NSWindow @end @@ -344,4 +356,8 @@ VISIBILITY_HIDDEN @end +/* Helper functions from tkMacOSXDeprecations.c */ + +extern NSPoint convertWindowToScreen( NSWindow *window, NSPoint point); + #endif /* _TKMACPRIV */ diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 2f500fa..a601c50 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -805,9 +805,6 @@ TkMacOSXUpdateClipRgn( /* * TODO: Here we should handle out of process embedding. */ - } else if (winPtr->wmInfoPtr->attributes & - kWindowResizableAttribute) { - NSWindow *w = TkMacOSXDrawableWindow(winPtr->window); } macWin->aboveVisRgn = HIShapeCreateCopy(rgn); diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index ef3c86b..c028a75 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -782,21 +782,6 @@ Tk_MacOSXIsAppInFront(void) * */ -@interface TKContentView(TKWindowEvent) -- (void) drawRect: (NSRect) rect; -- (void) generateExposeEvents: (HIShapeRef) shape; -- (void) generateExposeEvents: (HIShapeRef) shape childrenOnly: (int) childrenOnly; -- (void) viewDidEndLiveResize; -- (void) tkToolbarButton: (id) sender; -- (BOOL) isOpaque; -- (BOOL) wantsDefaultClipping; -- (BOOL) acceptsFirstResponder; -- (void) keyDown: (NSEvent *) theEvent; -@end - -@implementation TKContentView -@end - /*Restrict event processing to Expose events.*/ static Tk_RestrictAction ExposeRestrictProc( diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 37a1d25..241d70a 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -817,7 +817,7 @@ TkWmDeadWindow( } [pool drain]; } - ckfree(wmPtr); + ckfree((char *)wmPtr); winPtr->wmInfoPtr = NULL; } @@ -5194,22 +5194,22 @@ WmWinStyle( { "moveToActiveSpace", tkMoveToActiveSpaceAttribute }, { "nonActivating", tkNonactivatingPanelAttribute }, { "hud", tkHUDWindowAttribute }, - { "black", NULL }, - { "dark", NULL }, - { "light", NULL }, - { "gray", NULL }, - { "red", NULL }, - { "green", NULL }, - { "blue", NULL }, - { "cyan", NULL }, - { "yellow", NULL }, - { "magenta", NULL }, - { "orange", NULL }, - { "purple", NULL }, - { "brown", NULL }, - { "clear", NULL }, - { "opacity", NULL }, - { "fullscreen", NULL }, + { "black", 0 }, + { "dark", 0 }, + { "light", 0 }, + { "gray", 0 }, + { "red", 0 }, + { "green", 0 }, + { "blue", 0 }, + { "cyan", 0 }, + { "yellow", 0 }, + { "magenta", 0 }, + { "orange", 0 }, + { "purple", 0 }, + { "brown", 0 }, + { "clear", 0 }, + { "opacity", 0 }, + { "fullscreen", 0 }, { NULL } }; diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 59c6a56..2b9783d 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -911,9 +911,9 @@ XGetImage( bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height); bitmap_fmt = [bitmap_rep bitmapFormat]; - if ( bitmap_rep == Nil || - (bitmap_fmt != 0 && bitmap_fmt != 1) || - [bitmap_rep samplesPerPixel] != 4 || + if ( bitmap_rep == Nil || + (bitmap_fmt != 0 && bitmap_fmt != 1) || + [bitmap_rep samplesPerPixel] != 4 || [bitmap_rep isPlanar] != 0 ) { TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); return NULL; @@ -922,8 +922,8 @@ XGetImage( 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.*/ + + /* Assume premultiplied nonplanar data with 4 bytes per pixel.*/ if ( [bitmap_rep isPlanar ] == 0 && [bitmap_rep samplesPerPixel] == 4 ) { bytes_per_row = [bitmap_rep bytesPerRow]; @@ -934,9 +934,9 @@ XGetImage( bitmap = ckalloc(size); /* Oddly enough, the bitmap has the top row at the beginning, - and the pixels are in BGRA or ABGR format. + and the pixels are in BGRA or ABGR format. */ - if (bitmap_fmt == 0) { + if (bitmap_fmt == 0) { /* BGRA */ for (row=0, n=0; row Date: Mon, 9 Nov 2015 11:11:42 +0000 Subject: clean-up end-of-line spacing --- macosx/tkMacOSXDraw.c | 6 +++--- macosx/tkMacOSXMouseEvent.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 33c2ef9..672e266 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -446,7 +446,7 @@ CreateCGImageWithXImage( * BW image */ - /* Reverses the sense of the bits */ + /* Reverses the sense of the bits */ static const CGFloat decodeWB[2] = {1, 0}; decode = decodeWB; @@ -474,7 +474,7 @@ CreateCGImageWithXImage( /* * Color image */ - + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); bitsPerComponent = 8; @@ -761,7 +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 2b9d0bf..f4bfb44 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -75,7 +75,7 @@ static unsigned int ButtonModifiers2State(UInt32 buttonState, 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 -- cgit v0.12 From 86d9383e5ac170ca8a034085bb778f6fd96b7755 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 9 Nov 2015 15:43:08 +0000 Subject: Fix [5ee8af61e5ef8e233158a43459624f4ecf58a6fe|5ee8af61e5] on Unix: Window embedding can not work on 64-bit Unix and Windows --- unix/tkUnixEmbed.c | 5 ++--- unix/tkUnixXId.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/unix/tkUnixEmbed.c b/unix/tkUnixEmbed.c index 5b5f486..119bc67 100644 --- a/unix/tkUnixEmbed.c +++ b/unix/tkUnixEmbed.c @@ -100,7 +100,7 @@ TkpUseWindow( { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *usePtr; - int id, anyError; + int anyError; Window parent; Tk_ErrorHandler handler; Container *containerPtr; @@ -113,10 +113,9 @@ TkpUseWindow( "can't modify container after widget is created", NULL); return TCL_ERROR; } - if (Tcl_GetInt(interp, string, &id) != TCL_OK) { + if (TkpScanWindowId(interp, string, &parent) != TCL_OK) { return TCL_ERROR; } - parent = (Window) id; usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, parent); if (usePtr != NULL) { diff --git a/unix/tkUnixXId.c b/unix/tkUnixXId.c index ca2eb33..444be30 100644 --- a/unix/tkUnixXId.c +++ b/unix/tkUnixXId.c @@ -586,13 +586,23 @@ TkpScanWindowId( CONST char *string, Window *idPtr) { - int value; + int code; + Tcl_Obj obj; - if (Tcl_GetInt(interp, string, &value) != TCL_OK) { - return TCL_ERROR; + obj.refCount = 1; + obj.bytes = (char *) string; /* DANGER?! */ + obj.length = strlen(string); + obj.typePtr = NULL; + + code = Tcl_GetLongFromObj(interp, &obj, (long *)idPtr); + + if (obj.refCount > 1) { + Tcl_Panic("invalid sharing of Tcl_Obj on C stack"); + } + if (obj.typePtr && obj.typePtr->freeIntRepProc) { + obj.typePtr->freeIntRepProc(&obj); } - *idPtr = (Window) value; - return TCL_OK; + return code; } /* -- cgit v0.12 From 2a9fdd77c974171312d269dead962e6dcfc0ab21 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 10 Nov 2015 13:54:09 +0000 Subject: Fix [5ee8af61e5ef8e233158a43459624f4ecf58a6fe|5ee8af61e5] on Win64: Window embedding can not work on 64-bit Unix and Windows --- win/tkWinEmbed.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c index b7f5085..a0670cc 100644 --- a/win/tkWinEmbed.c +++ b/win/tkWinEmbed.c @@ -256,10 +256,13 @@ TkpUseWindow( return TCL_OK; } - if (Tcl_GetInt(interp, string, &id) != TCL_OK) { + if ( +#ifdef _WIN64 + (sscanf(string, "0x%p", &hwnd) != 1) && +#endif + Tcl_GetInt(interp, string, (int *) &hwnd) != TCL_OK) { return TCL_ERROR; } - hwnd = (HWND) INT2PTR(id); if ((HWND)winPtr->privatePtr == hwnd) { return TCL_OK; } -- cgit v0.12 From b4ab9d79f99aab6cfb1014e82271308f4d6184c9 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 10 Nov 2015 18:38:56 +0000 Subject: Typos in comments --- generic/tkTextBTree.c | 2 +- generic/tkTextDisp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c index 36f0ef3..58fc645 100644 --- a/generic/tkTextBTree.c +++ b/generic/tkTextBTree.c @@ -1117,7 +1117,7 @@ TkBTreeInsertChars( /* * I don't believe it's possible for either of the two lines passed to * this function to be the last line of text, but the function is robust - * to that case anyway. (We must never re-calculated the line height of + * to that case anyway. (We must never re-calculate the line height of * the last line). */ diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index fc7b46b..6036222 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -2225,7 +2225,7 @@ UpdateDisplayInfo( * Here's a problem: see the tests textDisp-29.2.1-4 * * If the widget is being created, but has not yet been configured it will - * have a maxY of 1 above, and we we won't have examined all the lines + * have a maxY of 1 above, and we won't have examined all the lines * (just the first line, in fact), and so maxOffset will not be a true * reflection of the widget's lines. Therefore we must not overwrite the * original newXPixelOffset in this case. -- cgit v0.12 From b9c5c010586da8c59bec01cd2e2d21835ef7916b Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 12 Nov 2015 21:59:18 +0000 Subject: Koen Danckaert's patch to speed up line metrics update --- generic/tkText.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index cb89218..ac56c85 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -572,8 +572,6 @@ CreateWidget( * start,end do not require a total recalculation. */ - TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); - textPtr->state = TK_TEXT_STATE_NORMAL; textPtr->relief = TK_RELIEF_FLAT; textPtr->cursor = None; @@ -583,6 +581,8 @@ CreateWidget( textPtr->prevWidth = Tk_Width(newWin); textPtr->prevHeight = Tk_Height(newWin); + TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); + /* * This will add refCounts to textPtr. */ @@ -2319,6 +2319,7 @@ TextWorldChanged( { Tk_FontMetrics fm; int border; + int oldCharHeight = textPtr->charHeight; textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, "0", 1); if (textPtr->charWidth <= 0) { @@ -2330,6 +2331,9 @@ TextWorldChanged( if (textPtr->charHeight <= 0) { textPtr->charHeight = 1; } + if (textPtr->charHeight != oldCharHeight) { + TkBTreeClientRangeChanged(textPtr, textPtr->charHeight); + } border = textPtr->borderWidth + textPtr->highlightWidth; Tk_GeometryRequest(textPtr->tkwin, textPtr->width * textPtr->charWidth + 2*textPtr->padX + 2*border, -- cgit v0.12 From de27a7c6e4d71115b1757e59735cbece10a62ae5 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 12 Nov 2015 22:50:12 +0000 Subject: Moved comment to follow the moved code in previous commit --- generic/tkText.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generic/tkText.c b/generic/tkText.c index ac56c85..6e982b0 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -566,12 +566,6 @@ CreateWidget( textPtr->end = NULL; } - /* - * Register with the B-tree. In some sense it would be best if we could do - * this later (after configuration options), so that any changes to - * start,end do not require a total recalculation. - */ - textPtr->state = TK_TEXT_STATE_NORMAL; textPtr->relief = TK_RELIEF_FLAT; textPtr->cursor = None; @@ -581,6 +575,12 @@ CreateWidget( textPtr->prevWidth = Tk_Width(newWin); textPtr->prevHeight = Tk_Height(newWin); + /* + * Register with the B-tree. In some sense it would be best if we could do + * this later (after configuration options), so that any changes to + * start,end do not require a total recalculation. + */ + TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); /* -- cgit v0.12 From 7e0de4a6b4f19d000e66c01ef7a01ca72a3960da Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 13 Nov 2015 08:44:35 +0000 Subject: Fix [https://www.sqlite.org/src/info/34eb6911afee09e7|34eb6911af], taken over from SQLite: Fix uses of ctype functions (ex: isspace()) on signed characters in test programs and in some obscure extensions. No changes to the core. --- win/nmakehlp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/win/nmakehlp.c b/win/nmakehlp.c index b1a1517..84cf75c 100644 --- a/win/nmakehlp.c +++ b/win/nmakehlp.c @@ -606,8 +606,8 @@ SubstituteFile( sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { - char *ks, *ke, *vs, *ve; - ks = szBuffer; + unsigned char *ks, *ke, *vs, *ve; + ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; @@ -616,7 +616,7 @@ SubstituteFile( ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; - list_insert(&substPtr, ks, vs); + list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } -- cgit v0.12 From f6a8214c69fd081220a6401284532d1d373749be Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 13 Nov 2015 14:54:12 +0000 Subject: Fix test-cases textDisp-33.2 and textDisp-33.3 --- tests/textDisp.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/textDisp.test b/tests/textDisp.test index a6bbfd7..9c6af70 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -4104,7 +4104,7 @@ test textDisp-33.2 {one line longer than fits in the widget} { .tt debug 1 set tk_textHeightCalc "" .tt insert 1.0 [string repeat "more wrap + " 1] - after 100 ; update + after 100 ; update idletasks # Nothing should have been recalculated. set tk_textHeightCalc } {} @@ -4184,7 +4184,7 @@ test textDisp-34.1 {Text widgets multi-scrolling problem: Bug 2677890} -setup { return $result } -cleanup { destroy .t1 .sy -} -result {{0.0 1.0} {0.0 1.0} {0.0 1.0} {0.0 0.24}} +} -result {{0.0 0.24} {0.0 0.24} {0.0 0.24} {0.0 0.24}} deleteWindows option clear -- cgit v0.12 From 3f3a9160c939098aa881f1b2429f23f883750a87 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 17 Nov 2015 15:20:13 +0000 Subject: Fixed bug [1997299fff] - Tag borderwidth is leaking horizontally --- generic/tkTextDisp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 6036222..7cf996f 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -2540,7 +2540,7 @@ DisplayLineBackground( * current x coordinate? */ int matchRight; /* Does line's style match its neighbor just * to the right of the current x-coord? */ - int minX, maxX, xOffset; + int minX, maxX, xOffset, bw; StyleValues *sValuePtr; Display *display; #ifndef TK_NO_DOUBLE_BUFFERING @@ -2611,16 +2611,25 @@ DisplayLineBackground( rightX = leftX + 32767; } + /* + * Prevent the borders from leaking on adjacent characters, + * which would happen for too large border width. + */ + + bw = sValuePtr->borderWidth; + if (leftX + sValuePtr->borderWidth > rightX) { + bw = rightX - leftX; + } + XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC, leftX + xOffset, y, (unsigned int) (rightX - leftX), (unsigned int) dlPtr->height); if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y, sValuePtr->borderWidth, - dlPtr->height, 1, sValuePtr->relief); + leftX + xOffset, y, bw, dlPtr->height, 1, + sValuePtr->relief); Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX - sValuePtr->borderWidth + xOffset, - y, sValuePtr->borderWidth, dlPtr->height, 0, + rightX - bw + xOffset, y, bw, dlPtr->height, 0, sValuePtr->relief); } } -- cgit v0.12 From f9deb87502be44e6422e4996e26bf383903fdda1 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 17 Nov 2015 23:52:07 +0000 Subject: More leaking tags fixed, see test script in bug [1997299fff] --- generic/tkTextDisp.c | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 7cf996f..cfe6e7a 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -2726,22 +2726,29 @@ DisplayLineBackground( matchRight = (nextPtr2 != NULL) && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr); if (matchLeft && !matchRight) { + bw = sValuePtr->borderWidth; + if (rightX2 - sValuePtr->borderWidth < leftX) { + bw = rightX2 - leftX; + } if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 - sValuePtr->borderWidth + xOffset, y, - sValuePtr->borderWidth, sValuePtr->borderWidth, 0, - sValuePtr->relief); + rightX2 - bw + xOffset, y, bw, + sValuePtr->borderWidth, 0, sValuePtr->relief); } - leftX = rightX2 - sValuePtr->borderWidth; + leftX = rightX2 - bw; leftXIn = 0; } else if (!matchLeft && matchRight && (sValuePtr->relief != TK_RELIEF_FLAT)) { + bw = sValuePtr->borderWidth; + if (rightX2 + sValuePtr->borderWidth > rightX) { + bw = rightX - rightX2; + } Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 + xOffset, y, sValuePtr->borderWidth, - sValuePtr->borderWidth, 1, sValuePtr->relief); + rightX2 + xOffset, y, bw, sValuePtr->borderWidth, + 1, sValuePtr->relief); Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y, rightX2 + sValuePtr->borderWidth - - leftX, sValuePtr->borderWidth, leftXIn, 0, 1, + leftX + xOffset, y, rightX2 + bw - leftX, + sValuePtr->borderWidth, leftXIn, 0, 1, sValuePtr->relief); } @@ -2773,7 +2780,7 @@ DisplayLineBackground( chunkPtr2 = NULL; if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) { /* - * Find the chunk in the previous line that covers leftX. + * Find the chunk in the next line that covers leftX. */ nextPtr2 = dlPtr->nextPtr->chunkPtr; @@ -2829,26 +2836,33 @@ DisplayLineBackground( matchRight = (nextPtr2 != NULL) && SAME_BACKGROUND(nextPtr2->stylePtr, chunkPtr->stylePtr); if (matchLeft && !matchRight) { + bw = sValuePtr->borderWidth; + if (rightX2 - sValuePtr->borderWidth < leftX) { + bw = rightX2 - leftX; + } if (sValuePtr->relief != TK_RELIEF_FLAT) { Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 - sValuePtr->borderWidth + xOffset, + rightX2 - bw + xOffset, y + dlPtr->height - sValuePtr->borderWidth, - sValuePtr->borderWidth, sValuePtr->borderWidth, 0, - sValuePtr->relief); + bw, sValuePtr->borderWidth, 0, sValuePtr->relief); } - leftX = rightX2 - sValuePtr->borderWidth; + leftX = rightX2 - bw; leftXIn = 1; } else if (!matchLeft && matchRight && (sValuePtr->relief != TK_RELIEF_FLAT)) { + bw = sValuePtr->borderWidth; + if (rightX2 + sValuePtr->borderWidth > rightX) { + bw = rightX - rightX2; + } Tk_3DVerticalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - rightX2 + xOffset, y + dlPtr->height - - sValuePtr->borderWidth, sValuePtr->borderWidth, + rightX2 + xOffset, + y + dlPtr->height - sValuePtr->borderWidth, bw, sValuePtr->borderWidth, 1, sValuePtr->relief); Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y + dlPtr->height - - sValuePtr->borderWidth, rightX2 + sValuePtr->borderWidth - - leftX, sValuePtr->borderWidth, leftXIn, 1, 0, - sValuePtr->relief); + leftX + xOffset, + y + dlPtr->height - sValuePtr->borderWidth, + rightX2 + bw - leftX, sValuePtr->borderWidth, leftXIn, + 1, 0, sValuePtr->relief); } nextChunk2b: -- cgit v0.12 From 617357cee930232f242f3f6345ac828f2ab59b10 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 18 Nov 2015 21:14:04 +0000 Subject: Added visual tests for borders, following bug [1997299fff] --- tests/bevel.tcl | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/bevel.tcl b/tests/bevel.tcl index 950b714..531def0 100644 --- a/tests/bevel.tcl +++ b/tests/bevel.tcl @@ -42,6 +42,7 @@ significance: r - should appear raised u - should appear raised and also slightly offset vertically s - should appear sunken +S - should appear solid n - preceding relief should extend right to end of line. * - should appear "normal" x - extra long lines to allow horizontal scrolling. @@ -125,15 +126,35 @@ foreach i {1 2 3} { .t.t insert end ***** .t.t insert end rrr r1 +font configure TkFixedFont -size 20 +.t.t tag configure sol100 -relief solid -borderwidth 100 \ + -foreground red -font TkFixedFont +.t.t tag configure sol12 -relief solid -borderwidth 12 \ + -foreground red -font TkFixedFont +.t.t tag configure big -font TkFixedFont +set ind [.t.t index end] + +.t.t insert end "\n\nBorders do not leak on the neighbour chars" +.t.t insert end "\nOnly \"S\" is on dark background" +.t.t insert end { + xxx + x} {} S sol100 {x + xxx} + +.t.t insert end "\n\nA very thick border grows toward the inside of the tagged area only" +.t.t insert end "\nOnly \"S\" is on dark background" +.t.t insert end { + xxxx} {} SSSSS sol100 {xxxx + x} {} SSSSSSSSSSSSSSSSSS sol100 {x + xxx} {} SSSSSSSSS sol100 xxxx {} +} +.t.t insert end "\n\nA thinner border is continuous" +.t.t insert end { + xxxx} {} SSSSS sol12 {xxxx + x} {} SSSSSSSSSSSSSSSSSS sol12 {x + xxx} {} SSSSSSSSS sol12 xxxx {} +} - - - - - - - - - +.t.t tag add big $ind end -- cgit v0.12 From 52d9e935fa49fe13831f9e0eddba4e260c88f0f0 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 22 Nov 2015 20:58:13 +0000 Subject: Added test textDisp-35.1 to check for regressions against pach [5b11cf19] --- tests/textDisp.test | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/textDisp.test b/tests/textDisp.test index 9c6af70..5508d7c 100644 --- a/tests/textDisp.test +++ b/tests/textDisp.test @@ -4186,6 +4186,22 @@ test textDisp-34.1 {Text widgets multi-scrolling problem: Bug 2677890} -setup { destroy .t1 .sy } -result {{0.0 0.24} {0.0 0.24} {0.0 0.24} {0.0 0.24}} +test textDisp-35.1 {Init value of charHeight - Dancing scrollbar bug 1499165} -setup { + pack [text .t1] -fill both -expand y -side left + .t insert end "[string repeat a\nb\nc\n 500000]THE END\n" + set res {} +} -body { + .t see 10000.0 + after 300 {set fr1 [.t yview] ; set done 1} + vwait done + after 300 {set fr2 [.t yview] ; set done 1} + vwait done + lappend res [expr {[lindex $fr1 0] == [lindex $fr2 0]}] + lappend res [expr {[lindex $fr1 1] == [lindex $fr2 1]}] +} -cleanup { + destroy .t1 +} -result {1 1} + deleteWindows option clear -- cgit v0.12 From 44411926e57b5c15f9910dcdcde14c666571645e Mon Sep 17 00:00:00 2001 From: Kevin Walzer Date: Wed, 25 Nov 2015 03:19:19 +0000 Subject: Remove multiple deprecated internal API calls on OS X; streamline Apple Events implementation; thanks to Marc Culler for extensive patches --- generic/tkImgPhoto.c | 6 +- macosx/tkMacOSXDialog.c | 386 ++++++++++++++-------- macosx/tkMacOSXDraw.c | 2 +- macosx/tkMacOSXFont.c | 18 +- macosx/tkMacOSXHLEvents.c | 756 +++++++++++++++++-------------------------- macosx/tkMacOSXMenu.c | 2 +- macosx/tkMacOSXMouseEvent.c | 107 +++--- macosx/tkMacOSXPrivate.h | 28 +- macosx/tkMacOSXWindowEvent.c | 13 +- macosx/tkMacOSXWm.c | 42 +++ macosx/tkMacOSXXStubs.c | 16 +- 11 files changed, 685 insertions(+), 691 deletions(-) diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 780b0c2..47aa523 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -2454,7 +2454,11 @@ ImgPhotoGet( } XFree((char *) visInfoPtr); - sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue); + if (mono) { + sprintf(buf, "%d", nRed); + } else { + sprintf(buf, "%d/%d/%d", nRed, nGreen, nBlue); + } instancePtr->defaultPalette = Tk_GetUid(buf); /* diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index b5ff48b..9cd9cf3 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -7,24 +7,34 @@ * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ #include "tkMacOSXPrivate.h" #include "tkFileFilter.h" +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 +#define modalOK NSOKButton +#define modalCancel NSCancelButton +#else +#define modalOK NSModalResponseOK +#define modalCancel NSModalResponseCancel +#endif +#define modalOther -1 +#define modalError -2 + static int TkBackgroundEvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int flags); -static const char *colorOptionStrings[] = { +static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL }; enum colorOptions { COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE }; -static const char *openOptionStrings[] = { +static const char *const openOptionStrings[] = { "-defaultextension", "-filetypes", "-initialdir", "-initialfile", "-message", "-multiple", "-parent", "-title", "-typevariable", "-command", NULL @@ -34,7 +44,7 @@ enum openOptions { OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE, OPEN_TYPEVARIABLE, OPEN_COMMAND, }; -static const char *saveOptionStrings[] = { +static const char *const saveOptionStrings[] = { "-defaultextension", "-filetypes", "-initialdir", "-initialfile", "-message", "-parent", "-title", "-typevariable", "-command", "-confirmoverwrite", NULL @@ -44,7 +54,7 @@ enum saveOptions { SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE, SAVE_TYPEVARIABLE, SAVE_COMMAND, SAVE_CONFIRMOW }; -static const char *chooseOptionStrings[] = { +static const char *const chooseOptionStrings[] = { "-initialdir", "-message", "-mustexist", "-parent", "-title", "-command", NULL }; @@ -58,7 +68,7 @@ typedef struct { int multiple; } FilePanelCallbackInfo; -static const char *alertOptionStrings[] = { +static const char *const alertOptionStrings[] = { "-default", "-detail", "-icon", "-message", "-parent", "-title", "-type", "-command", NULL }; @@ -71,7 +81,7 @@ typedef struct { Tcl_Obj *cmdObj; int typeIndex; } AlertCallbackInfo; -static const char *alertTypeStrings[] = { +static const char *const alertTypeStrings[] = { "abortretryignore", "ok", "okcancel", "retrycancel", "yesno", "yesnocancel", NULL }; @@ -79,13 +89,13 @@ enum alertTypeOptions { TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL, TYPE_YESNO, TYPE_YESNOCANCEL }; -static const char *alertIconStrings[] = { +static const char *const alertIconStrings[] = { "error", "info", "question", "warning", NULL }; enum alertIconOptions { ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING }; -static const char *alertButtonStrings[] = { +static const char *const alertButtonStrings[] = { "abort", "retry", "ignore", "ok", "cancel", "yes", "no", NULL }; @@ -105,9 +115,9 @@ static const NSAlertStyle alertStyles[] = { }; /* - * Need to map from 'alertButtonStrings' and its corresponding integer, - * index to the native button index, which is 1, 2, 3, from right to left. - * This is necessary to do for each separate '-type' of button sets. + * Need to map from 'alertButtonStrings' and its corresponding integer, index + * to the native button index, which is 1, 2, 3, from right to left. This is + * necessary to do for each separate '-type' of button sets. */ static const short alertButtonIndexAndTypeToNativeButtonIndex[][7] = { @@ -134,27 +144,47 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { [TYPE_YESNOCANCEL] = {5, 6, 4}, }; +/* + * Construct a file URL from directory and filename. Either may + * be nil. If both are nil, returns nil. + */ +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1050 +static NSURL *getFileURL(NSString *directory, NSString *filename) { + NSURL *url = nil; + if (directory) { + url = [NSURL fileURLWithPath:directory]; + } + if (filename) { + url = [NSURL URLWithString:filename relativeToURL:url]; + } + return url; +} +#endif + #pragma mark TKApplication(TKDialog) @interface NSColorPanel(TKDialog) -- (void)_setUseModalAppearance:(BOOL)flag; +- (void) _setUseModalAppearance: (BOOL) flag; @end @implementation TKApplication(TKDialog) -- (void)tkFilePanelDidEnd:(NSSavePanel *)panel returnCode:(NSInteger)returnCode - contextInfo:(void *)contextInfo { + +- (void) tkFilePanelDidEnd: (NSSavePanel *) panel + returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo +{ FilePanelCallbackInfo *callbackInfo = contextInfo; if (returnCode == NSFileHandlingPanelOKButton) { Tcl_Obj *resultObj; + if (callbackInfo->multiple) { resultObj = Tcl_NewListObj(0, NULL); - for (NSString *name in [(NSOpenPanel*)panel filenames]) { + for (NSURL *url in [(NSOpenPanel*)panel URLs]) { Tcl_ListObjAppendElement(callbackInfo->interp, resultObj, - Tcl_NewStringObj([name UTF8String], -1)); + Tcl_NewStringObj([[url path] UTF8String], -1)); } } else { - resultObj = Tcl_NewStringObj([[panel filename] UTF8String], -1); + resultObj = Tcl_NewStringObj([[[panel URL]path] UTF8String], -1); } if (callbackInfo->cmdObj) { Tcl_Obj **objv, **tmpv; @@ -179,14 +209,14 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { } if (callbackInfo->cmdObj) { Tcl_DecrRefCount(callbackInfo->cmdObj); - ckfree((char*) callbackInfo); + ckfree((char *)callbackInfo); } } - (void)tkAlertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { AlertCallbackInfo *callbackInfo = contextInfo; - if (returnCode != NSAlertErrorReturn) { + if (returnCode >= NSAlertFirstButtonReturn) { Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo-> typeIndex][returnCode - NSAlertFirstButtonReturn]], -1); @@ -211,7 +241,7 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { } if (callbackInfo->cmdObj) { Tcl_DecrRefCount(callbackInfo->cmdObj); - ckfree((char*) callbackInfo); + ckfree((char *) callbackInfo); } } @end @@ -252,43 +282,41 @@ Tk_ChooseColorObjCmd( for (i = 1; i < objc; i += 2) { int index; - const char *option, *value; + const char *value; - if (Tcl_GetIndexFromObj(interp, objv[i], colorOptionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], colorOptionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - option = Tcl_GetString(objv[i]); - Tcl_AppendResult(interp, "value for \"", option, "\" missing", - NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL); goto end; } value = Tcl_GetString(objv[i + 1]); switch (index) { - case COLOR_INITIAL: { - XColor *colorPtr; + case COLOR_INITIAL: { + XColor *colorPtr; - colorPtr = Tk_GetColor(interp, tkwin, value); - if (colorPtr == NULL) { - goto end; - } - initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel); - Tk_FreeColor(colorPtr); - break; - } - case COLOR_PARENT: { - parent = Tk_NameToWindow(interp, value, tkwin); - if (parent == NULL) { - goto end; - } - break; + colorPtr = Tk_GetColor(interp, tkwin, value); + if (colorPtr == NULL) { + goto end; } - case COLOR_TITLE: { - title = value; - break; + initialColor = TkMacOSXGetNSColor(NULL, colorPtr->pixel); + Tk_FreeColor(colorPtr); + break; + } + case COLOR_PARENT: + parent = Tk_NameToWindow(interp, value, tkwin); + if (parent == NULL) { + goto end; } + break; + case COLOR_TITLE: + title = value; + break; } } colorPanel = [NSColorPanel sharedColorPanel]; @@ -306,7 +334,7 @@ Tk_ChooseColorObjCmd( [colorPanel setColor:initialColor]; } returnCode = [NSApp runModalForWindow:colorPanel]; - if (returnCode == NSOKButton) { + if (returnCode == modalOK) { color = [[colorPanel color] colorUsingColorSpace: [NSColorSpace genericRGBColorSpace]]; numberOfComponents = [color numberOfComponents]; @@ -325,6 +353,7 @@ Tk_ChooseColorObjCmd( Tcl_ResetResult(interp); } result = TCL_OK; + end: return result; } @@ -365,17 +394,18 @@ Tk_GetOpenFileObjCmd( NSWindow *parent; NSMutableArray *fileTypes = nil; NSOpenPanel *panel = [NSOpenPanel openPanel]; - NSInteger returnCode = NSAlertErrorReturn; + NSInteger modalReturnCode = modalError; TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], openOptionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - str = Tcl_GetString(objv[i]); - Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL); goto end; } switch (index) { @@ -434,6 +464,7 @@ Tk_GetOpenFileObjCmd( break; } } + [panel setAllowsMultipleSelection:multiple]; if (fl.filters) { fileTypes = [NSMutableArray array]; for (FileFilter *filterPtr = fl.filters; filterPtr; @@ -466,10 +497,9 @@ Tk_GetOpenFileObjCmd( } } } - [panel setAllowsMultipleSelection:multiple]; + [panel setAllowedFileTypes:fileTypes]; if (cmdObj) { - callbackInfo = (FilePanelCallbackInfo *) - ckalloc(sizeof(FilePanelCallbackInfo)); + callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { cmdObj = Tcl_DuplicateObj(cmdObj); } @@ -480,28 +510,47 @@ Tk_GetOpenFileObjCmd( callbackInfo->multiple = multiple; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - [panel beginSheetForDirectory:directory file:filename types:fileTypes - modalForWindow:parent modalDelegate:NSApp didEndSelector: - @selector(tkFilePanelDidEnd:returnCode:contextInfo:) - contextInfo:callbackInfo]; - returnCode = cmdObj ? NSAlertOtherReturn : - [NSApp runModalForWindow:panel]; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + [panel beginSheetForDirectory:directory + file:filename + types:fileTypes + modalForWindow:parent + modalDelegate:NSApp + didEndSelector: + @selector(tkFilePanelDidEnd:returnCode:contextInfo:) + contextInfo:callbackInfo]; +#else + [panel setAllowedFileTypes:fileTypes]; + [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel beginSheetModalForWindow:parent + completionHandler:^(NSInteger returnCode) + { [NSApp tkFilePanelDidEnd:panel + returnCode:returnCode + contextInfo:callbackInfo ]; } ]; +#endif + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; } else { - returnCode = [panel runModalForDirectory:directory file:filename - types:fileTypes]; - [NSApp tkFilePanelDidEnd:panel returnCode:returnCode +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + modalReturnCode = [panel runModalForDirectory:directory + file:filename]; +#else + [panel setDirectoryURL:getFileURL(directory, filename)]; + modalReturnCode = [panel runModal]; +#endif + [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode contextInfo:callbackInfo]; } - result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR; + result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (typeVariablePtr && result == TCL_OK) { /* * The -typevariable option is not really supported. */ - Tcl_SetVar(interp, Tcl_GetString(typeVariablePtr), "", - TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, Tcl_GetString(typeVariablePtr), NULL, + "", TCL_GLOBAL_ONLY); } -end: + + end: TkFreeFileFilters(&fl); return result; } @@ -543,18 +592,18 @@ Tk_GetSaveFileObjCmd( NSWindow *parent; NSMutableArray *fileTypes = nil; NSSavePanel *panel = [NSSavePanel savePanel]; - NSInteger returnCode = NSAlertErrorReturn; + NSInteger modalReturnCode = modalError; TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - str = Tcl_GetString(objv[i]); - Tcl_AppendResult(interp, "value for \"", str, "\" missing", - NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL); goto end; } switch (index) { @@ -614,7 +663,7 @@ Tk_GetSaveFileObjCmd( break; case SAVE_CONFIRMOW: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], - &confirmOverwrite) != TCL_OK) { + &confirmOverwrite) != TCL_OK) { goto end; } break; @@ -649,8 +698,7 @@ Tk_GetSaveFileObjCmd( [panel setCanSelectHiddenExtension:YES]; [panel setExtensionHidden:NO]; if (cmdObj) { - callbackInfo = (FilePanelCallbackInfo *) - ckalloc(sizeof(FilePanelCallbackInfo)); + callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { cmdObj = Tcl_DuplicateObj(cmdObj); } @@ -661,19 +709,36 @@ Tk_GetSaveFileObjCmd( callbackInfo->multiple = 0; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - [panel beginSheetForDirectory:directory file:filename - modalForWindow:parent modalDelegate:NSApp didEndSelector: - @selector(tkFilePanelDidEnd:returnCode:contextInfo:) - contextInfo:callbackInfo]; - returnCode = cmdObj ? NSAlertOtherReturn : - [NSApp runModalForWindow:panel]; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + [panel beginSheetForDirectory:directory + file:filename + modalForWindow:parent + modalDelegate:NSApp + didEndSelector: + @selector(tkFilePanelDidEnd:returnCode:contextInfo:) + contextInfo:callbackInfo]; +#else + [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel beginSheetModalForWindow:parent + completionHandler:^(NSInteger returnCode) + { [NSApp tkFilePanelDidEnd:panel + returnCode:returnCode + contextInfo:callbackInfo ]; } ]; +#endif + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; } else { - returnCode = [panel runModalForDirectory:directory file:filename]; - [NSApp tkFilePanelDidEnd:panel returnCode:returnCode +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + modalReturnCode = [panel runModalForDirectory:directory file:filename]; +#else + [panel setDirectoryURL:getFileURL(directory, filename)]; + modalReturnCode = [panel runModal]; +#endif + [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode contextInfo:callbackInfo]; } - result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR; -end: + result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; + + end: TkFreeFileFilters(&fl); return result; } @@ -714,16 +779,17 @@ Tk_ChooseDirectoryObjCmd( NSString *message, *title; NSWindow *parent; NSOpenPanel *panel = [NSOpenPanel openPanel]; - NSInteger returnCode = NSAlertErrorReturn; + NSInteger modalReturnCode = modalError; for (i = 1; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], chooseOptionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - str = Tcl_GetString(objv[i]); - Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL); goto end; } switch (index) { @@ -770,8 +836,7 @@ Tk_ChooseDirectoryObjCmd( [panel setCanChooseDirectories:YES]; [panel setCanCreateDirectories:!mustexist]; if (cmdObj) { - callbackInfo = (FilePanelCallbackInfo *) - ckalloc(sizeof(FilePanelCallbackInfo)); + callbackInfo = (FilePanelCallbackInfo *)ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { cmdObj = Tcl_DuplicateObj(cmdObj); } @@ -782,19 +847,35 @@ Tk_ChooseDirectoryObjCmd( callbackInfo->multiple = 0; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - [panel beginSheetForDirectory:directory file:filename - modalForWindow:parent modalDelegate:NSApp didEndSelector: - @selector(tkFilePanelDidEnd:returnCode:contextInfo:) +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + [panel beginSheetForDirectory:directory + file:filename + modalForWindow:parent + modalDelegate:NSApp + didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; - returnCode = cmdObj ? NSAlertOtherReturn : - [NSApp runModalForWindow:panel]; +#else + [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel beginSheetModalForWindow:parent + completionHandler:^(NSInteger returnCode) + { [NSApp tkFilePanelDidEnd:panel + returnCode:returnCode + contextInfo:callbackInfo ]; } ]; +#endif + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; } else { - returnCode = [panel runModalForDirectory:directory file:filename]; - [NSApp tkFilePanelDidEnd:panel returnCode:returnCode +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + modalReturnCode = [panel runModalForDirectory:directory file:nil]; +#else + [panel setDirectoryURL:getFileURL(directory, filename)]; + modalReturnCode = [panel runModal]; +#endif + [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode contextInfo:callbackInfo]; } - result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR; -end: + result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; + + end: return result; } @@ -818,20 +899,29 @@ void TkAboutDlg(void) { NSImage *image; - NSString *path = [NSApp tkFrameworkImagePath:@"Tk.tiff"]; + NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"]; + if (path) { image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease]; } else { image = [NSApp applicationIconImage]; } + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; [dateFormatter setDateFormat:@"Y"]; + NSString *year = [dateFormatter stringFromDate:[NSDate date]]; + [dateFormatter release]; - NSMutableParagraphStyle *style = [[[NSParagraphStyle defaultParagraphStyle] - mutableCopy] autorelease]; + + NSMutableParagraphStyle *style = + [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] + autorelease]; + [style setAlignment:NSCenterTextAlignment]; + NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: @"Tcl & Tk", @"ApplicationName", @"Tcl " TCL_VERSION " & Tk " TK_VERSION, @"ApplicationVersion", @@ -842,15 +932,15 @@ TkAboutDlg(void) [[[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"%1$C 1987-%2$@ Tcl Core Team." "\n\n" - "%1$C 1989-%2$@ Contributors." "\n\n" + "%1$C 1989-%2$@ Contributors." "\n\n" "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC." "\n\n" "%1$C 2014-%2$@ Marc Culler." "\n\n" - "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n" - "%1$C 2001-2009 Apple Inc." "\n\n" - "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n" - "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n" - "%1$C 1998-2000 Scriptics Inc." "\n\n" - "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes: + "%1$C 2002-%2$@ Daniel A. Steffen." "\n\n" + "%1$C 2001-2009 Apple Inc." "\n\n" + "%1$C 2001-2002 Jim Ingham & Ian Reid" "\n\n" + "%1$C 1998-2000 Jim Ingham & Ray Johnson" "\n\n" + "%1$C 1998-2000 Scriptics Inc." "\n\n" + "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] attributes: [NSDictionary dictionaryWithObject:style forKey:NSParagraphStyleAttributeName]] autorelease], @"Credits", nil]; @@ -884,7 +974,7 @@ TkMacOSXStandardAboutPanelObjCmd( Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } - [NSApp orderFrontStandardAboutPanelWithOptions:nil]; + [NSApp orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionary]]; return TCL_OK; } @@ -922,18 +1012,19 @@ Tk_MessageBoxObjCmd( NSWindow *parent; NSArray *buttons; NSAlert *alert = [NSAlert new]; - NSInteger returnCode = NSAlertErrorReturn; + NSInteger modalReturnCode = 1; iconIndex = ICON_INFO; typeIndex = TYPE_OK; for (i = 1; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], alertOptionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i], alertOptionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - str = Tcl_GetString(objv[i]); - Tcl_AppendResult(interp, "value for \"", str, "\" missing", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL); goto end; } switch (index) { @@ -954,8 +1045,8 @@ Tk_MessageBoxObjCmd( break; case ALERT_ICON: - if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertIconStrings, - "value", TCL_EXACT, &iconIndex) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertIconStrings, + sizeof(char *), "value", TCL_EXACT, &iconIndex) != TCL_OK) { goto end; } break; @@ -984,8 +1075,8 @@ Tk_MessageBoxObjCmd( break; case ALERT_TYPE: - if (Tcl_GetIndexFromObj(interp, objv[i + 1], alertTypeStrings, - "value", TCL_EXACT, &typeIndex) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[i + 1], alertTypeStrings, + sizeof(char *), "value", TCL_EXACT, &typeIndex) != TCL_OK) { goto end; } break; @@ -996,13 +1087,12 @@ Tk_MessageBoxObjCmd( } if (indexDefaultOption) { /* - * Any '-default' option needs to know the '-type' option, which is why - * we do this here. + * Any '-default' option needs to know the '-type' option, which is + * why we do this here. */ - if (Tcl_GetIndexFromObj(interp, objv[indexDefaultOption + 1], - alertButtonStrings, "value", TCL_EXACT, &index) - != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, objv[indexDefaultOption + 1], + alertButtonStrings, sizeof(char *), "value", TCL_EXACT, &index) != TCL_OK) { goto end; } @@ -1015,6 +1105,7 @@ Tk_MessageBoxObjCmd( if (!defaultNativeButtonIndex) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Illegal default option", -1)); + Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL); goto end; } } @@ -1027,15 +1118,17 @@ Tk_MessageBoxObjCmd( buttons = [alert buttons]; for (NSButton *b in buttons) { NSString *ke = [b keyEquivalent]; + if (([ke isEqualToString:@"\r"] || [ke isEqualToString:@"\033"]) && ![b keyEquivalentModifierMask]) { [b setKeyEquivalent:@""]; } } - [[buttons objectAtIndex:[buttons count]-1] setKeyEquivalent:@"\033"]; - [[buttons objectAtIndex:defaultNativeButtonIndex-1] setKeyEquivalent:@"\r"]; + [[buttons objectAtIndex: [buttons count]-1] setKeyEquivalent: @"\033"]; + [[buttons objectAtIndex: defaultNativeButtonIndex-1] + setKeyEquivalent: @"\r"]; if (cmdObj) { - callbackInfo = (AlertCallbackInfo *) ckalloc(sizeof(AlertCallbackInfo)); + callbackInfo = (AlertCallbackInfo *)ckalloc(sizeof(AlertCallbackInfo)); if (Tcl_IsShared(cmdObj)) { cmdObj = Tcl_DuplicateObj(cmdObj); } @@ -1046,18 +1139,27 @@ Tk_MessageBoxObjCmd( callbackInfo->typeIndex = typeIndex; parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { - [alert beginSheetModalForWindow:parent modalDelegate:NSApp - didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:) - contextInfo:callbackInfo]; - returnCode = cmdObj ? NSAlertOtherReturn : - [NSApp runModalForWindow:[alert window]]; +#if MAC_OS_X_VERSION_MIN_REQUIRED > 1090 + [alert beginSheetModalForWindow:parent + completionHandler:^(NSModalResponse returnCode) + { [NSApp tkAlertDidEnd:alert + returnCode:returnCode + contextInfo:callbackInfo ]; } ]; +#else + [alert beginSheetModalForWindow:parent + modalDelegate:NSApp + didEndSelector:@selector(tkAlertDidEnd:returnCode:contextInfo:) + contextInfo:callbackInfo]; +#endif + modalReturnCode = cmdObj ? 0 : + [NSApp runModalForWindow:[alert window]]; } else { - returnCode = [alert runModal]; - [NSApp tkAlertDidEnd:alert returnCode:returnCode + modalReturnCode = [alert runModal]; + [NSApp tkAlertDidEnd:alert returnCode:modalReturnCode contextInfo:callbackInfo]; } - result = (returnCode != NSAlertErrorReturn) ? TCL_OK : TCL_ERROR; -end: + result = (modalReturnCode < 1) ? TCL_OK : TCL_ERROR; + end: [alert release]; return result; } diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 672e266..45a07c7 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -675,7 +675,7 @@ GetCGContextForDrawable( if (macDraw->flags & TK_IS_BW_PIXMAP) { bitsPerPixel = 8; - bitmapInfo = kCGImageAlphaOnly; + bitmapInfo = (CGBitmapInfo)kCGImageAlphaOnly; } else { colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); bitsPerPixel = 32; diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index d30da09..f1e01d2 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -15,6 +15,19 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXFont.h" +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 +#define defaultOrientation kCTFontDefaultOrientation +#define verticalOrientation kCTFontVerticalOrientation +#else +#define defaultOrientation kCTFontOrientationDefault +#define verticalOrientation kCTFontOrientationVertical +#endif +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101100 +#define fixedPitch kCTFontUserFixedPitchFontType +#else +#define fixedPitch kCTFontUIFontUserFixedPitch +#endif + /* #ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_FONTS @@ -270,7 +283,7 @@ InitFont( fmPtr->fixed = [nsFont advancementForGlyph:glyphs[0]].width == [nsFont advancementForGlyph:glyphs[1]].width; bounds = NSRectFromCGRect(CTFontGetBoundingRectsForGlyphs((CTFontRef) - nsFont, kCTFontDefaultOrientation, ch, boundingRects, nCh)); + nsFont, defaultOrientation, ch, boundingRects, nCh)); kern = [nsFont advancementForGlyph:glyphs[2]].width - [fontPtr->nsFont advancementForGlyph:glyphs[2]].width; } @@ -382,8 +395,7 @@ TkpFontPkgInit( systemFont++; } TkInitFontAttributes(&fa); - nsFont = (NSFont*) CTFontCreateUIFontForLanguage( - kCTFontUserFixedPitchFontType, 11, NULL); + nsFont = (NSFont*) CTFontCreateUIFontForLanguage(fixedPitch, 11, NULL); if (nsFont) { GetTkFontAttributesForNSFont(nsFont, &fa); CFRelease(nsFont); diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index 9671ab9..9c0f9d1 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -7,12 +7,15 @@ * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright (c) 2015 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkMacOSXPrivate.h" +#include +#define URL_MAX_LENGTH (17 + MAXPATHLEN) /* * This is a Tcl_Event structure that the Quit AppleEvent handler uses to @@ -30,154 +33,32 @@ typedef struct KillEvent { * Static functions used only in this file. */ -static OSErr QuitHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr OappHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr RappHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr OdocHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr PrintHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr ScriptHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static OSErr PrefsHandler(const AppleEvent *event, - AppleEvent *reply, SRefCon handlerRefcon); -static int MissedAnyParameters(const AppleEvent *theEvent); -static int ReallyKillMe(Tcl_Event *eventPtr, int flags); -static OSStatus FSRefToDString(const FSRef *fsref, Tcl_DString *ds); +static void tkMacOSXProcessFiles(NSAppleEventDescriptor* event, + NSAppleEventDescriptor* replyEvent, + Tcl_Interp *interp, + char* procedure); +static int MissedAnyParameters(const AppleEvent *theEvent); +static int ReallyKillMe(Tcl_Event *eventPtr, int flags); #pragma mark TKApplication(TKHLEvents) @implementation TKApplication(TKHLEvents) - -- (void)terminate:(id)sender { - QuitHandler(NULL, NULL, (SRefCon) _eventInterp); -} - -- (void)preferences:(id)sender { - PrefsHandler(NULL, NULL, (SRefCon) _eventInterp); -} - -@end - -#pragma mark - - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXInitAppleEvents -- - * - * Initilize the Apple Events on the Macintosh. This registers the core - * event handlers. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TkMacOSXInitAppleEvents( - Tcl_Interp *interp) /* Interp to handle basic events. */ +- (void) terminate: (id) sender { - AEEventHandlerUPP OappHandlerUPP, RappHandlerUPP, OdocHandlerUPP; - AEEventHandlerUPP PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP; - AEEventHandlerUPP PrefsHandlerUPP; - static Boolean initialized = FALSE; - - if (!initialized) { - initialized = TRUE; - - /* - * Install event handlers for the core apple events. - */ - - QuitHandlerUPP = NewAEEventHandlerUPP(QuitHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEQuitApplication, - QuitHandlerUPP, (SRefCon) interp, false); - - OappHandlerUPP = NewAEEventHandlerUPP(OappHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenApplication, - OappHandlerUPP, (SRefCon) interp, false); - - RappHandlerUPP = NewAEEventHandlerUPP(RappHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEReopenApplication, - RappHandlerUPP, (SRefCon) interp, false); - - OdocHandlerUPP = NewAEEventHandlerUPP(OdocHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenDocuments, - OdocHandlerUPP, (SRefCon) interp, false); - - PrintHandlerUPP = NewAEEventHandlerUPP(PrintHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEPrintDocuments, - PrintHandlerUPP, (SRefCon) interp, false); - - PrefsHandlerUPP = NewAEEventHandlerUPP(PrefsHandler); - ChkErr(AEInstallEventHandler, kCoreEventClass, kAEShowPreferences, - PrefsHandlerUPP, (SRefCon) interp, false); - - if (interp) { - ScriptHandlerUPP = NewAEEventHandlerUPP(ScriptHandler); - ChkErr(AEInstallEventHandler, kAEMiscStandards, kAEDoScript, - ScriptHandlerUPP, (SRefCon) interp, false); - } - } + [self handleQuitApplicationEvent:Nil withReplyEvent:Nil]; } - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXDoHLEvent -- - * - * Dispatch incomming highlevel events. - * - * Results: - * None. - * - * Side effects: - * Depends on the incoming event. - * - *---------------------------------------------------------------------- - */ -int -TkMacOSXDoHLEvent( - void *theEvent) +- (void) preferences: (id) sender { - return AEProcessAppleEvent((EventRecord *)theEvent); + [self handleShowPreferencesEvent:Nil withReplyEvent:Nil]; } - -/* - *---------------------------------------------------------------------- - * - * QuitHandler -- - * - * This is the 'quit' core Apple event handler. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static OSErr -QuitHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; KillEvent *eventPtr; - if (interp) { + if (_eventInterp) { /* * Call the exit command from the event loop, since you are not * supposed to call ExitToShell in an Apple Event Handler. We put this @@ -186,289 +67,292 @@ QuitHandler( * quickly as possible. */ - eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent)); + eventPtr = (KillEvent*)ckalloc(sizeof(KillEvent)); eventPtr->header.proc = ReallyKillMe; - eventPtr->interp = interp; + eventPtr->interp = _eventInterp; Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD); } - return noErr; } - -/* - *---------------------------------------------------------------------- - * - * OappHandler -- - * - * This is the 'oapp' core Apple event handler. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static OSErr -OappHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_CmdInfo dummy; - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; + Tcl_Interp *interp = _eventInterp; if (interp && - Tcl_GetCommandInfo(interp, "::tk::mac::OpenApplication", &dummy)){ - int code = Tcl_EvalEx(interp, "::tk::mac::OpenApplication", -1, TCL_EVAL_GLOBAL); + Tcl_FindCommand(_eventInterp, "::tk::mac::OpenApplication", NULL, 0)){ + int code = Tcl_EvalEx(_eventInterp, "::tk::mac::OpenApplication", + -1, TCL_EVAL_GLOBAL); if (code != TCL_OK) { - Tcl_BackgroundError(interp); + Tcl_BackgroundError(_eventInterp); } } - return noErr; } - -/* - *---------------------------------------------------------------------- - * - * RappHandler -- - * - * This is the 'rapp' core Apple event handler. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static OSErr -RappHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_CmdInfo dummy; - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 ProcessSerialNumber thePSN = {0, kCurrentProcess}; - OSStatus err = ChkErr(SetFrontProcess, &thePSN); - - if (interp && Tcl_GetCommandInfo(interp, - "::tk::mac::ReopenApplication", &dummy)) { - int code = Tcl_EvalEx(interp, "::tk::mac::ReopenApplication", -1, TCL_EVAL_GLOBAL); + SetFrontProcess(&thePSN); +#else + [[NSApplication sharedApplication] activateIgnoringOtherApps: YES]; +#endif + if (_eventInterp && Tcl_FindCommand(_eventInterp, + "::tk::mac::ReopenApplication", NULL, 0)) { + int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ReopenApplication", + -1, TCL_EVAL_GLOBAL); if (code != TCL_OK){ - Tcl_BackgroundError(interp); + Tcl_BackgroundError(_eventInterp); } } - return err; } - -/* - *---------------------------------------------------------------------- - * - * PrefsHandler -- - * - * This is the 'pref' core Apple event handler. Called when the user - * selects 'Preferences...' in MacOS X - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static OSErr -PrefsHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_CmdInfo dummy; - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; - - if (interp && - Tcl_GetCommandInfo(interp, "::tk::mac::ShowPreferences", &dummy)){ - int code = Tcl_EvalEx(interp, "::tk::mac::ShowPreferences", -1, TCL_EVAL_GLOBAL); + if (_eventInterp && + Tcl_FindCommand(_eventInterp, "::tk::mac::ShowPreferences", NULL, 0)){ + int code = Tcl_EvalEx(_eventInterp, "::tk::mac::ShowPreferences", + -1, TCL_EVAL_GLOBAL); if (code != TCL_OK) { - Tcl_BackgroundError(interp); + Tcl_BackgroundError(_eventInterp); } } - return noErr; } - -/* - *---------------------------------------------------------------------- - * - * OdocHandler -- - * - * This is the 'odoc' core Apple event handler. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ -static OSErr -OdocHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent { - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; - AEDescList fileSpecList; - FSRef file; - DescType type; - Size actual; - long count, index; - AEKeyword keyword; - Tcl_DString command, pathName; - Tcl_CmdInfo dummy; - int code; + tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::OpenDocument"); +} - /* - * Don't bother if we don't have an interp or the open document procedure - * doesn't exist. - */ +- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent +{ + tkMacOSXProcessFiles(event, replyEvent, _eventInterp, "::tk::mac::PrintDocument"); +} - if (!interp || - !Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) { - return noErr; - } +- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent +{ + OSStatus err; + const AEDesc *theDesc = nil; + DescType type = 0, initialType = 0; + Size actual; + int tclErr = -1; + char URLBuffer[1 + URL_MAX_LENGTH]; + char errString[128]; + char typeString[5]; /* - * If we get any errors while retrieving our parameters we just return with - * no error. + * The DoScript event receives one parameter that should be text data or a + * fileURL. */ - if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList, - &fileSpecList) != noErr) { - return noErr; + theDesc = [event aeDesc]; + if (theDesc == nil) { + return; } - if (MissedAnyParameters(event) != noErr) { - return noErr; + + err = AEGetParamPtr(theDesc, keyDirectObject, typeWildCard, &initialType, + NULL, 0, NULL); + if (err != noErr) { + sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", (int)err); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, + errString, strlen(errString)); + return; } - if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) { - return noErr; + + if (MissedAnyParameters((AppleEvent*)theDesc)) { + sprintf(errString, "AEDoScriptHandler: extra parameters"); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, + errString, strlen(errString)); + return; } - /* - * Convert our parameters into a script to evaluate, skipping things that - * we can't handle right. - */ - - Tcl_DStringInit(&command); - Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1); - for (index = 1; index <= count; index++) { - if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword, - &type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) { - continue; + if (initialType == typeFileURL || initialType == typeAlias) { + /* + * The descriptor can be coerced to a file url. Source the file, or + * pass the path as a string argument to ::tk::mac::DoScriptFile if + * that procedure exists. + */ + err = AEGetParamPtr(theDesc, keyDirectObject, typeFileURL, &type, + (Ptr) URLBuffer, URL_MAX_LENGTH, &actual); + if (err == noErr && actual > 0){ + URLBuffer[actual] = '\0'; + NSString *urlString = [NSString stringWithUTF8String:(char*)URLBuffer]; + NSURL *fileURL = [NSURL URLWithString:urlString]; + Tcl_DString command; + Tcl_DStringInit(&command); + if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptFile", NULL, 0)){ + Tcl_DStringAppend(&command, "::tk::mac::DoScriptFile", -1); + } else { + Tcl_DStringAppend(&command, "source", -1); + } + Tcl_DStringAppendElement(&command, [[fileURL path] UTF8String]); + tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command), + Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); } - - if (ChkErr(FSRefToDString, &file, &pathName) == noErr) { - Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); - Tcl_DStringFree(&pathName); + } else if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, + NULL, 0, &actual)) { + if (actual > 0) { + /* + * The descriptor can be coerced to UTF8 text. Evaluate as Tcl, or + * or pass the text as a string argument to ::tk::mac::DoScriptText + * if that procedure exists. + */ + char *data = ckalloc(actual + 1); + if (noErr == AEGetParamPtr(theDesc, keyDirectObject, typeUTF8Text, &type, + data, actual, NULL)) { + if (Tcl_FindCommand(_eventInterp, "::tk::mac::DoScriptText", NULL, 0)){ + Tcl_DString command; + Tcl_DStringInit(&command); + Tcl_DStringAppend(&command, "::tk::mac::DoScriptText", -1); + Tcl_DStringAppendElement(&command, data); + tclErr = Tcl_EvalEx(_eventInterp, Tcl_DStringValue(&command), + Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); + } else { + tclErr = Tcl_EvalEx(_eventInterp, data, actual, TCL_EVAL_GLOBAL); + } + } + ckfree(data); + } + } else { + /* + * The descriptor can not be coerced to a fileURL or UTF8 text. + */ + for (int i = 0; i < 4; i++) { + typeString[i] = ((char*)&initialType)[3-i]; } + typeString[4] = '\0'; + sprintf(errString, "AEDoScriptHandler: invalid script type '%s', " + "must be coercable to 'furl' or 'utf8'", typeString); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, errString, + strlen(errString)); } - /* - * Now handle the event by evaluating a script. + * If we ran some Tcl code, put the result in the reply. */ - - code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), - Tcl_DStringLength(&command), TCL_EVAL_GLOBAL); - if (code != TCL_OK) { - Tcl_BackgroundError(interp); + if (tclErr >= 0) { + int reslen; + const char *result = + Tcl_GetStringFromObj(Tcl_GetObjResult(_eventInterp), &reslen); + if (tclErr == TCL_OK) { + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyDirectObject, typeChar, + result, reslen); + } else { + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorString, typeChar, + result, reslen); + AEPutParamPtr((AppleEvent*)[replyEvent aeDesc], keyErrorNumber, typeSInt32, + (Ptr) &tclErr,sizeof(int)); + } } - Tcl_DStringFree(&command); - return noErr; + return; } - +@end + +#pragma mark - + /* *---------------------------------------------------------------------- * - * PrintHandler -- + * TkMacOSXProcessFiles -- * - * This is the 'pdoc' core Apple event handler. + * Extract a list of fileURLs from an AppleEvent and call the specified + * procedure with the file paths as arguments. * * Results: * None. * * Side effects: - * None. + * The event is handled by running the procedure. * *---------------------------------------------------------------------- */ -static OSErr -PrintHandler( - const AppleEvent * event, - AppleEvent * reply, - SRefCon handlerRefcon) +static void +tkMacOSXProcessFiles( + NSAppleEventDescriptor* event, + NSAppleEventDescriptor* replyEvent, + Tcl_Interp *interp, + char* procedure) { - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; - AEDescList fileSpecList; - FSRef file; + Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8"); + const AEDesc *fileSpecDesc = nil; + AEDesc contents; + char URLString[1 + URL_MAX_LENGTH]; + NSURL *fileURL; DescType type; Size actual; long count, index; AEKeyword keyword; Tcl_DString command, pathName; - Tcl_CmdInfo dummy; int code; /* - * Don't bother if we don't have an interp or the print document procedure - * doesn't exist. + * Do nothing if we don't have an interpreter or the procedure doesn't exist. */ - if (!interp || - !Tcl_GetCommandInfo(interp, "::tk::mac::PrintDocument", &dummy)) { - return noErr; + if (!interp || !Tcl_FindCommand(interp, procedure, NULL, 0)) { + return; } - + + fileSpecDesc = [event aeDesc]; + if (fileSpecDesc == nil ) { + return; + } + /* - * If we get any errors while retrieving our parameters we just return with - * no error. + * The AppleEvent's descriptor should either contain a value of + * typeObjectSpecifier or typeAEList. In the first case, the descriptor + * can be treated as a list of size 1 containing a value which can be + * coerced into a fileURL. In the second case we want to work with the list + * itself. Values in the list will be coerced into fileURL's if possible; + * otherwise they will be ignored. */ - - if (ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList, - &fileSpecList) != noErr) { - return noErr; + + /* Get a copy of the AppleEvent's descriptor. */ + AEGetParamDesc(fileSpecDesc, keyDirectObject, typeWildCard, &contents); + if (contents.descriptorType == typeAEList) { + fileSpecDesc = &contents; } - if (ChkErr(MissedAnyParameters, event) != noErr) { - return noErr; + + if (AECountItems(fileSpecDesc, &count) != noErr) { + AEDisposeDesc(&contents); + return; } - if (ChkErr(AECountItems, &fileSpecList, &count) != noErr) { - return noErr; - } - + + /* + * Construct a Tcl command which calls the procedure, passing the + * paths contained in the AppleEvent as arguments. + */ + Tcl_DStringInit(&command); - Tcl_DStringAppend(&command, "::tk::mac::PrintDocument", -1); + Tcl_DStringAppend(&command, procedure, -1); + for (index = 1; index <= count; index++) { - if (ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword, - &type, (Ptr) &file, sizeof(FSRef), &actual) != noErr) { + if (noErr != AEGetNthPtr(fileSpecDesc, index, typeFileURL, &keyword, + &type, (Ptr) URLString, URL_MAX_LENGTH, &actual)) { continue; } - - if (ChkErr(FSRefToDString, &file, &pathName) == noErr) { - Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); - Tcl_DStringFree(&pathName); + if (type != typeFileURL) { + continue; + } + URLString[actual] = '\0'; + fileURL = [NSURL URLWithString:[NSString stringWithUTF8String:(char*)URLString]]; + if (fileURL == nil) { + continue; } + Tcl_ExternalToUtfDString(utf8, [[fileURL path] UTF8String], -1, &pathName); + Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); + Tcl_DStringFree(&pathName); } + AEDisposeDesc(&contents); /* - * Now handle the event by evaluating a script. + * Handle the event by evaluating the Tcl expression we constructed. */ code = Tcl_EvalEx(interp, Tcl_DStringValue(&command), @@ -477,18 +361,19 @@ PrintHandler( Tcl_BackgroundError(interp); } Tcl_DStringFree(&command); - return noErr; + return; } /* *---------------------------------------------------------------------- * - * ScriptHandler -- + * TkMacOSXInitAppleEvents -- * - * This handler process the script event. + * Register AppleEvent handlers with the NSAppleEventManager for + * this NSApplication. * * Results: - * Schedules the given event to be processed. + * None. * * Side effects: * None. @@ -496,108 +381,91 @@ PrintHandler( *---------------------------------------------------------------------- */ -static OSErr -ScriptHandler( - const AppleEvent *event, - AppleEvent *reply, - SRefCon handlerRefcon) +void +TkMacOSXInitAppleEvents( + Tcl_Interp *interp) /* not used */ { - OSStatus theErr; - AEDescList theDesc; - Size size; - int tclErr = -1; - Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; - char errString[128]; + NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager]; + static Boolean initialized = FALSE; - /* - * The do script event receives one parameter that should be data or a - * file. - */ + if (!initialized) { + initialized = TRUE; - theErr = AEGetParamDesc(event, keyDirectObject, typeWildCard, - &theDesc); - if (theErr != noErr) { - sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", - (int)theErr); - theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); - } else if (MissedAnyParameters(event)) { - /* - * Return error if parameter is missing. - */ + [aeManager setEventHandler:NSApp + andSelector:@selector(handleQuitApplicationEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEQuitApplication]; - sprintf(errString, "AEDoScriptHandler: extra parameters"); - AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); - theErr = -1771; - } else if (theDesc.descriptorType == (DescType) typeAlias && - AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, NULL, - 0, &size) == noErr && size == sizeof(FSRef)) { - /* - * We've had a file sent to us. Source it. - */ + [aeManager setEventHandler:NSApp + andSelector:@selector(handleOpenApplicationEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEOpenApplication]; - FSRef file; - theErr = AEGetParamPtr(event, keyDirectObject, typeFSRef, NULL, &file, - size, NULL); - if (theErr == noErr) { - Tcl_DString scriptName; + [aeManager setEventHandler:NSApp + andSelector:@selector(handleReopenApplicationEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEReopenApplication]; - theErr = FSRefToDString(&file, &scriptName); - if (theErr == noErr) { - tclErr = Tcl_EvalFile(interp, Tcl_DStringValue(&scriptName)); - Tcl_DStringFree(&scriptName); - } else { - sprintf(errString, "AEDoScriptHandler: file not found"); - AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); - } - } - } else if (AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, NULL, - 0, &size) == noErr && size) { - /* - * We've had some data sent to us. Evaluate it. - */ + [aeManager setEventHandler:NSApp + andSelector:@selector(handleShowPreferencesEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEShowPreferences]; - char *data = ckalloc(size + 1); - theErr = AEGetParamPtr(event, keyDirectObject, typeUTF8Text, NULL, data, - size, NULL); - if (theErr == noErr) { - tclErr = Tcl_EvalEx(interp, data, size, TCL_EVAL_GLOBAL); - } - } else { - /* - * Umm, don't recognize what we've got... - */ + [aeManager setEventHandler:NSApp + andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEOpenDocuments]; - sprintf(errString, "AEDoScriptHandler: invalid script type '%-4.4s', " - "must be 'alis' or coercable to 'utf8'", - (char*) &theDesc.descriptorType); - AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); - theErr = -1770; + [aeManager setEventHandler:NSApp + andSelector:@selector(handleOpenDocumentsEvent:withReplyEvent:) + forEventClass:kCoreEventClass andEventID:kAEPrintDocuments]; + + [aeManager setEventHandler:NSApp + andSelector:@selector(handleDoScriptEvent:withReplyEvent:) + forEventClass:kAEMiscStandards andEventID:kAEDoScript]; } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXDoHLEvent -- + * + * Dispatch an AppleEvent. + * + * Results: + * None. + * + * Side effects: + * Depend on the AppleEvent. + * + *---------------------------------------------------------------------- + */ - /* - * If we actually go to run Tcl code - put the result in the reply. +int +TkMacOSXDoHLEvent( + void *theEvent) +{ + /* According to the NSAppleEventManager reference: + * "The theReply parameter always specifies a reply Apple event, never + * nil. However, the handler should not fill out the reply if the + * descriptor type for the reply event is typeNull, indicating the sender + * does not want a reply." + * The specified way to build such a non-nil descriptor is used here. But + * on OSX 10.11, the compiler nonetheless generates a warning. I am + * supressing the warning here -- maybe the warnings will stop in a future + * compiler release. */ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" +#endif - if (tclErr >= 0) { - int reslen; - const char *result = - Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &reslen); + NSAppleEventDescriptor* theReply = [NSAppleEventDescriptor nullDescriptor]; + NSAppleEventManager *aeManager = [NSAppleEventManager sharedAppleEventManager]; - if (tclErr == TCL_OK) { - AEPutParamPtr(reply, keyDirectObject, typeChar, result, reslen); - } else { - AEPutParamPtr(reply, keyErrorString, typeChar, result, reslen); - AEPutParamPtr(reply, keyErrorNumber, typeSInt32, (Ptr) &tclErr, - sizeof(int)); - } - } + return [aeManager dispatchRawAppleEvent:(const AppleEvent*)theEvent + withRawReply: (AppleEvent *)theReply + handlerRefCon: (SRefCon)0]; - AEDisposeDesc(&theDesc); - return theErr; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } /* @@ -616,7 +484,6 @@ ScriptHandler( * *---------------------------------------------------------------------- */ - static int ReallyKillMe( Tcl_Event *eventPtr, @@ -666,38 +533,7 @@ MissedAnyParameters( return (err != errAEDescNotFound); } - -/* - *---------------------------------------------------------------------- - * - * FSRefToDString -- - * - * Get a POSIX path from an FSRef. - * - * Results: - * In the parameter ds. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static OSStatus -FSRefToDString( - const FSRef *fsref, - Tcl_DString *ds) -{ - UInt8 fileName[PATH_MAX+1]; - OSStatus err; - err = ChkErr(FSRefMakePath, fsref, fileName, sizeof(fileName)); - if (err == noErr) { - Tcl_ExternalToUtfDString(NULL, (char*) fileName, -1, ds); - } - return err; -} - /* * Local Variables: * mode: objc diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c index c3121cb..3f4b3b5 100644 --- a/macosx/tkMacOSXMenu.c +++ b/macosx/tkMacOSXMenu.c @@ -792,7 +792,7 @@ TkpPostMenu( NSRect frame = NSMakeRect(x + 9, tkMacOSXZeroScreenHeight - y - 9, 1, 1); frame.origin = [view convertPoint: - [win convertScreenToBase:frame.origin] fromView:nil]; + [win convertPointFromScreen:frame.origin] fromView:nil]; NSMenu *menu = (NSMenu *) menuPtr->platformData; NSPopUpButtonCell *popUpButtonCell = [[NSPopUpButtonCell alloc] diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c index f4bfb44..cd3eac1 100644 --- a/macosx/tkMacOSXMouseEvent.c +++ b/macosx/tkMacOSXMouseEvent.c @@ -26,65 +26,22 @@ typedef struct { static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, - UInt32 keyModifiers); - -#pragma mark NSWindow(TKMouseEvent) - -/* Conversion of coordinates between window and screen */ -@interface NSWindow(TKWm) -- (NSPoint) convertPointToScreen:(NSPoint)point; -- (NSPoint) convertPointFromScreen:(NSPoint)point; -@end - -@implementation NSWindow(TKMouseEvent) -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 -- (NSPoint) convertPointToScreen: (NSPoint) point -{ - return [self convertBaseToScreen:point]; -} -- (NSPoint) convertPointFromScreen: (NSPoint)point -{ - return [self convertScreenToBase:point]; -} -@end -#else -- (NSPoint) convertPointToScreen: (NSPoint)point -{ - NSRect pointrect; - pointrect.origin = point; - pointrect.size.width = 0; - pointrect.size.height = 0; - return [self convertRectToScreen:pointrect].origin; -} -- (NSPoint) convertPointFromScreen: (NSPoint)point -{ - NSRect pointrect; - pointrect.origin = point; - pointrect.size.width = 0; - pointrect.size.height = 0; - return [self convertRectFromScreen:pointrect].origin; -} -@end -#endif - -#pragma mark - - + UInt32 keyModifiers); #pragma mark TKApplication(TKMouseEvent) 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. + * window attribute pointing to the active 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 the TKApplication remembers the last non-Nil + * window that it received in a mouse event. If it receives an NSEvent with a + * Nil window attribute then the saved window is used. */ @implementation TKApplication(TKMouseEvent) @@ -92,14 +49,14 @@ enum { #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, theEvent); #endif - id win; - NSEventType type = [theEvent type]; + NSWindow* eventWindow = [theEvent window]; + NSEventType eventType = [theEvent type]; #if 0 NSTrackingArea *trackingArea = nil; NSInteger eventNumber, clickCount, buttonNumber; #endif - switch (type) { + switch (eventType) { case NSMouseEntered: /* Remember which window has the mouse. */ if (_windowWithMouse) { @@ -133,25 +90,31 @@ enum { case NSTabletProximity: case NSScrollWheel: break; - default: /* Unrecognized mouse event. */ return theEvent; } + /* Remember the window in case we need it next time. */ + if (eventWindow && eventWindow != _windowWithMouse) { + if (_windowWithMouse) { + [_windowWithMouse release]; + } + _windowWithMouse = eventWindow; + [_windowWithMouse retain]; + } + /* Create an Xevent to add to the Tk queue. */ - win = [theEvent window]; - NSWindow *nswindow = (NSWindow *)win; NSPoint global, local = [theEvent locationInWindow]; - if (win) { /* local will be in window coordinates. */ - global = [nswindow convertPointToScreen: local]; - local.y = [win frame].size.height - local.y; + if (eventWindow) { /* local will be in window coordinates. */ + global = [eventWindow convertPointToScreen: local]; + local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } else { /* local will be in screen coordinates. */ if (_windowWithMouse ) { - win = _windowWithMouse; + eventWindow = _windowWithMouse; global = local; - local = [nswindow convertPointFromScreen: local]; - local.y = [win frame].size.height - local.y; + local = [eventWindow convertPointFromScreen: local]; + local.y = [eventWindow frame].size.height - local.y; global.y = tkMacOSXZeroScreenHeight - global.y; } else { /* We have no window. Use the screen???*/ local.y = tkMacOSXZeroScreenHeight - local.y; @@ -159,7 +122,7 @@ enum { } } - Window window = TkMacOSXGetXWindow(win); + Window window = TkMacOSXGetXWindow(eventWindow); Tk_Window tkwin = window ? Tk_IdToWindow(TkGetDisplayList()->display, window) : NULL; if (!tkwin) { @@ -187,7 +150,7 @@ enum { state |= (buttons & ((1<<5) - 1)) << 8; } else { if (button < 5) { - switch (type) { + switch (eventType) { case NSLeftMouseDown: case NSRightMouseDown: case NSLeftMouseDragged: @@ -224,12 +187,12 @@ enum { state |= Mod4Mask; } - if (type != NSScrollWheel) { + if (eventType != NSScrollWheel) { #ifdef TK_MAC_DEBUG_EVENTS TKLog(@"UpdatePointer %p x %f.0 y %f.0 %d", tkwin, global.x, global.y, state); #endif Tk_UpdatePointer(tkwin, global.x, global.y, state); - } else { + } else { /* handle scroll wheel event */ CGFloat delta; int coarseDelta; XEvent xEvent; @@ -245,7 +208,8 @@ enum { delta = [theEvent deltaY]; if (delta != 0.0) { - coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta); + coarseDelta = (delta > -1.0 && delta < 1.0) ? + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -253,7 +217,8 @@ enum { } delta = [theEvent deltaX]; if (delta != 0.0) { - coarseDelta = (delta > -1.0 && delta < 1.0) ? (signbit(delta) ? -1 : 1) : lround(delta); + coarseDelta = (delta > -1.0 && delta < 1.0) ? + (signbit(delta) ? -1 : 1) : lround(delta); xEvent.xbutton.state = state | ShiftMask; xEvent.xkey.keycode = coarseDelta; xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); @@ -424,7 +389,7 @@ XQueryPointer( if (win) { NSPoint local; - local = [win convertScreenToBase:global]; + local = [win convertPointFromScreen:global]; local.y = [win frame].size.height - local.y; if (macWin->winPtr && macWin->winPtr->wmInfoPtr) { local.x -= macWin->winPtr->wmInfoPtr->xInParent; @@ -522,7 +487,7 @@ TkGenerateButtonEvent( if (win) { NSPoint local = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); - local = [win convertScreenToBase:local]; + local = [win convertPointFromScreen:local]; local.y = [win frame].size.height - local.y; if (macWin->winPtr && macWin->winPtr->wmInfoPtr) { local.x -= macWin->winPtr->wmInfoPtr->xInParent; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 4f96f64..4891b32 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -294,6 +294,24 @@ VISIBILITY_HIDDEN - (void)tkProvidePasteboard:(TkDisplay *)dispPtr; - (void)tkCheckPasteboard; @end +@interface TKApplication(TKHLEvents) +- (void) terminate: (id) sender; +- (void) preferences: (id) sender; +- (void) handleQuitApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handleOpenApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handleReopenApplicationEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handleShowPreferencesEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handleOpenDocumentsEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handlePrintDocumentsEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +- (void) handleDoScriptEvent: (NSAppleEventDescriptor *)event + withReplyEvent: (NSAppleEventDescriptor *)replyEvent; +@end VISIBILITY_HIDDEN @interface TKContentView : NSView { @@ -327,6 +345,11 @@ VISIBILITY_HIDDEN @interface TKWindow : NSWindow @end +@interface NSWindow(TKWm) +- (NSPoint) convertPointToScreen:(NSPoint)point; +- (NSPoint) convertPointFromScreen:(NSPoint)point; +@end + #pragma mark NSMenu & NSMenuItem Utilities @interface NSMenu(TKUtils) @@ -355,9 +378,4 @@ VISIBILITY_HIDDEN keyEquivalentModifierMask:(NSUInteger)keyEquivalentModifierMask; @end - -/* Helper functions from tkMacOSXDeprecations.c */ - -extern NSPoint convertWindowToScreen( NSWindow *window, NSPoint point); - #endif /* _TKMACPRIV */ diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index c028a75..0b32e7e 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -747,15 +747,16 @@ TkWmProtocolEventProc( int Tk_MacOSXIsAppInFront(void) { - OSStatus err; - ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess}; Boolean isFrontProcess = true; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + ProcessSerialNumber frontPsn, ourPsn = {0, kCurrentProcess}; - err = ChkErr(GetFrontProcess, &frontPsn); - if (err == noErr) { - ChkErr(SameProcess, &frontPsn, &ourPsn, &isFrontProcess); + if (noErr == GetFrontProcess(&frontPsn)){ + SameProcess(&frontPsn, &ourPsn, &isFrontProcess); } - +#else + isFrontProcess = [NSRunningApplication currentApplication].active; +#endif return (isFrontProcess == true); } diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 241d70a..69d3cfb 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -200,6 +200,48 @@ static int tkMacOSXWmAttrNotifyVal = 0; static Tcl_HashTable windowTable; static int windowHashInit = false; + + +#pragma mark NSWindow(TKWm) + +/* + * Conversion of coordinates between window and screen. + */ + +@implementation NSWindow(TKWm) +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 +- (NSPoint) convertPointToScreen: (NSPoint) point +{ + return [self convertBaseToScreen:point]; +} +- (NSPoint) convertPointFromScreen: (NSPoint)point +{ + return [self convertScreenToBase:point]; +} +@end +#else +- (NSPoint) convertPointToScreen: (NSPoint) point +{ + NSRect pointrect; + pointrect.origin = point; + pointrect.size.width = 0; + pointrect.size.height = 0; + return [self convertRectToScreen:pointrect].origin; +} +- (NSPoint) convertPointFromScreen: (NSPoint)point +{ + NSRect pointrect; + pointrect.origin = point; + pointrect.size.width = 0; + pointrect.size.height = 0; + return [self convertRectFromScreen:pointrect].origin; +} +@end +#endif + +#pragma mark - + + /* * Forward declarations for procedures defined in this file: */ diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 2b9783d..f8adf1e 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -181,7 +181,21 @@ TkpOpenDisplay( NSAppKitVersionNumber); } display->vendor = vendor; - Gestalt(gestaltSystemVersion, (SInt32 *) &display->release); + { + int major, minor, patch; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 + Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); + Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); + Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); +#else + NSOperatingSystemVersion systemVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; + major = systemVersion.majorVersion; + minor = systemVersion.minorVersion; + patch = systemVersion.patchVersion; +#endif + display->release = major << 16 | minor << 8 | patch; + } /* * These screen bits never change -- cgit v0.12 From 510e1a4afed492f79e94a67224a0823158aa1db2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 26 Nov 2015 13:55:28 +0000 Subject: On cygwin, install libtk8.5.dll.a in the {prefix}/lib directory. --- unix/configure | 2 +- unix/tcl.m4 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/configure b/unix/configure index afd5bff..1be3cb8 100755 --- a/unix/configure +++ b/unix/configure @@ -7086,7 +7086,7 @@ fi MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' if test "${SHLIB_SUFFIX}" = ".dll"; then - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" else diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 4b9543c..3005321 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -2069,7 +2069,7 @@ dnl # preprocessing tests use only CPPFLAGS. LIB_SUFFIX=${SHARED_LIB_SUFFIX} MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [ - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' + INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)";if test -f $(LIB_FILE).a; then $(INSTALL_DATA) $(LIB_FILE).a "$(LIB_INSTALL_DIR)"; fi;' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" ], [ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' -- cgit v0.12