private static bool TryGetFileDropData(IDataObject data, out IEnumerable <string> fileNames) { if (data.Contains(CefNetDragData.DataFormatFileDrop)) { fileNames = (IEnumerable <string>)data.Get(CefNetDragData.DataFormatFileDrop); } else if (data.Contains(CefNetDragData.DataFormatFileNames)) { fileNames = (IEnumerable <string>)data.Get(CefNetDragData.DataFormatFileNames); } else { fileNames = null; } return(fileNames != null); }
public Task <DragDropEffects> DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects) { // Sanity check var tl = FindRoot(triggerEvent.Source); var view = tl?.PlatformImpl as WindowBaseImpl; if (view == null) { throw new ArgumentException(); } triggerEvent.Pointer.Capture(null); var tcs = new TaskCompletionSource <DragDropEffects>(); var clipboardImpl = _factory.CreateDndClipboard(); using (var clipboard = new ClipboardImpl(clipboardImpl)) using (var cb = new DndCallback(tcs)) { if (data.Contains(DataFormats.Text)) { // API is synchronous, so it's OK clipboard.SetTextAsync(data.GetText()).Wait(); } view.BeginDraggingSession((AvnDragDropEffects)allowedEffects, triggerEvent.GetPosition(tl).ToAvnPoint(), clipboardImpl, cb, GCHandle.ToIntPtr(GCHandle.Alloc(data))); } return(tcs.Task); }
private unsafe void OnEvent(ref XEvent ev) { if (ev.type == XEventName.SelectionRequest) { var sel = ev.SelectionRequestEvent; var resp = new XEvent { SelectionEvent = { type = XEventName.SelectionNotify, send_event = 1, display = _x11.Display, selection = sel.selection, target = sel.target, requestor = sel.requestor, time = sel.time, property = IntPtr.Zero } }; if (sel.selection == _x11.Atoms.CLIPBOARD) { resp.SelectionEvent.property = WriteTargetToProperty(sel.target, sel.requestor, sel.property); } XSendEvent(_x11.Display, sel.requestor, false, new IntPtr((int)EventMask.NoEventMask), ref resp); } IntPtr WriteTargetToProperty(IntPtr target, IntPtr window, IntPtr property) { Encoding textEnc; if (target == _x11.Atoms.TARGETS) { var atoms = new HashSet <IntPtr> { _x11.Atoms.TARGETS, _x11.Atoms.MULTIPLE }; foreach (var fmt in _storedDataObject.GetDataFormats()) { if (fmt == DataFormats.Text) { foreach (var ta in _textAtoms) { atoms.Add(ta); } } else { atoms.Add(_x11.Atoms.GetAtom(fmt)); } } XChangeProperty(_x11.Display, window, property, _x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms.ToArray(), atoms.Count); return(property); } else if (target == _x11.Atoms.SAVE_TARGETS && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero) { return(property); } else if ((textEnc = GetStringEncoding(target)) != null && _storedDataObject?.Contains(DataFormats.Text) == true) { var text = _storedDataObject.GetText(); if (text == null) { return(IntPtr.Zero); } var data = textEnc.GetBytes(text); fixed(void *pdata = data) XChangeProperty(_x11.Display, window, property, target, 8, PropertyMode.Replace, pdata, data.Length); return(property); } else if (target == _x11.Atoms.MULTIPLE && _x11.Atoms.MULTIPLE != IntPtr.Zero) { XGetWindowProperty(_x11.Display, window, property, IntPtr.Zero, new IntPtr(0x7fffffff), false, _x11.Atoms.ATOM_PAIR, out _, out var actualFormat, out var nitems, out _, out var prop); if (nitems == IntPtr.Zero) { return(IntPtr.Zero); } if (actualFormat == 32) { var data = (IntPtr *)prop.ToPointer(); for (var c = 0; c < nitems.ToInt32(); c += 2) { var subTarget = data[c]; var subProp = data[c + 1]; var converted = WriteTargetToProperty(subTarget, window, subProp); data[c + 1] = converted; } XChangeProperty(_x11.Display, window, property, _x11.Atoms.ATOM_PAIR, 32, PropertyMode.Replace, prop.ToPointer(), nitems.ToInt32()); } XFree(prop); return(property); } else if (_storedDataObject?.Contains(_x11.Atoms.GetAtomName(target)) == true) { var objValue = _storedDataObject.Get(_x11.Atoms.GetAtomName(target)); if (!(objValue is byte[] bytes)) { if (objValue is string s) { bytes = Encoding.UTF8.GetBytes(s); } else { return(IntPtr.Zero); } } XChangeProperty(_x11.Display, window, property, target, 8, PropertyMode.Replace, bytes, bytes.Length); return(property); } else { return(IntPtr.Zero); } } if (ev.type == XEventName.SelectionNotify && ev.SelectionEvent.selection == _x11.Atoms.CLIPBOARD) { var sel = ev.SelectionEvent; if (sel.property == IntPtr.Zero) { _requestedFormatsTcs?.TrySetResult(null); _requestedDataTcs?.TrySetResult(null); } XGetWindowProperty(_x11.Display, _handle, sel.property, IntPtr.Zero, new IntPtr(0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out var actualTypeAtom, out var actualFormat, out var nitems, out var bytes_after, out var prop); Encoding textEnc = null; if (nitems == IntPtr.Zero) { _requestedFormatsTcs?.TrySetResult(null); _requestedDataTcs?.TrySetResult(null); } else { if (sel.property == _x11.Atoms.TARGETS) { if (actualFormat != 32) { _requestedFormatsTcs?.TrySetResult(null); } else { var formats = new IntPtr[nitems.ToInt32()]; Marshal.Copy(prop, formats, 0, formats.Length); _requestedFormatsTcs?.TrySetResult(formats); } } else if ((textEnc = GetStringEncoding(actualTypeAtom)) != null) { var text = textEnc.GetString((byte *)prop.ToPointer(), nitems.ToInt32()); _requestedDataTcs?.TrySetResult(text); } else { if (actualTypeAtom == _x11.Atoms.INCR) { // TODO: Actually implement that monstrosity _requestedDataTcs.TrySetResult(null); } else { var data = new byte[(int)nitems * (actualFormat / 8)]; Marshal.Copy(prop, data, 0, data.Length); _requestedDataTcs?.TrySetResult(data); } } } XFree(prop); } }