From a180f18ae3f3ada9c56d86479135d64d4c8eae6e Mon Sep 17 00:00:00 2001 From: "petasisg@gmail.com" Date: Wed, 13 Aug 2014 18:33:48 +0000 Subject: OSX updates --- CMakeLists.txt | 9 +- Changelog | 13 ++ demos/complex_source.tcl | 4 +- demos/simple_source.tcl | 2 +- library/tkdnd.tcl | 11 +- library/tkdnd_macosx.tcl | 87 ++++++++---- library/tkdnd_unix.tcl | 41 ++++-- library/tkdnd_windows.tcl | 11 +- macosx/macdnd.m | 337 ++++++++++++++++++++++++++++++++++++---------- 9 files changed, 390 insertions(+), 125 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2906567..96064d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ CMAKE_MINIMUM_REQUIRED ( VERSION 2.6 ) -CMAKE_POLICY ( SET CMP0042 NEW ) +IF ( POLICY CMP0042 ) + CMAKE_POLICY ( SET CMP0042 NEW ) +ENDIF ( POLICY CMP0042 ) ## Ensure that the variable PKG_OS_ARCH exists! If undefined, define it with ## the value "x86_32" @@ -47,11 +49,12 @@ ELSE ( WIN32 ) INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) ADD_DEFINITIONS ( -DMAC_TK_COCOA -DMAC_OSX_TK) + ADD_DEFINITIONS ( -DMAC_OSX_TK ) ADD_DEFINITIONS ( -std=gnu99 ) ADD_DEFINITIONS ( -x objective-c ) -# ADD_DEFINITIONS ( -fobjc-gc ) + ADD_DEFINITIONS ( -fobjc-gc ) + ADD_DEFINITIONS ( -fno-objc-arc ) # ADD_DEFINITIONS ( -fobjc-arc ) -# ADD_DEFINITIONS ( -fno-objc-arc ) LINK_LIBRARIES ( ${COCOA_LIBRARY} ) SET ( PKG_SOURCES macosx/macdnd.m ) ELSE ( APPLE ) diff --git a/Changelog b/Changelog index f17ab84..5d6b345 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,16 @@ +2014-08-13 Petasis George + * library/tkdnd_windows.tcl: + * library/tkdnd.tcl: + * library/tkdnd_unix.tcl: + * library/tkdnd_macosx.tcl: + * macosx/macdnd.m: Added support for complex sources under OS X. + + * CMakeLists.txt: A few fixes for OS X. + + * demos/complex_source.tcl: + * demos/simple_source.tcl: Ensure returned paths are absolute (to avoid + warnings under OS X). + 2014-08-06 Petasis George * library/tkdnd_unix.tcl: Added support for sources with multiple and (incompatible) types under Unix. Completed implementation started diff --git a/demos/complex_source.tcl b/demos/complex_source.tcl index 3255ea8..717231b 100644 --- a/demos/complex_source.tcl +++ b/demos/complex_source.tcl @@ -1,5 +1,6 @@ package require tkdnd catch {console show} +set filename [file normalize [info script]] ## ## Drag source @@ -16,7 +17,7 @@ proc my_data {} { list copy [list \ DND_HTML {

