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);
        }
示例#3
0
        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);
            }
        }