|
|
|
@ -72,12 +72,12 @@ namespace Avalonia.X11 |
|
|
|
WaitConfigure, |
|
|
|
WaitPaint |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool overrideRedirect = false) |
|
|
|
{ |
|
|
|
_platform = platform; |
|
|
|
_popup = popupParent != null; |
|
|
|
_overrideRedirect = _popup || overrideRedirect; |
|
|
|
_overrideRedirect = _popup || overrideRedirect; |
|
|
|
_x11 = platform.Info; |
|
|
|
_mouse = new MouseDevice(); |
|
|
|
_touch = new TouchDevice(); |
|
|
|
@ -104,7 +104,7 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
// OpenGL seems to be do weird things to it's current window which breaks resize sometimes
|
|
|
|
_useRenderWindow = glfeature != null; |
|
|
|
|
|
|
|
|
|
|
|
var glx = glfeature as GlxPlatformGraphics; |
|
|
|
if (glx != null) |
|
|
|
visualInfo = *glx.Display.VisualInfo; |
|
|
|
@ -112,7 +112,7 @@ namespace Avalonia.X11 |
|
|
|
visualInfo = _x11.TransparentVisualInfo; |
|
|
|
|
|
|
|
var egl = glfeature as EglPlatformGraphics; |
|
|
|
|
|
|
|
|
|
|
|
var visual = IntPtr.Zero; |
|
|
|
var depth = 24; |
|
|
|
if (visualInfo != null) |
|
|
|
@ -120,7 +120,7 @@ namespace Avalonia.X11 |
|
|
|
visual = visualInfo.Value.visual; |
|
|
|
depth = (int)visualInfo.Value.depth; |
|
|
|
attr.colormap = XCreateColormap(_x11.Display, _x11.RootWindow, visualInfo.Value.visual, 0); |
|
|
|
valueMask |= SetWindowValuemask.ColorMap; |
|
|
|
valueMask |= SetWindowValuemask.ColorMap; |
|
|
|
} |
|
|
|
|
|
|
|
int defaultWidth = 0, defaultHeight = 0; |
|
|
|
@ -144,7 +144,7 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
_handle = XCreateWindow(_x11.Display, _x11.RootWindow, 10, 10, defaultWidth, defaultHeight, 0, |
|
|
|
depth, |
|
|
|
(int)CreateWindowArgs.InputOutput, |
|
|
|
(int)CreateWindowArgs.InputOutput, |
|
|
|
visual, |
|
|
|
new UIntPtr((uint)valueMask), ref attr); |
|
|
|
|
|
|
|
@ -184,10 +184,10 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
var surfaces = new List<object> |
|
|
|
{ |
|
|
|
new X11FramebufferSurface(_x11.DeferredDisplay, _renderHandle, |
|
|
|
new X11FramebufferSurface(_x11.DeferredDisplay, _renderHandle, |
|
|
|
depth, () => RenderScaling) |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (egl != null) |
|
|
|
surfaces.Insert(0, |
|
|
|
new EglGlPlatformSurface(new SurfaceInfo(this, _x11.DeferredDisplay, _handle, _renderHandle))); |
|
|
|
@ -201,7 +201,7 @@ namespace Avalonia.X11 |
|
|
|
UpdateSizeHints(null); |
|
|
|
|
|
|
|
_rawEventGrouper = new RawEventGrouper(DispatchInput, platform.EventGrouperDispatchQueue); |
|
|
|
|
|
|
|
|
|
|
|
_transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals); |
|
|
|
_transparencyHelper.SetTransparencyRequest(Array.Empty<WindowTransparencyLevel>()); |
|
|
|
|
|
|
|
@ -214,7 +214,7 @@ namespace Avalonia.X11 |
|
|
|
_nativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle); |
|
|
|
_nativeControlHost = new X11NativeControlHost(_platform, this); |
|
|
|
InitializeIme(); |
|
|
|
|
|
|
|
|
|
|
|
XChangeProperty(_x11.Display, _handle, _x11.Atoms.WM_PROTOCOLS, _x11.Atoms.XA_ATOM, 32, |
|
|
|
PropertyMode.Replace, new[] { _x11.Atoms.WM_DELETE_WINDOW, _x11.Atoms.WM_TAKE_FOCUS, _x11.Atoms._NET_WM_SYNC_REQUEST }, 3); |
|
|
|
|
|
|
|
@ -271,8 +271,8 @@ namespace Avalonia.X11 |
|
|
|
var decorations = MotifDecorations.Menu | MotifDecorations.Title | MotifDecorations.Border | |
|
|
|
MotifDecorations.Maximize | MotifDecorations.Minimize | MotifDecorations.ResizeH; |
|
|
|
|
|
|
|
if (_popup |
|
|
|
|| _systemDecorations == SystemDecorations.None) |
|
|
|
if (_popup |
|
|
|
|| _systemDecorations == SystemDecorations.None) |
|
|
|
decorations = 0; |
|
|
|
|
|
|
|
if (!_canResize) |
|
|
|
@ -302,7 +302,7 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
if (!_canResize) |
|
|
|
max = min = _realSize; |
|
|
|
|
|
|
|
|
|
|
|
if (preResize.HasValue) |
|
|
|
{ |
|
|
|
var desired = preResize.Value; |
|
|
|
@ -319,7 +319,7 @@ namespace Avalonia.X11 |
|
|
|
var flags = XSizeHintsFlags.PMinSize | XSizeHintsFlags.PResizeInc; |
|
|
|
if (_usePositioningFlags) |
|
|
|
flags |= XSizeHintsFlags.PPosition | XSizeHintsFlags.PSize; |
|
|
|
|
|
|
|
|
|
|
|
// People might be passing double.MaxValue
|
|
|
|
if (max.Width < 100000 && max.Height < 100000) |
|
|
|
{ |
|
|
|
@ -354,10 +354,10 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
public double RenderScaling |
|
|
|
{ |
|
|
|
get => Interlocked.CompareExchange(ref _scaling, 0.0, 0.0); |
|
|
|
private set => Interlocked.Exchange(ref _scaling, value); |
|
|
|
get => Interlocked.CompareExchange(ref _scaling, 0.0, 0.0); |
|
|
|
private set => Interlocked.Exchange(ref _scaling, value); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public double DesktopScaling => RenderScaling; |
|
|
|
|
|
|
|
public IEnumerable<object> Surfaces { get; } |
|
|
|
@ -394,7 +394,7 @@ namespace Avalonia.X11 |
|
|
|
public Action? LostFocus { get; set; } |
|
|
|
|
|
|
|
public Compositor Compositor => _platform.Compositor; |
|
|
|
|
|
|
|
|
|
|
|
private void OnEvent(ref XEvent ev) |
|
|
|
{ |
|
|
|
if (_inputRoot is null) |
|
|
|
@ -463,7 +463,7 @@ namespace Avalonia.X11 |
|
|
|
_inputRoot, new Point(ev.ButtonEvent.x, ev.ButtonEvent.y), delta, |
|
|
|
TranslateModifiers(ev.ButtonEvent.state)), ref ev); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
else if (ev.type == XEventName.ButtonRelease) |
|
|
|
{ |
|
|
|
@ -504,7 +504,7 @@ namespace Avalonia.X11 |
|
|
|
var npos = _configurePoint.Value; |
|
|
|
_configure = null; |
|
|
|
_configurePoint = null; |
|
|
|
|
|
|
|
|
|
|
|
var nsize = new PixelSize(cev.width, cev.height); |
|
|
|
var changedSize = _realSize != nsize; |
|
|
|
var changedPos = _position == null || npos != _position; |
|
|
|
@ -531,7 +531,7 @@ namespace Avalonia.X11 |
|
|
|
EnqueuePaint(); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (ev.type == XEventName.DestroyNotify |
|
|
|
else if (ev.type == XEventName.DestroyNotify |
|
|
|
&& ev.DestroyWindowEvent.window == _handle) |
|
|
|
{ |
|
|
|
Cleanup(true); |
|
|
|
@ -608,7 +608,7 @@ namespace Avalonia.X11 |
|
|
|
Resize(oldScaledSize, true, WindowResizeReason.DpiChange); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
@ -730,7 +730,7 @@ namespace Avalonia.X11 |
|
|
|
rv |= RawInputModifiers.Meta; |
|
|
|
return rv; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private SystemDecorations _systemDecorations = SystemDecorations.Full; |
|
|
|
private bool _canResize = true; |
|
|
|
private const int MaxWindowDimension = 100000; |
|
|
|
@ -740,7 +740,7 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
private (PixelSize minSize, PixelSize maxSize) _minMaxSize = (new PixelSize(1, 1), |
|
|
|
new PixelSize(MaxWindowDimension, MaxWindowDimension)); |
|
|
|
|
|
|
|
|
|
|
|
private double _scaling = 1; |
|
|
|
|
|
|
|
private void ScheduleInput(RawInputEventArgs args, ref XEvent xev) |
|
|
|
@ -781,14 +781,14 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
ScheduleInput(args); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void ScheduleInput(RawInputEventArgs args) |
|
|
|
{ |
|
|
|
if (args is RawPointerEventArgs mouse) |
|
|
|
mouse.Position = mouse.Position / RenderScaling; |
|
|
|
if (args is RawDragEvent drag) |
|
|
|
drag.Location = drag.Location / RenderScaling; |
|
|
|
|
|
|
|
|
|
|
|
_rawEventGrouper?.HandleEvent(args); |
|
|
|
} |
|
|
|
|
|
|
|
@ -824,14 +824,14 @@ namespace Avalonia.X11 |
|
|
|
XSyncSetCounter(_x11.Display, _xSyncCounter, _xSyncValue); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Invalidate(Rect rect) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public IInputRoot? InputRoot => _inputRoot; |
|
|
|
|
|
|
|
|
|
|
|
public void SetInputRoot(IInputRoot inputRoot) |
|
|
|
{ |
|
|
|
_inputRoot = inputRoot; |
|
|
|
@ -839,7 +839,7 @@ namespace Avalonia.X11 |
|
|
|
|
|
|
|
public void Dispose() |
|
|
|
{ |
|
|
|
Cleanup(false); |
|
|
|
Cleanup(false); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual object? TryGetFeature(Type featureType) |
|
|
|
@ -848,7 +848,7 @@ namespace Avalonia.X11 |
|
|
|
{ |
|
|
|
return _nativeMenuExporter; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (featureType == typeof(IStorageProvider)) |
|
|
|
{ |
|
|
|
return _storageProvider; |
|
|
|
@ -878,30 +878,30 @@ namespace Avalonia.X11 |
|
|
|
if(_cleaningUp) |
|
|
|
return; |
|
|
|
_cleaningUp = true; |
|
|
|
|
|
|
|
|
|
|
|
// Before doing anything else notify the TopLevel that ITopLevelImpl is no longer valid
|
|
|
|
if (_handle != IntPtr.Zero) |
|
|
|
Closed?.Invoke(); |
|
|
|
|
|
|
|
|
|
|
|
if (_rawEventGrouper != null) |
|
|
|
{ |
|
|
|
_rawEventGrouper.Dispose(); |
|
|
|
_rawEventGrouper = null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_transparencyHelper != null) |
|
|
|
{ |
|
|
|
_transparencyHelper.Dispose(); |
|
|
|
_transparencyHelper = null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_imeControl != null) |
|
|
|
{ |
|
|
|
_imeControl.Dispose(); |
|
|
|
_imeControl = null; |
|
|
|
_ime = null; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_xic != IntPtr.Zero) |
|
|
|
{ |
|
|
|
XDestroyIC(_xic); |
|
|
|
@ -913,7 +913,7 @@ namespace Avalonia.X11 |
|
|
|
XSyncDestroyCounter(_x11.Display, _xSyncCounter); |
|
|
|
_xSyncCounter = IntPtr.Zero; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_handle != IntPtr.Zero) |
|
|
|
{ |
|
|
|
_platform.Windows.Remove(_handle); |
|
|
|
@ -925,9 +925,9 @@ namespace Avalonia.X11 |
|
|
|
if (!fromDestroyNotification) |
|
|
|
XDestroyWindow(_x11.Display, handle); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_useRenderWindow && _renderHandle != IntPtr.Zero) |
|
|
|
{ |
|
|
|
{ |
|
|
|
_renderHandle = IntPtr.Zero; |
|
|
|
} |
|
|
|
|
|
|
|
@ -963,13 +963,13 @@ namespace Avalonia.X11 |
|
|
|
} |
|
|
|
|
|
|
|
public void Hide() => XUnmapWindow(_x11.Display, _handle); |
|
|
|
|
|
|
|
|
|
|
|
public Point PointToClient(PixelPoint point) => new Point((point.X - (_position ?? default).X) / RenderScaling, (point.Y - (_position ?? default).Y) / RenderScaling); |
|
|
|
|
|
|
|
public PixelPoint PointToScreen(Point point) => new PixelPoint( |
|
|
|
(int)(point.X * RenderScaling + (_position ?? default).X), |
|
|
|
(int)(point.Y * RenderScaling + (_position ?? default).Y)); |
|
|
|
|
|
|
|
|
|
|
|
public void SetSystemDecorations(SystemDecorations enabled) |
|
|
|
{ |
|
|
|
_systemDecorations = enabled == SystemDecorations.Full ? SystemDecorations.Full : SystemDecorations.None; |
|
|
|
@ -994,7 +994,7 @@ namespace Avalonia.X11 |
|
|
|
{ |
|
|
|
if (!force && clientSize == ClientSize) |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
var needImmediatePopupResize = clientSize != ClientSize; |
|
|
|
|
|
|
|
var pixelSize = ToPixelSize(clientSize); |
|
|
|
@ -1010,7 +1010,7 @@ namespace Avalonia.X11 |
|
|
|
Resized?.Invoke(ClientSize, reason); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void CanResize(bool value) |
|
|
|
{ |
|
|
|
_canResize = value; |
|
|
|
@ -1029,7 +1029,7 @@ namespace Avalonia.X11 |
|
|
|
} |
|
|
|
|
|
|
|
public IPlatformHandle Handle { get; } |
|
|
|
|
|
|
|
|
|
|
|
public PixelPoint Position |
|
|
|
{ |
|
|
|
get |
|
|
|
@ -1076,7 +1076,7 @@ namespace Avalonia.X11 |
|
|
|
public IMouseDevice MouseDevice => _mouse; |
|
|
|
public TouchDevice TouchDevice => _touch; |
|
|
|
|
|
|
|
public IPopupImpl? CreatePopup() |
|
|
|
public IPopupImpl? CreatePopup() |
|
|
|
=> _platform.Options.OverlayPopups ? null : new X11Window(_platform, this); |
|
|
|
|
|
|
|
public void Activate() |
|
|
|
@ -1131,7 +1131,7 @@ namespace Avalonia.X11 |
|
|
|
SendNetWMMessage (_x11.Atoms._NET_WM_MOVERESIZE, (IntPtr) pos.x, (IntPtr) pos.y, |
|
|
|
(IntPtr) side, |
|
|
|
(IntPtr) 1, (IntPtr)1); // left button
|
|
|
|
|
|
|
|
|
|
|
|
e.Pointer.Capture(null); |
|
|
|
} |
|
|
|
|
|
|
|
@ -1214,7 +1214,7 @@ namespace Avalonia.X11 |
|
|
|
var max = new PixelSize( |
|
|
|
(int)(maxSize.Width > maxDim ? maxDim : Math.Max(min.Width, maxSize.Width * RenderScaling)), |
|
|
|
(int)(maxSize.Height > maxDim ? maxDim : Math.Max(min.Height, maxSize.Height * RenderScaling))); |
|
|
|
|
|
|
|
|
|
|
|
_minMaxSize = (min, max); |
|
|
|
UpdateSizeHints(null); |
|
|
|
} |
|
|
|
@ -1223,7 +1223,7 @@ namespace Avalonia.X11 |
|
|
|
{ |
|
|
|
ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void SetEnabled(bool enable) |
|
|
|
{ |
|
|
|
_disabled = !enable; |
|
|
|
@ -1302,7 +1302,7 @@ namespace Avalonia.X11 |
|
|
|
out var prop); |
|
|
|
var ptr = (IntPtr*)prop.ToPointer(); |
|
|
|
var newAtoms = new HashSet<IntPtr>(); |
|
|
|
for (var c = 0; c < nitems.ToInt64(); c++) |
|
|
|
for (var c = 0; c < nitems.ToInt64(); c++) |
|
|
|
newAtoms.Add(*ptr); |
|
|
|
XFree(prop); |
|
|
|
foreach(var atom in atoms) |
|
|
|
@ -1314,7 +1314,7 @@ namespace Avalonia.X11 |
|
|
|
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, |
|
|
|
PropertyMode.Replace, newAtoms.ToArray(), newAtoms.Count); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SendNetWMMessage(_x11.Atoms._NET_WM_STATE, |
|
|
|
(IntPtr)(enable ? 1 : 0), |
|
|
|
atoms[0], |
|
|
|
|