| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- // Copyright (c) 2007 Novell, Inc.
- //
- // Authors:
- // Geoff Norton ([email protected])
- //
- //
- using System;
- using System.IO;
- using System.Text;
- using System.Drawing;
- using System.Threading;
- using System.Collections;
- using System.Windows.Forms;
- using System.Runtime.Serialization;
- using System.Runtime.InteropServices;
- using System.Runtime.Serialization.Formatters.Binary;
- namespace System.Windows.Forms.CarbonInternal {
- internal delegate void DragTrackingDelegate (short message, IntPtr window, IntPtr data, IntPtr dragref);
- internal class Dnd {
- internal const uint kEventParamDragRef = 1685217639;
- internal const uint typeDragRef = 1685217639;
- internal const uint typeMono = 1836019311;
- internal const uint typeMonoSerializedObject = 1836279154;
- private static DragDropEffects effects = DragDropEffects.None;
- private static DragTrackingDelegate DragTrackingHandler = new DragTrackingDelegate (TrackingCallback);
- static Dnd () {
- try {
- InstallTrackingHandler (DragTrackingHandler, IntPtr.Zero, IntPtr.Zero);
- } catch (EntryPointNotFoundException) {
- // it is deprecated in 10.6 and does not exist anymore.
- }
- }
- internal Dnd () {
- }
- internal static void TrackingCallback (short message, IntPtr window, IntPtr data, IntPtr dragref) {
- XplatUICarbon.GetInstance ().FlushQueue ();
- }
-
- internal static DragDropEffects DragActionsToEffects (UInt32 actions) {
- DragDropEffects effects = DragDropEffects.None;
- if ((actions & 1) != 0)
- effects |= DragDropEffects.Copy;
- if ((actions & (1 << 4)) != 0)
- effects |= DragDropEffects.Move;
- if ((actions & 0xFFFFFFFF) != 0)
- effects |= DragDropEffects.All;
- return effects;
- }
- internal static DataObject DragToDataObject (IntPtr dragref) {
- UInt32 items = 0;
- ArrayList flavorlist = new ArrayList ();
- CountDragItems (dragref, ref items);
-
- for (uint item_counter = 1; item_counter <= items; item_counter++) {
- IntPtr itemref = IntPtr.Zero;
- UInt32 flavors = 0;
-
- GetDragItemReferenceNumber (dragref, item_counter, ref itemref);
- CountDragItemFlavors (dragref, itemref, ref flavors);
- for (uint flavor_counter = 1; flavor_counter <= flavors; flavor_counter++) {
- FlavorHandler flavor = new FlavorHandler (dragref, itemref, flavor_counter);
- if (flavor.Supported)
- flavorlist.Add (flavor);
- }
- }
- if (flavorlist.Count > 0) {
- return ((FlavorHandler) flavorlist [0]).Convert (flavorlist);
- }
- return new DataObject ();
- }
- internal static bool HandleEvent (IntPtr callref, IntPtr eventref, IntPtr handle, uint kind, ref MSG msg) {
- Control control;
- DataObject data;
- DragEventArgs drag_event;
- DragDropEffects allowed;
- QDPoint point = new QDPoint ();
- UInt32 actions = 0;
- IntPtr dragref = IntPtr.Zero;
- Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
- if (hwnd == null || hwnd.Handle != handle)
- return false;
- GetEventParameter (eventref, kEventParamDragRef, typeDragRef, IntPtr.Zero, (uint) Marshal.SizeOf (typeof (IntPtr)), IntPtr.Zero, ref dragref);
- XplatUICarbon.GetGlobalMouse (ref point);
- GetDragAllowableActions (dragref, ref actions);
- control = Control.FromHandle (hwnd.Handle);
- allowed = DragActionsToEffects (actions);
- data = DragToDataObject (dragref);
- drag_event = new DragEventArgs (data, 0, point.x, point.y, allowed, DragDropEffects.None);
-
- switch (kind) {
- case ControlHandler.kEventControlDragEnter: {
- bool accept = control.AllowDrop;
- SetEventParameter (eventref, ControlHandler.kEventParamControlLikesDrag, ControlHandler.typeBoolean, (uint)Marshal.SizeOf (typeof (bool)), ref accept);
- control.DndEnter (drag_event);
- effects = drag_event.Effect;
- return false;
- }
- case ControlHandler.kEventControlDragWithin:
- control.DndOver (drag_event);
- effects = drag_event.Effect;
- break;
- case ControlHandler.kEventControlDragLeave:
- control.DndLeave (drag_event);
- break;
- case ControlHandler.kEventControlDragReceive:
- control.DndDrop (drag_event);
- break;
- }
- return true;
- }
- public void SetAllowDrop (Hwnd hwnd, bool allow) {
- if (hwnd.allow_drop == allow)
- return;
- hwnd.allow_drop = allow;
- SetControlDragTrackingEnabled (hwnd.whole_window, true);
- SetControlDragTrackingEnabled (hwnd.client_window, true);
- }
- public void SendDrop (IntPtr handle, IntPtr from, IntPtr time) {
- }
- public DragDropEffects StartDrag (IntPtr handle, object data, DragDropEffects allowed_effects) {
- IntPtr dragref = IntPtr.Zero;
- EventRecord eventrecord = new EventRecord ();
- effects = DragDropEffects.None;
- NewDrag (ref dragref);
- XplatUICarbon.GetGlobalMouse (ref eventrecord.mouse);
- StoreObjectInDrag (handle, dragref, data);
- TrackDrag (dragref, ref eventrecord, IntPtr.Zero);
- DisposeDrag (dragref);
- return effects;
- }
- public void StoreObjectInDrag (IntPtr handle, IntPtr dragref, object data) {
- IntPtr type = IntPtr.Zero;
- IntPtr dataptr = IntPtr.Zero;
- Int32 size = 0;
- if (data is string) {
- // implement me
- throw new NotSupportedException ("Implement me.");
- } else if (data is ISerializable) {
- MemoryStream stream = new MemoryStream ();
- BinaryFormatter bf = new BinaryFormatter ();
- bf.Serialize (stream, data);
- dataptr = Marshal.AllocHGlobal ((int) stream.Length);
- stream.Seek (0, 0);
- for (int i = 0; i < stream.Length; i++) {
- Marshal.WriteByte (dataptr, i, (byte) stream.ReadByte ());
- }
-
- type = (IntPtr) typeMonoSerializedObject;
- size = (int) stream.Length;
- } else {
- dataptr = (IntPtr) GCHandle.Alloc (data);
- type = (IntPtr) typeMono;
- size = Marshal.SizeOf (typeof (IntPtr));
- }
- AddDragItemFlavor (dragref, handle, type, ref dataptr, size, 1 << 0);
- }
- [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- static extern int InstallTrackingHandler (DragTrackingDelegate callback, IntPtr window, IntPtr data);
- [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- static extern int GetEventParameter (IntPtr eventref, uint name, uint type, IntPtr outtype, uint size, IntPtr outsize, ref IntPtr data);
- [DllImport ("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- static extern int SetEventParameter (IntPtr eventref, uint name, uint type, uint size, ref bool data);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int SetControlDragTrackingEnabled (IntPtr view, bool enabled);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int AddDragItemFlavor (IntPtr dragref, IntPtr itemref, IntPtr flavortype, ref IntPtr data, Int32 size, UInt32 flags);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int CountDragItems (IntPtr dragref, ref UInt32 count);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int CountDragItemFlavors (IntPtr dragref, IntPtr itemref, ref UInt32 count);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetDragItemReferenceNumber (IntPtr dragref, UInt32 index, ref IntPtr itemref);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int NewDrag (ref IntPtr dragref);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int TrackDrag (IntPtr dragref, ref EventRecord eventrecord, IntPtr region);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int DisposeDrag (IntPtr dragref);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetDragAllowableActions (IntPtr dragref, ref UInt32 actions);
- }
- internal struct EventRecord {
- internal UInt16 what;
- internal UInt32 message;
- internal UInt32 when;
- internal QDPoint mouse;
- internal UInt16 modifiers;
- }
- internal class FlavorHandler {
- internal IntPtr flavorref;
- internal IntPtr dragref;
- internal IntPtr itemref;
- internal Int32 size;
- internal UInt32 flags;
- internal byte [] data;
- internal string fourcc;
- internal FlavorHandler (IntPtr dragref, IntPtr itemref, uint counter) {
- GetFlavorType (dragref, itemref, counter, ref flavorref);
- GetFlavorFlags (dragref, itemref, flavorref, ref flags);
- byte [] fourcc_b = BitConverter.GetBytes ((Int32)flavorref);
- this.fourcc = String.Format ("{0}{1}{2}{3}", (char)fourcc_b [3], (char)fourcc_b [2], (char)fourcc_b [1], (char)fourcc_b [0]);
- this.dragref = dragref;
- this.itemref = itemref;
- this.GetData ();
- }
- internal void GetData () {
- GetFlavorDataSize (dragref, itemref, flavorref, ref size);
- data = new byte [size];
- GetFlavorData (dragref, itemref, flavorref, data, ref size, 0);
- }
- internal string DataString {
- get { return Encoding.Default.GetString (this.data); }
- }
-
- internal byte[] DataArray {
- get { return this.data; }
- }
- internal IntPtr DataPtr {
- get { return (IntPtr) BitConverter.ToInt32 (this.data, 0); }
- }
- internal bool Supported {
- get {
- switch (fourcc) {
- case "furl":
- return true;
- case "mono":
- return true;
- case "mser":
- return true;
- }
- return false;
- }
- }
- internal DataObject Convert (ArrayList flavorlist) {
- switch (fourcc) {
- case "furl":
- return ConvertToFileDrop (flavorlist);
- case "mono":
- return ConvertToObject (flavorlist);
- case "mser":
- return DeserializeObject (flavorlist);
- }
- return new DataObject ();
- }
- internal DataObject DeserializeObject (ArrayList flavorlist) {
- DataObject data = new DataObject ();
- MemoryStream stream = new MemoryStream (this.DataArray);
- BinaryFormatter bf = new BinaryFormatter ();
- if (stream.Length == 0)
- return data;
- stream.Seek (0, 0);
- data.SetData (bf.Deserialize (stream));
- return data;
- }
- internal DataObject ConvertToObject (ArrayList flavorlist) {
- DataObject data = new DataObject ();
-
- foreach (FlavorHandler flavor in flavorlist) {
- GCHandle handle = (GCHandle) flavor.DataPtr;
- data.SetData (handle.Target);
- }
-
- return data;
- }
- internal DataObject ConvertToFileDrop (ArrayList flavorlist) {
- DataObject data = new DataObject ();
- ArrayList uri_list = new ArrayList ();
- foreach (FlavorHandler flavor in flavorlist) {
- try {
- uri_list.Add (new Uri (flavor.DataString).LocalPath);
- } catch { }
- }
- string [] l = (string []) uri_list.ToArray (typeof (string));
- if (l.Length < 1)
- return data;
- data.SetData (DataFormats.FileDrop, l);
- data.SetData ("FileName", l [0]);
- data.SetData ("FileNameW", l [0]);
-
- return data;
- }
- public override string ToString () {
- return fourcc;
- }
-
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetFlavorDataSize (IntPtr dragref, IntPtr itemref, IntPtr flavorref, ref Int32 size);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetFlavorData (IntPtr dragref, IntPtr itemref, IntPtr flavorref, [In, Out] byte[] data, ref Int32 size, UInt32 offset);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetFlavorFlags (IntPtr dragref, IntPtr itemref, IntPtr flavorref, ref UInt32 flags);
- [DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon")]
- extern static int GetFlavorType (IntPtr dragref, IntPtr itemref, UInt32 index, ref IntPtr flavor);
- }
- }
|