Some nice HTML text!

} \ DND_Text {Some nice dropped text!} \ - DND_Files [list /tmp/some_nice_dropped_file] \ + DND_Files [list $::filename $::filename] \ ] };# my_data @@ -36,4 +37,5 @@ foreach type {DND_HTML DND_Text DND_Files} { bind $w <> {%W state active} bind $w <> {%W state !active} bind $w <> [list my_drop %W %CPT %D %A] + # bind $w <> {puts "Common types: %CTT"; return copy} } diff --git a/demos/simple_source.tcl b/demos/simple_source.tcl index 53b0df3..2cff6d3 100644 --- a/demos/simple_source.tcl +++ b/demos/simple_source.tcl @@ -10,7 +10,7 @@ tkdnd::drag_source register .drag_source_text DND_Text tkdnd::drag_source register .drag_source_files DND_Files ## Event <> -set filename [info script] +set filename [file normalize [info script]] bind .drag_source_text <> \ {list copy DND_Text {Some nice dropped text!}} bind .drag_source_files <> \ diff --git a/library/tkdnd.tcl b/library/tkdnd.tcl index 0fbf3db..d15f622 100644 --- a/library/tkdnd.tcl +++ b/library/tkdnd.tcl @@ -157,6 +157,7 @@ namespace eval tkdnd { } load $dir/$PKG_LIB_FILE $PACKAGE_NAME source $dir/tkdnd_compat.tcl + ${_platform_namespace}::initialise };# initialise proc GetDropFileTempDirectory { } { @@ -325,7 +326,7 @@ proc tkdnd::_init_drag { button source state rootX rootY } { set action [_DoDragDrop $source $actions $types $data $button] } aqua { - set action [macdnd::dodragdrop $source $actions $types $data] + set action [macdnd::dodragdrop $source $actions $types $data $button] } default { error "unknown Tk windowing system" @@ -381,7 +382,7 @@ proc tkdnd::_end_drag { button source target action type data result # ---------------------------------------------------------------------------- proc tkdnd::platform_specific_types { types } { variable _platform_namespace - return [${_platform_namespace}::_platform_specific_types $types] + ${_platform_namespace}::_platform_specific_types $types }; # tkdnd::platform_specific_types # ---------------------------------------------------------------------------- @@ -389,7 +390,7 @@ proc tkdnd::platform_specific_types { types } { # ---------------------------------------------------------------------------- proc tkdnd::platform_independent_types { types } { variable _platform_namespace - return [${_platform_namespace}::_platform_independent_types $types] + ${_platform_namespace}::_platform_independent_types $types }; # tkdnd::platform_independent_types # ---------------------------------------------------------------------------- @@ -397,7 +398,7 @@ proc tkdnd::platform_independent_types { types } { # ---------------------------------------------------------------------------- proc tkdnd::platform_specific_type { type } { variable _platform_namespace - return [${_platform_namespace}::_platform_specific_type $type] + ${_platform_namespace}::_platform_specific_type $type }; # tkdnd::platform_specific_type # ---------------------------------------------------------------------------- @@ -405,7 +406,7 @@ proc tkdnd::platform_specific_type { type } { # ---------------------------------------------------------------------------- proc tkdnd::platform_independent_type { type } { variable _platform_namespace - return [${_platform_namespace}::_platform_independent_type $type] + ${_platform_namespace}::_platform_independent_type $type }; # tkdnd::platform_independent_type # ---------------------------------------------------------------------------- diff --git a/library/tkdnd_macosx.tcl b/library/tkdnd_macosx.tcl index a610d05..ce1b224 100644 --- a/library/tkdnd_macosx.tcl +++ b/library/tkdnd_macosx.tcl @@ -1,6 +1,6 @@ # # tkdnd_macosx.tcl -- -# +# # This file implements some utility procedures that are used by the TkDND # package. @@ -24,13 +24,13 @@ # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. -# +# # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -# +# # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE @@ -53,27 +53,42 @@ if {[tk windowingsystem] eq "aqua" && "AppKit" ni [winfo server .]} { namespace eval macdnd { variable _dropped_data + + + proc initialise {} { + variable _tkdnd2platform + variable _platform2tkdnd + + ## Initialize the tkdnd 2 platform & platform 2 tkdnd arrays for type conversion... + array set _platform2tkdnd [list \ + NSPasteboardTypeString DND_Text \ + NSFilenamesPboardType DND_Files \ + ] + foreach type [array names _platform2tkdnd] { + lappend _tkdnd2platform($_platform2tkdnd($type)) $type + } + };# initialise };# namespace macdnd # ---------------------------------------------------------------------------- # Command macdnd::_HandleEnter # ---------------------------------------------------------------------------- proc macdnd::_HandleEnter { path drag_source typelist } { - return [::tkdnd::xdnd::_HandleXdndEnter $path $drag_source $typelist] + ::tkdnd::xdnd::_HandleXdndEnter $path $drag_source $typelist };# macdnd::_HandleEnter # ---------------------------------------------------------------------------- -# Command macdnd::_HandlePosition +# Command macdnd::_HandlePosition # ---------------------------------------------------------------------------- proc macdnd::_HandlePosition { drop_target rootX rootY } { - return [::tkdnd::xdnd::_HandleXdndPosition $drop_target $rootX $rootY] + ::tkdnd::xdnd::_HandleXdndPosition $drop_target $rootX $rootY };# macdnd::_HandlePosition # ---------------------------------------------------------------------------- # Command macdnd::_HandleLeave # ---------------------------------------------------------------------------- proc macdnd::_HandleLeave { args } { - return [::tkdnd::xdnd::_HandleXdndLeave] + ::tkdnd::xdnd::_HandleXdndLeave };# macdnd::_HandleLeave # ---------------------------------------------------------------------------- @@ -82,7 +97,7 @@ proc macdnd::_HandleLeave { args } { proc macdnd::_HandleDrop { drop_target data args } { variable _dropped_data set _dropped_data $data - return [::tkdnd::xdnd::_HandleXdndDrop 0] + ::tkdnd::xdnd::_HandleXdndDrop 0 };# macdnd::_HandleDrop # ---------------------------------------------------------------------------- @@ -90,81 +105,99 @@ proc macdnd::_HandleDrop { drop_target data args } { # ---------------------------------------------------------------------------- proc macdnd::_GetDroppedData { time } { variable _dropped_data - return $_dropped_data + return $_dropped_data };# macdnd::_GetDroppedData proc xdnd::_GetDroppedData { time } { - return [::tkdnd::macdnd::_GetDroppedData $time] + ::tkdnd::macdnd::_GetDroppedData $time };# xdnd::_GetDroppedData # ---------------------------------------------------------------------------- # Command macdnd::_GetDragSource # ---------------------------------------------------------------------------- proc macdnd::_GetDragSource { } { - return [::tkdnd::xdnd::_GetDragSource] + ::tkdnd::xdnd::_GetDragSource };# macdnd::_GetDragSource # ---------------------------------------------------------------------------- # Command macdnd::_GetDropTarget # ---------------------------------------------------------------------------- proc macdnd::_GetDropTarget { } { - return [::tkdnd::xdnd::_GetDropTarget] + ::tkdnd::xdnd::_GetDropTarget };# macdnd::_GetDropTarget # ---------------------------------------------------------------------------- +# Command macdnd::_GetDragSourceCommonTypes +# ---------------------------------------------------------------------------- +proc macdnd::_GetDragSourceCommonTypes { } { + ::tkdnd::xdnd::_GetDragSourceCommonTypes +};# macdnd::_GetDragSourceCommonTypes + +# ---------------------------------------------------------------------------- +# Command macdnd::_GetDropTargetCommonTypes +# ---------------------------------------------------------------------------- +proc macdnd::_GetDropTargetCommonTypes { } { + ::tkdnd::xdnd::_GetDropTargetCommonTypes +};# macdnd::_GetDropTargetCommonTypes + +# ---------------------------------------------------------------------------- # Command macdnd::_supported_types # ---------------------------------------------------------------------------- proc macdnd::_supported_types { types } { - return [::tkdnd::xdnd::_supported_types $types] + ::tkdnd::xdnd::_supported_types $types }; # macdnd::_supported_types # ---------------------------------------------------------------------------- # Command macdnd::_platform_specific_types # ---------------------------------------------------------------------------- proc macdnd::_platform_specific_types { types } { - return [::tkdnd::xdnd::_platform_specific_types $types] + ::tkdnd::xdnd::_platform_specific_types $types }; # macdnd::_platform_specific_types # ---------------------------------------------------------------------------- # Command macdnd::_normalise_data # ---------------------------------------------------------------------------- proc macdnd::_normalise_data { type data } { - return [::tkdnd::xdnd::_normalise_data $type $data] + ::tkdnd::xdnd::_normalise_data $type $data }; # macdnd::_normalise_data # ---------------------------------------------------------------------------- # Command macdnd::_platform_specific_type # ---------------------------------------------------------------------------- proc macdnd::_platform_specific_type { type } { - switch $type { - DND_Text {return [list NSStringPboardType]} - DND_Files {return [list NSFilenamesPboardType]} - default {return [list $type]} + variable _tkdnd2platform + if {[info exists _tkdnd2platform($type)]} { + return $_tkdnd2platform($type) } + list $type }; # macdnd::_platform_specific_type proc xdnd::_platform_specific_type { type } { - return [::tkdnd::macdnd::_platform_specific_type $type] + ::tkdnd::macdnd::_platform_specific_type $type }; # xdnd::_platform_specific_type # ---------------------------------------------------------------------------- # Command macdnd::_platform_independent_type # ---------------------------------------------------------------------------- proc macdnd::_platform_independent_type { type } { - switch $type { - NSStringPboardType {return DND_Text} - NSFilenamesPboardType {return DND_Files} - default {return [list $type]} + variable _platform2tkdnd + if {[info exists _platform2tkdnd($type)]} { + return $_platform2tkdnd($type) } + return $type }; # macdnd::_platform_independent_type proc xdnd::_platform_independent_type { type } { - return [::tkdnd::macdnd::_platform_independent_type $type] + ::tkdnd::macdnd::_platform_independent_type $type }; # xdnd::_platform_independent_type # ---------------------------------------------------------------------------- # Command macdnd::_supported_type # ---------------------------------------------------------------------------- proc macdnd::_supported_type { type } { - return 1 + variable _platform2tkdnd + if {[info exists _platform2tkdnd($type)]} { + return 1 + } + return 0 }; # macdnd::_supported_type proc xdnd::_supported_type { type } { - return [::tkdnd::macdnd::_supported_type $type] + ::tkdnd::macdnd::_supported_type $type }; # xdnd::_supported_type diff --git a/library/tkdnd_unix.tcl b/library/tkdnd_unix.tcl index 4d70eb0..38cb4bf 100644 --- a/library/tkdnd_unix.tcl +++ b/library/tkdnd_unix.tcl @@ -1,6 +1,6 @@ # # tkdnd_unix.tcl -- -# +# # This file implements some utility procedures that are used by the TkDND # package. # @@ -21,13 +21,13 @@ # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. -# +# # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -# +# # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE @@ -56,6 +56,9 @@ namespace eval xdnd { proc debug {msg} { puts $msg };# debug + + proc initialise { } { + };# initialise };# namespace xdnd # ---------------------------------------------------------------------------- @@ -114,7 +117,7 @@ proc xdnd::_HandleXdndPosition { drop_target rootX rootY {drag_source {}} } { return refuse_drop } - ## Does the new drop target support any of our new types? + ## Does the new drop target support any of our new types? set _types [bind $drop_target <>] # debug ">> Accepted types: $drop_target $_types" if {[llength $_types]} { @@ -129,7 +132,7 @@ proc xdnd::_HandleXdndPosition { drop_target rootX rootY {drag_source {}} } { } } } - + # debug "\t($_drop_target) -> ($drop_target)" if {$drop_target != $_drop_target} { if {[string length $_drop_target]} { @@ -183,7 +186,7 @@ proc xdnd::_HandleXdndPosition { drop_target rootX rootY {drag_source {}} } { } set _drop_target $drop_target } - + set _action refuse_drop set _drop_target {} if {[info exists common_drag_source_types]} { @@ -380,7 +383,7 @@ proc xdnd::_GetDroppedData { time } { # ---------------------------------------------------------------------------- proc xdnd::_GetDragSource { } { variable _drag_source - return $_drag_source + return $_drag_source };# xdnd::_GetDragSource # ---------------------------------------------------------------------------- @@ -395,6 +398,22 @@ proc xdnd::_GetDropTarget { } { };# xdnd::_GetDropTarget # ---------------------------------------------------------------------------- +# Command xdnd::_GetDragSourceCommonTypes +# ---------------------------------------------------------------------------- +proc xdnd::_GetDragSourceCommonTypes { } { + variable _common_drag_source_types + return $_common_drag_source_types +};# xdnd::_GetDragSourceCommonTypes + +# ---------------------------------------------------------------------------- +# Command xdnd::_GetDropTargetCommonTypes +# ---------------------------------------------------------------------------- +proc xdnd::_GetDropTargetCommonTypes { } { + variable _common_drag_source_types + return $_common_drag_source_types +};# xdnd::_GetDropTargetCommonTypes + +# ---------------------------------------------------------------------------- # Command xdnd::_supported_types # ---------------------------------------------------------------------------- proc xdnd::_supported_types { types } { @@ -423,7 +442,7 @@ proc xdnd::_normalise_data { type data } { # Tk knows how to interpret the following types: # STRING, TEXT, COMPOUND_TEXT # UTF8_STRING - # Else, it returns a list of 8 or 32 bit numbers... + # Else, it returns a list of 8 or 32 bit numbers... switch -glob $type { STRING - UTF8_STRING - TEXT - COMPOUND_TEXT {return $data} text/html - @@ -459,7 +478,7 @@ proc xdnd::_normalise_data { type data } { application/x-color { return $data } - text/x-moz-url - + text/x-moz-url - application/q-iconlist - default {return $data} } @@ -636,7 +655,7 @@ proc xdnd::_process_drag_events {event} { ## Examine the modifiers to suggest an action... set _dodragdrop_default_action [_default_action $event] ## Is it a Tk widget? - # set path [winfo containing $rootx $rooty] + # set path [winfo containing $rootx $rooty] # puts "Window under mouse: $window ($path)" if {$_dodragdrop_drop_target != $window} { ## Send XdndLeave to $_dodragdrop_drop_target @@ -867,7 +886,7 @@ proc xdnd::_default_action {event} { variable _dodragdrop_actions variable _dodragdrop_actions_len if {$_dodragdrop_actions_len == 1} {return [lindex $_dodragdrop_actions 0]} - + set alt [dict get $event Alt] set shift [dict get $event Shift] set control [dict get $event Control] diff --git a/library/tkdnd_windows.tcl b/library/tkdnd_windows.tcl index 9533f0f..b1a8268 100644 --- a/library/tkdnd_windows.tcl +++ b/library/tkdnd_windows.tcl @@ -1,6 +1,6 @@ # # tkdnd_windows.tcl -- -# +# # This file implements some utility procedures that are used by the TkDND # package. # @@ -21,13 +21,13 @@ # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. -# +# # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -# +# # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE @@ -49,6 +49,9 @@ namespace eval olednd { variable _last_mouse_root_x 0 variable _last_mouse_root_y 0 + + proc initialise { } { + };# initialise };# namespace olednd # ---------------------------------------------------------------------------- @@ -72,7 +75,7 @@ proc olednd::_HandleDragEnter { drop_target typelist actionlist pressedkeys # pressedkeys=$pressedkeys, rootX=$rootX, rootY=$rootY" focus $drop_target - ## Does the new drop target support any of our new types? + ## Does the new drop target support any of our new types? variable _types; set _types [bind $drop_target <>] if {[llength $_types]} { ## Examine the drop target types, to find at least one match with the drag diff --git a/macosx/macdnd.m b/macosx/macdnd.m index da1d283..1745d5b 100644 --- a/macosx/macdnd.m +++ b/macosx/macdnd.m @@ -19,6 +19,8 @@ #import #import +#pragma clang diagnostic ignored "-Warc-bridge-casts-disallowed-in-nonarc" +#if 0 // not using clang LLVM compiler, or LLVM version is not 3.x #if !defined(__clang__) || __clang_major__ < 3 @@ -44,6 +46,8 @@ #define __unsafe_unretained #endif +#endif + #endif // __clang_major__ < 3 #define TKDND_OSX_KEVIN_WORKARROUND @@ -80,16 +84,15 @@ Tcl_Interp * TkDND_Interp(Tk_Window tkwin) { #define Tk_Interp TkDND_Interp #endif /* Tk_Interp */ - /* * Here we need to wrap Cocoa methods in Cocoa class: methods for initiating, * tracking, and terminating drag from inside and outside the application. */ @interface DNDView : NSView { - NSDragOperation sourceDragMask; - NSPasteboard *sourcePasteBoard; - NSMutableArray *draggedtypes; +// NSDragOperation sourceDragMask; +// NSPasteboard *sourcePasteBoard; +// NSMutableArray *draggedtypes; NSInteger tag; } @@ -100,7 +103,7 @@ Tcl_Interp * TkDND_Interp(Tk_Window tkwin) { - (int)draggingSourceOperationMaskForLocal:(BOOL)isLocal; - (void)setTag:(NSInteger) t; - (NSInteger)tag; -TkWindow* TkMacOSXGetTkWindow( NSWindow *w); +Tk_Window TkMacOSXGetTkWindow(NSWindow *w); DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin); @end @@ -117,12 +120,11 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin); /* * Ripped from Tk-Cocoa source code to map Tk window to Cocoa window */ -TkWindow* TkMacOSXGetTkWindow(NSWindow *w) { +Tk_Window TkMacOSXGetTkWindow(NSWindow *w) { Window window = TkMacOSXGetXWindow((__bridge void*)w); TkDisplay *dispPtr = TkGetDisplayList(); - return (window != None ? (TkWindow *)Tk_IdToWindow(dispPtr->display, window) : - NULL); + return (window != None ? Tk_IdToWindow(dispPtr->display, window) : NULL); }; /* TkMacOSXGetTkWindow */ /* @@ -185,6 +187,122 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { return NSDragOperationCopy|NSDragOperationMove|NSDragOperationLink; } +/* + * Convert from strings to OS X type NSString objects... + */ +const NSString *TKDND_Obj2NSString(Tcl_Interp *interp, Tcl_Obj *obj) { + int index, status; + NSString *str = NULL; + static char *OSXTypes[] = { + /* OS X v10.6 and later */ + "NSPasteboardTypeString", + "NSPasteboardTypePDF", + "NSPasteboardTypeTIFF", + "NSPasteboardTypePNG", + "NSPasteboardTypeRTF", + "NSPasteboardTypeRTFD", + "NSPasteboardTypeHTML", + "NSPasteboardTypeTabularText", + "NSPasteboardTypeFont", + "NSPasteboardTypeRuler", + "NSPasteboardTypeColor", + "NSPasteboardTypeSound", + "NSPasteboardTypeMultipleTextSelection", + "NSPasteboardTypeFindPanelSearchOptions", + /* OS X v10.5 and earlier */ + "NSStringPboardType", + "NSFilenamesPboardType", + "NSPostScriptPboardType", + "NSTIFFPboardType", + "NSRTFPboardType", + "NSTabularTextPboardType", + "NSFontPboardType", + "NSRulerPboardType", + "NSFileContentsPboardType", + "NSColorPboardType", + "NSRTFDPboardType", + "NSHTMLPboardType", + "NSURLPboardType", + "NSPDFPboardType", + "NSVCardPboardType", + "NSFilesPromisePboardType", + "NSMultipleTextSelectionPboardType", + (char *) NULL + }; + enum osxtypes { + /* OS X v10.6 and later */ + TYPE_NSPasteboardTypeString, + TYPE_NSPasteboardTypePDF, + TYPE_NSPasteboardTypeTIFF, + TYPE_NSPasteboardTypePNG, + TYPE_NSPasteboardTypeRTF, + TYPE_NSPasteboardTypeRTFD, + TYPE_NSPasteboardTypeHTML, + TYPE_NSPasteboardTypeTabularText, + TYPE_NSPasteboardTypeFont, + TYPE_NSPasteboardTypeRuler, + TYPE_NSPasteboardTypeColor, + TYPE_NSPasteboardTypeSound, + TYPE_NSPasteboardTypeMultipleTextSelection, + TYPE_NSPasteboardTypeFindPanelSearchOptions, + /* OS X v10.5 and earlier */ + TYPE_NSStringPboardType, + TYPE_NSFilenamesPboardType, + TYPE_NSPostScriptPboardType, + TYPE_NSTIFFPboardType, + TYPE_NSRTFPboardType, + TYPE_NSTabularTextPboardType, + TYPE_NSFontPboardType, + TYPE_NSRulerPboardType, + TYPE_NSFileContentsPboardType, + TYPE_NSColorPboardType, + TYPE_NSRTFDPboardType, + TYPE_NSHTMLPboardType, + TYPE_NSURLPboardType, + TYPE_NSPDFPboardType, + TYPE_NSVCardPboardType, + TYPE_NSFilesPromisePboardType, + TYPE_NSMultipleTextSelectionPboardType, + }; + status = Tcl_GetIndexFromObj(interp, obj, (const char **) OSXTypes, + "osxtypes", 0, &index); + if (status != TCL_OK) return NULL; + switch ((enum osxtypes) index) { + case TYPE_NSPasteboardTypeString: {str = NSPasteboardTypeString ; break;} + case TYPE_NSPasteboardTypePDF: {str = NSPasteboardTypePDF ; break;} + case TYPE_NSPasteboardTypeTIFF: {str = NSPasteboardTypeTIFF ; break;} + case TYPE_NSPasteboardTypePNG: {str = NSPasteboardTypePNG ; break;} + case TYPE_NSPasteboardTypeRTF: {str = NSPasteboardTypeRTF ; break;} + case TYPE_NSPasteboardTypeRTFD: {str = NSPasteboardTypeRTFD ; break;} + case TYPE_NSPasteboardTypeHTML: {str = NSPasteboardTypeHTML ; break;} + case TYPE_NSPasteboardTypeTabularText: {str = NSPasteboardTypeTabularText ; break;} + case TYPE_NSPasteboardTypeFont: {str = NSPasteboardTypeFont ; break;} + case TYPE_NSPasteboardTypeRuler: {str = NSPasteboardTypeRuler ; break;} + case TYPE_NSPasteboardTypeColor: {str = NSPasteboardTypeColor ; break;} + case TYPE_NSPasteboardTypeSound: {str = NSPasteboardTypeSound ; break;} + case TYPE_NSPasteboardTypeMultipleTextSelection: {str = NSPasteboardTypeMultipleTextSelection ; break;} + case TYPE_NSPasteboardTypeFindPanelSearchOptions: {str = NSPasteboardTypeFindPanelSearchOptions; break;} + case TYPE_NSStringPboardType: {str = NSStringPboardType ; break;} + case TYPE_NSFilenamesPboardType: {str = NSFilenamesPboardType ; break;} + case TYPE_NSPostScriptPboardType: {str = NSPostScriptPboardType ; break;} + case TYPE_NSTIFFPboardType: {str = NSTIFFPboardType ; break;} + case TYPE_NSRTFPboardType: {str = NSRTFPboardType ; break;} + case TYPE_NSTabularTextPboardType: {str = NSTabularTextPboardType ; break;} + case TYPE_NSFontPboardType: {str = NSFontPboardType ; break;} + case TYPE_NSRulerPboardType: {str = NSRulerPboardType ; break;} + case TYPE_NSFileContentsPboardType: {str = NSFileContentsPboardType ; break;} + case TYPE_NSColorPboardType: {str = NSColorPboardType ; break;} + case TYPE_NSRTFDPboardType: {str = NSRTFDPboardType ; break;} + case TYPE_NSHTMLPboardType: {str = NSHTMLPboardType ; break;} + case TYPE_NSURLPboardType: {str = NSURLPboardType ; break;} + case TYPE_NSPDFPboardType: {str = NSPDFPboardType ; break;} + case TYPE_NSVCardPboardType: {str = NSVCardPboardType ; break;} + case TYPE_NSFilesPromisePboardType: {str = NSFilesPromisePboardType ; break;} + case TYPE_NSMultipleTextSelectionPboardType: {str = NSMultipleTextSelectionPboardType ; break;} + } + return str; +}; /* TKDND_Obj2NSString */ + /******************************************************************************* ******************************************************************************* ***** Drop Target Operations ***** @@ -205,10 +323,9 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { refuse_drop, ActionDefault }; - TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - Tk_Window tkwin = (Tk_Window) winPtr; - Tcl_Interp *interp = Tk_Interp(tkwin); - sourcePasteBoard = [sender draggingPasteboard]; + Tk_Window tkwin = TkMacOSXGetTkWindow([self window]); + Tcl_Interp *interp = Tk_Interp(tkwin); + NSPasteboard *sourcePasteBoard = [sender draggingPasteboard]; Tcl_Obj* objv[4], *element, *result; int i, index, status; @@ -220,8 +337,8 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { /* * Search for known types... */ - if ([[sourcePasteBoard types] containsObject:NSStringPboardType]) { - element = Tcl_NewStringObj("NSStringPboardType", -1); + if ([[sourcePasteBoard types] containsObject:NSPasteboardTypeString]) { + element = Tcl_NewStringObj("NSPasteboardTypeString", -1); Tcl_ListObjAppendElement(NULL, objv[3], element); } if ([[sourcePasteBoard types] containsObject:NSFilenamesPboardType]) { @@ -272,10 +389,9 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { Tk_Window mouse_tkwin; NSPoint mouseLoc; - TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - Tk_Window tkwin = (Tk_Window) winPtr; - Tcl_Interp *interp = Tk_Interp(tkwin); - sourcePasteBoard = [sender draggingPasteboard]; + Tk_Window tkwin = TkMacOSXGetTkWindow([self window]); + Tcl_Interp *interp = Tk_Interp(tkwin); + NSPasteboard *sourcePasteBoard = [sender draggingPasteboard]; /* Get the coordinates of the cursor... */ mouseLoc = [NSEvent mouseLocation]; @@ -336,7 +452,7 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { //prepare to perform drag operation - (BOOL)prepareForDragOperation:(id )sender { - sourcePasteBoard = [sender draggingPasteboard]; + // sourcePasteBoard = [sender draggingPasteboard]; return YES; }; /* prepareForDragOperation */ @@ -353,40 +469,74 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { ActionCopy, ActionMove, ActionLink, ActionAsk, ActionPrivate, refuse_drop, ActionDefault, NoReturnedAction }; - TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - Tk_Window tkwin = (Tk_Window) winPtr; - Tcl_Interp *interp = Tk_Interp(tkwin); - sourcePasteBoard = [sender draggingPasteboard]; + Tk_Window tkwin = TkMacOSXGetTkWindow([self window]); + Tcl_Interp *interp = Tk_Interp(tkwin); + NSPasteboard *sourcePasteBoard = [sender draggingPasteboard]; Tcl_Obj *data = NULL; + Tcl_Obj* objv[3], **elem, *result; + int i, index, status, elem_nu; + const NSString *type; + + /* Retrieve the common types, as prefered by the drag source... */ + objv[0] = Tcl_NewStringObj("tkdnd::macdnd::_GetDragSourceCommonTypes", -1); + /* Evaluate the command and get the result...*/ + TkDND_Status_Eval(1); + // printf("Status=%d (%d)\n", status, TCL_OK);fflush(0); + if (status != TCL_OK) { + /* An error has happened. Cancel the drop! */ + return NO; + } + result = Tcl_GetObjResult(interp); Tcl_IncrRefCount(result); + status = Tcl_ListObjGetElements(interp, result, &elem_nu, &elem); + if (status != TCL_OK) { + Tcl_DecrRefCount(result); + return NO; + } + +#if 0 + /* Print what exists in the clipboard... */ + i = 0; + for (NSPasteboardItem *item in [sourcePasteBoard pasteboardItems]) { + for (NSString *type in [item types]) { + printf("item %d: type: %s\n", i++, [type UTF8String]); + } + } + /* Print what we can accept... */ + for (int j = 0; j < elem_nu; ++j) { + printf("accept: %s\n", Tcl_GetString(elem[j])); + } +#endif - /* Retrieve string data from clipboard... */ - NSArray *types = [sourcePasteBoard types]; - NSString *pasteboardvalue = nil; - for (NSString *type in types) { - if ([type isEqualToString:NSStringPboardType]) { + /* Retrieve data from clipboard, checking all items... */ + for (int j = 0; j < elem_nu; ++j) { + type = TKDND_Obj2NSString(interp, elem[j]); + if ([type isEqualToString:NSPasteboardTypeString]) { /* String type... */ - pasteboardvalue = [sourcePasteBoard stringForType:NSStringPboardType]; - data = Tcl_NewStringObj([pasteboardvalue UTF8String], -1); + for (NSPasteboardItem *item in [sourcePasteBoard pasteboardItems]) { + NSString *pasteboardvalue = [item stringForType:NSPasteboardTypeString]; + if (pasteboardvalue) { + data = Tcl_NewStringObj([pasteboardvalue UTF8String], -1); + break; + } + } } else if ([type isEqualToString:NSFilenamesPboardType]) { - Tcl_Obj *element; - data = Tcl_NewListObj(0, NULL); - /* File array... */ - NSArray *files = - [sourcePasteBoard propertyListForType:NSFilenamesPboardType]; - for (NSString *filename in files) { - element = Tcl_NewStringObj([filename UTF8String], -1); - if (element == NULL) continue; - Tcl_IncrRefCount(element); - Tcl_ListObjAppendElement(interp, data, element); - Tcl_DecrRefCount(element); + /* Filenames array... */ + NSArray *files = [sourcePasteBoard propertyListForType:NSFilenamesPboardType]; + if (files) { + Tcl_Obj *element; + data = Tcl_NewListObj(0, NULL); + for (NSString *filename in files) { + element = Tcl_NewStringObj([filename UTF8String], -1); + if (element == NULL) continue; + Tcl_ListObjAppendElement(interp, data, element); + } } } + if (data != NULL) break; } + Tcl_DecrRefCount(result); if (data == NULL) data = Tcl_NewStringObj(NULL, 0); - Tcl_Obj* objv[3], *result; - int i, index, status; - objv[0] = Tcl_NewStringObj("tkdnd::macdnd::_HandleDrop", -1); objv[1] = Tcl_NewStringObj(Tk_PathName(tkwin), -1); objv[2] = data; @@ -425,10 +575,8 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { * Calls tkdnd::macdnd::_HandleXdndDrop */ - (void)draggingExited:(id < NSDraggingInfo >)sender { - TkWindow *winPtr = TkMacOSXGetTkWindow([self window]); - Tk_Window tkwin = (Tk_Window) winPtr; + Tk_Window tkwin = TkMacOSXGetTkWindow([self window]); Tcl_Interp *interp = Tk_Interp(tkwin); - sourcePasteBoard = [sender draggingPasteboard]; Tcl_Obj* objv[4]; int i; @@ -459,20 +607,20 @@ DNDView* TkDND_GetDNDSubview(NSView *view, Tk_Window tkwin) { */ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - Tcl_Obj **elem; + Tcl_Obj **elem, **data_elem, **files_elem; int actions = 0; - int status, elem_nu, i, index; + int status, elem_nu, data_elem_nu, files_elem_nu, i, j, index; Tk_Window path; Drawable d; NSView *view; DNDView *dragview; NSImage *dragicon = NULL; static char *DropTypes[] = { - "NSStringPboardType", "NSFilenamesPboardType", + "NSPasteboardTypeString", "NSFilenamesPboardType", (char *) NULL }; enum droptypes { - TYPE_NSStringPboardType, TYPE_NSFilenamesPboardType + TYPE_NSPasteboardTypeString, TYPE_NSFilenamesPboardType }; static char *DropActions[] = { "copy", "move", "link", "ask", "private", "refuse_drop", @@ -485,8 +633,8 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, }; bool added_string = false, added_filenames = false, perform_drag = false; - if (objc != 5) { - Tcl_WrongNumArgs(interp, 1, objv, "path actions types data"); + if (objc != 6) { + Tcl_WrongNumArgs(interp, 1, objv, "path actions types data button"); return TCL_ERROR; } Tcl_ResetResult(interp); @@ -524,18 +672,25 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, /* Process drag types. */ status = Tcl_ListObjGetElements(interp, objv[3], &elem_nu, &elem); if (status != TCL_OK) return status; + /* objv[4] contains a list, one element for each data drag type... */ + status = Tcl_ListObjGetElements(interp, objv[4], &data_elem_nu, &data_elem); + if (status != TCL_OK) return status; + if (elem_nu != data_elem_nu) { + /* This can never happen... */ + return TCL_ERROR; + } /* Initialize array of drag types... */ - NSMutableArray *draggedtypes=[[NSMutableArray alloc] init]; + NSMutableArray *draggedtypes=[[[NSMutableArray alloc] init] autorelease]; /* Iterate over all data, to collect the types... */ for (i = 0; i < elem_nu; i++) { status = Tcl_GetIndexFromObj(interp, elem[i], (const char **) DropTypes, - "dropactions", 0, &index); + "droptypes", 0, &index); if (status != TCL_OK) continue; switch ((enum droptypes) index) { - case TYPE_NSStringPboardType: { + case TYPE_NSPasteboardTypeString: { if (!added_string) { - [draggedtypes addObject: NSStringPboardType]; + // [draggedtypes addObject: NSPasteboardTypeString]; added_string = true; perform_drag = true; } @@ -563,7 +718,18 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, * to drop targets via [sender draggingPasteboard] */ NSPasteboard *dragpasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - [dragpasteboard declareTypes:draggedtypes owner:dragview]; + NSMutableArray *dataitems =[[[NSMutableArray alloc] init] autorelease]; + NSMutableArray *filelist = [[[NSMutableArray alloc] init] autorelease]; + [dragpasteboard clearContents]; + + if (added_filenames) { + /* There is a request about deprecated NSFilenamesPboardType. The only way to + use it, is through setPropertyList:forType, which operates only on the first + item. So, call declareTypes, to create this first item... */ + //[dragpasteboard declareTypes:draggedtypes owner:dragview]; + NSPasteboardItem *item = [[[NSPasteboardItem alloc] init] autorelease]; + [dataitems addObject: item]; + } /* * We need an icon for the drag: @@ -572,14 +738,18 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, */ for (i = 0; i < elem_nu; i++) { status = Tcl_GetIndexFromObj(interp, elem[i], (const char **) DropTypes, - "dropactions", 0, &index); + "droptypes", 0, &index); if (status == TCL_OK) { switch ((enum droptypes) index) { - case TYPE_NSStringPboardType: { + case TYPE_NSPasteboardTypeString: { /* Place the string into the clipboard. */ NSString *datastring = - [NSString stringWithUTF8String:Tcl_GetString(objv[4])]; - [dragpasteboard setString:datastring forType:NSStringPboardType]; + [NSString stringWithUTF8String:Tcl_GetString(data_elem[i])]; + NSPasteboardItem *item = [[[NSPasteboardItem alloc] init] autorelease]; + [item setString:datastring forType:NSPasteboardTypeString]; + [dataitems addObject: item]; + //[dragpasteboard writeObjects:[NSArray arrayWithObject:item]]; + //[dragpasteboard setString:datastring forType:NSPasteboardTypeString]; /* Create a custom icon: draw dragged string into drag icon, * make sure icon is large enough to contain several lines of text */ @@ -595,24 +765,24 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, break; } case TYPE_NSFilenamesPboardType: { - NSMutableArray *filelist = [[NSMutableArray alloc] init]; /* Place the filenames into the clipboard. */ - status = Tcl_ListObjGetElements(interp, objv[4], &elem_nu, &elem); + status = Tcl_ListObjGetElements(interp, data_elem[i], + &files_elem_nu, &files_elem); if ( status == TCL_OK) { - for (i = 0; i < elem_nu; i++) { + for (j = 0; j < files_elem_nu; j++) { /* Get string value of file name from list */ - char* filename = Tcl_GetString(elem[i]); + char* filename = Tcl_GetString(files_elem[j]); /* Convert file names to NSSString, add to NSMutableArray, * and set pasteboard type */ NSString *filestring = [NSString stringWithUTF8String:filename]; - [filelist addObject: filestring]; + [filelist addObject: /*[NSURL fileURLWithPath:*/ filestring] /*]*/; } } /* This successfully writes the file path data to the clipboard, * and it is available to other non-Tk applications... */ - [dragpasteboard setPropertyList:filelist - forType:NSFilenamesPboardType]; + // [dragpasteboard writeObjects: filelist]; + // [dragpasteboard setPropertyList:filelist forType:NSFilenamesPboardType]; /* Set the correct icon depending on whether a single file * [iconForFileType] or multiple files [NSImageNameMultipleDocuments] @@ -620,7 +790,7 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, if (dragicon == NULL) { if ([filelist count] == 1) { NSString *pathtype = [[filelist objectAtIndex:0] pathExtension]; - dragicon = [[NSWorkspace sharedWorkspace] + dragicon = [[NSWorkspace sharedWorkspace] iconForFileType:pathtype]; } else { dragicon = [NSImage imageNamed:NSImageNameMultipleDocuments]; @@ -633,6 +803,10 @@ int TkDND_DoDragDropObjCmd(ClientData clientData, Tcl_Interp *interp, /* An unknown (or user defined) type. Silently skip it... */ } } + [dragpasteboard writeObjects: dataitems]; + if (added_filenames) { + [dragpasteboard setPropertyList:filelist forType:NSFilenamesPboardType]; + } /* Do drag & drop... */ @@ -721,16 +895,16 @@ int TkDND_RegisterDragWidgetObjCmd(ClientData clientData, Tcl_Interp *ip, if (strncmp(str, "*", len) == 0) { /* A request for all available types... */ if (!added_string) { - [draggedtypes addObject: NSStringPboardType]; + [draggedtypes addObject: NSPasteboardTypeString]; added_string = true; } if (!added_filenames) { [draggedtypes addObject: NSFilenamesPboardType]; added_filenames = true; } - } else if (strncmp(str, "NSStringPboardType", len) == 0) { + } else if (strncmp(str, "NSPasteboardTypeString", len) == 0) { if (!added_string) { - [draggedtypes addObject: NSStringPboardType]; + [draggedtypes addObject: NSPasteboardTypeString]; added_string = true; } } else if (strncmp(str, "NSFilenamesPboardType", len) == 0) { @@ -772,6 +946,20 @@ int TkDND_UnregisterDragWidgetObjCmd(ClientData clientData, Tcl_Interp *ip, return TCL_OK; }; /* TkDND_UnregisterDragWidgetObjCmd */ +/* Convert OS X types to strings... */ +int TkDND_Type2StringObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) { + const NSString *str; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "type"); + return TCL_ERROR; + } + str = TKDND_Obj2NSString(interp, objv[1]); + if (str == NULL) return TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj([str UTF8String], -1)); + return TCL_OK; +}; /* TkDND_Type2StringObjCmd */ + /* * Initalize the package in the tcl interpreter, create tcl commands... */ @@ -794,6 +982,9 @@ int Tkdnd_Init (Tcl_Interp *interp) { Tcl_CreateObjCommand(interp, "::macdnd::dodragdrop", TkDND_DoDragDropObjCmd, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "::macdnd::osxtype2string", + TkDND_Type2StringObjCmd, + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) { return TCL_ERROR; -- cgit v0.12