From c65f1fb7bcbade77fd08f838119aa0a2d5460467 Mon Sep 17 00:00:00 2001 From: Vlad K Date: Wed, 17 May 2017 00:03:03 +0300 Subject: [PATCH] Initial d&d x11 event support --- src/OpenTK/Platform/X11/X11GLNative.cs | 90 +++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/src/OpenTK/Platform/X11/X11GLNative.cs b/src/OpenTK/Platform/X11/X11GLNative.cs index 8cbb25d5..934820c1 100644 --- a/src/OpenTK/Platform/X11/X11GLNative.cs +++ b/src/OpenTK/Platform/X11/X11GLNative.cs @@ -68,7 +68,7 @@ namespace OpenTK.Platform.X11 const string ICON_NET_ATOM = "_NET_WM_ICON"; // The Atom class from Mono might be useful to avoid calling XInternAtom by hand (somewhat error prone). - IntPtr _atom_wm_destroy; + IntPtr _atom_wm_destroy; IntPtr _atom_net_wm_state; IntPtr _atom_net_wm_state_minimized; @@ -76,6 +76,16 @@ namespace OpenTK.Platform.X11 IntPtr _atom_net_wm_state_maximized_horizontal; IntPtr _atom_net_wm_state_maximized_vertical; + // Xdnd atoms + IntPtr _atom_xdnd_enter; + IntPtr _atom_xdnd_position; + IntPtr _atom_xdnd_status; + IntPtr _atom_xdnd_type_list; + IntPtr _atom_xdnd_action_copy; + IntPtr _atom_xdnd_drop; + IntPtr _atom_xdnd_finished; + IntPtr _atom_xdnd_selection; + #pragma warning disable 414 // assigned but never used IntPtr _atom_net_wm_allowed_actions; IntPtr _atom_net_wm_action_resize; @@ -264,6 +274,13 @@ namespace OpenTK.Platform.X11 xi2_version = XI2MouseKeyboard.XIVersion; } + // Alow window recive Xdnd Events + IntPtr xdndAware = Functions.XInternAtom(window.Display, "XdndAware", false); + IntPtr xdndProtocol = new IntPtr(5); + using (new XLock (window.Display)) { + Functions.XChangeProperty(this.window.Display, this.Handle, xdndAware, (IntPtr)AtomName.XA_ATOM, 32, PropertyMode.Replace, ref xdndProtocol, 1); + } + exists = true; } @@ -306,6 +323,22 @@ namespace OpenTK.Platform.X11 #region Private Members + #region Utils + + private void ReadProperty(IntPtr property, IntPtr type, ref IntPtr data, ref IntPtr itemsCount) + { + int format; + IntPtr length = new IntPtr(int.MaxValue); + IntPtr actualType; + IntPtr bytesLeft; + + Functions.XGetWindowProperty(this.window.Display, this.window.Handle, property, IntPtr.Zero, + length, false, type, + out actualType, out format, out itemsCount, out bytesLeft, ref data); + } + + #endregion + #region private void RegisterAtoms() /// @@ -342,6 +375,16 @@ namespace OpenTK.Platform.X11 _atom_net_frame_extents = Functions.XInternAtom(window.Display, "_NET_FRAME_EXTENTS", false); + // Some Xdnd atoms + _atom_xdnd_enter = Functions.XInternAtom(window.Display, "XdndEnter", false); + _atom_xdnd_position = Functions.XInternAtom(window.Display, "XdndPosition", false); + _atom_xdnd_status = Functions.XInternAtom(window.Display, "XdndStatus", false); + _atom_xdnd_type_list = Functions.XInternAtom(window.Display, "XdndTypeList", false); + _atom_xdnd_action_copy = Functions.XInternAtom(window.Display, "XdndActionCopy", false); + _atom_xdnd_drop = Functions.XInternAtom(window.Display, "XdndDrop", false); + _atom_xdnd_finished = Functions.XInternAtom(window.Display, "Xdndfinished", false); + _atom_xdnd_selection = Functions.XInternAtom(window.Display, "XdndSelection", false); + // string[] atom_names = new string[] // { // //"WM_TITLE", @@ -798,7 +841,7 @@ namespace OpenTK.Platform.X11 !Functions.XCheckTypedWindowEvent(window.Display, window.Handle, XEventName.ClientMessage, ref e)) break; } - + // Respond to the event e switch (e.type) { @@ -838,8 +881,46 @@ namespace OpenTK.Platform.X11 OnClosed(EventArgs.Empty); break; } + } else if (e.ClientMessageEvent.message_type == _atom_xdnd_enter) { + // Xdnd started + bool useList = ((e.ClientMessageEvent.ptr2.ToInt64() & 1) == 1); + //long source = e.ClientMessageEvent.ptr1.ToInt64(); + //long version = e.ClientMessageEvent.ptr2.ToInt64() >> 24; + + IntPtr formats = IntPtr.Zero; + int formatCount; + if (useList) { + IntPtr count = IntPtr.Zero; + ReadProperty(_atom_xdnd_type_list, (IntPtr)AtomName.XA_ATOM, ref formats, ref count); + formatCount = count.ToInt32(); + } else { + Marshal.WriteIntPtr(formats, e.ClientMessageEvent.ptr3); + Marshal.WriteIntPtr(formats, e.ClientMessageEvent.ptr4); + Marshal.WriteIntPtr(formats, e.ClientMessageEvent.ptr5); + formatCount = 3; + } + + IntPtr atom = IntPtr.Zero; + for (int i = 0; i < formatCount && atom == IntPtr.Zero; i++) { + IntPtr tempAtom = Marshal.ReadIntPtr(formats, IntPtr.Size * i); + IntPtr atomName = Functions.XGetAtomName(this.window.Display, tempAtom); + + string str = Marshal.PtrToStringUni(atomName); + if (str == "text/uri-list") { + atom = tempAtom; + } + + Functions.XFree(atomName); + } + + if (useList && formats != IntPtr.Zero) { + Functions.XFree(formats); + } + } else if (e.ClientMessageEvent.message_type == _atom_xdnd_position) { + // Ignore for now it handle position of mouse when d&d happens + } else if (e.ClientMessageEvent.message_type == _atom_xdnd_drop) { + // Ignore for now it handle actual d&d } - break; case XEventName.DestroyNotify: @@ -1006,6 +1087,9 @@ namespace OpenTK.Platform.X11 //} break; + case XEventName.SelectionNotify: + break; + default: //Debug.WriteLine(String.Format("{0} event was not handled", e.type)); break;