Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

X11 clipboard incr proto #12357

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7ef6152
code format
viordash Jul 23, 2023
5ffb53e
X11Clipboard.OnEvent code refactoring
viordash Jul 23, 2023
341984f
fix potential memleak. (XGetWindowProperty always allocates one extra…
viordash Jul 23, 2023
94225f2
no need to call XGetWindowProperty for an empty property
viordash Jul 23, 2023
7a85d21
X11Clipboard. handle PropertyNotify events
viordash Jul 23, 2023
8d86c4f
X11Clipboard. implement receive INCR data
viordash Jul 23, 2023
41e5ff1
X11Clipboard. unify the process of changing properties (text and bina…
viordash Jul 23, 2023
de6cc22
wip. X11Clipboard. implement transmit INCR data
viordash Jul 24, 2023
5dcacd7
X11Clipboard. get MaxRequestSize from X11
viordash Jul 25, 2023
46faae7
Clipboard X11. wait for the data to be stored
viordash Jul 25, 2023
09f1d6c
Revert "X11Clipboard. get MaxRequestSize from X11"
viordash Jul 25, 2023
4058759
X11Clipboard. for big data don't use CLIPBOARD_MANAGER
viordash Jul 25, 2023
0f89be8
X11Clipboard. fix waiting for INCR store to complete
viordash Jul 26, 2023
8e5f7db
X11Clipboard. fix UseIncrProtocol
viordash Jul 26, 2023
decd3a6
X11Clipboard. INCR for foreign windows only
viordash Jul 26, 2023
edfac01
use byte array
viordash Jul 27, 2023
0c9946e
X11Clipboard. support parallel INCR reading
viordash Jul 29, 2023
bbfbe50
X11Clipboard. support parallel INCR writing
viordash Jul 29, 2023
a977d3d
Merge remote-tracking branch 'origin/master' into x11-clipboard-incr-…
viordash Jul 29, 2023
8c41a77
X11Clipboard. fix ClearAsync completion
viordash Jul 29, 2023
6670284
Merge branch 'master' into x11-clipboard-incr-proto
viordash Jul 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
X11Clipboard.OnEvent code refactoring
  • Loading branch information
viordash committed Jul 27, 2023
commit 5ffb53ed33604b4d2c3e27cc67bfc469f26347e5
152 changes: 79 additions & 73 deletions src/Avalonia.X11/X11Clipboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,79 +82,7 @@ private unsafe void OnEvent(ref XEvent ev)
}

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 = ConvertDataObject(_storedDataObject);
XChangeProperty(_x11.Display, window, property,
_x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms, atoms.Length);
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;
return;
}

if (ev.type == XEventName.SelectionNotify && ev.SelectionEvent.selection == _x11.Atoms.CLIPBOARD)
Expand Down Expand Up @@ -208,9 +136,87 @@ IntPtr WriteTargetToProperty(IntPtr target, IntPtr window, IntPtr property)
}

XFree(prop);
return;
}
}

private unsafe IntPtr WriteTargetToProperty(IntPtr target, IntPtr window, IntPtr property)
{
Encoding textEnc;
if (target == _x11.Atoms.TARGETS)
{
var atoms = ConvertDataObject(_storedDataObject);
XChangeProperty(_x11.Display, window, property,
_x11.Atoms.XA_ATOM, 32, PropertyMode.Replace, atoms, atoms.Length);
return property;
}

if (target == _x11.Atoms.SAVE_TARGETS && _x11.Atoms.SAVE_TARGETS != IntPtr.Zero)
{
return property;
}

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;
}

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;
}

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;
}

return IntPtr.Zero;
}

private Task<IntPtr[]> SendFormatRequest()
{
if (_requestedFormatsTcs == null || _requestedFormatsTcs.Task.IsCompleted)
Expand Down