Browse Source

Merge pull request #10895 from AvaloniaUI/linux-frame-position

X11 - Return frame position for Window.Position
pull/10953/head
Nikita Tsukanov 4 years ago
committed by GitHub
parent
commit
cce3fea3a6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Avalonia.X11/X11Window.Ime.cs
  2. 69
      src/Avalonia.X11/X11Window.cs

2
src/Avalonia.X11/X11Window.Ime.cs

@ -89,7 +89,7 @@ namespace Avalonia.X11
} }
} }
private void UpdateImePosition() => _imeControl?.UpdateWindowInfo(Position, RenderScaling); private void UpdateImePosition() => _imeControl?.UpdateWindowInfo(_position ?? default, RenderScaling);
private void HandleKeyEvent(ref XEvent ev) private void HandleKeyEvent(ref XEvent ev)
{ {

69
src/Avalonia.X11/X11Window.cs

@ -124,7 +124,7 @@ namespace Avalonia.X11
if (!_popup && Screen != null) if (!_popup && Screen != null)
{ {
var monitor = Screen.AllScreens.OrderBy(x => x.Scaling) var monitor = Screen.AllScreens.OrderBy(x => x.Scaling)
.FirstOrDefault(m => m.Bounds.Contains(Position)); .FirstOrDefault(m => m.Bounds.Contains(_position ?? default));
if (monitor != null) if (monitor != null)
{ {
@ -326,23 +326,16 @@ namespace Avalonia.X11
{ {
get get
{ {
XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_FRAME_EXTENTS, IntPtr.Zero, var extents = GetFrameExtents();
new IntPtr(4), false, (IntPtr)Atom.AnyPropertyType, out var _,
out var _, out var nitems, out var _, out var prop);
if (nitems.ToInt64() != 4) if(extents == null)
{ {
// Window hasn't been mapped by the WM yet, so can't get the extents.
return null; return null;
} }
var data = (IntPtr*)prop.ToPointer();
var extents = new Thickness(data[0].ToInt32(), data[2].ToInt32(), data[1].ToInt32(), data[3].ToInt32());
XFree(prop);
return new Size( return new Size(
(_realSize.Width + extents.Left + extents.Right) / RenderScaling, (_realSize.Width + extents.Value.Left + extents.Value.Right) / RenderScaling,
(_realSize.Height + extents.Top + extents.Bottom) / RenderScaling); (_realSize.Height + extents.Value.Top + extents.Value.Bottom) / RenderScaling);
} }
} }
@ -556,6 +549,25 @@ namespace Avalonia.X11
} }
} }
private Thickness? GetFrameExtents()
{
XGetWindowProperty(_x11.Display, _handle, _x11.Atoms._NET_FRAME_EXTENTS, IntPtr.Zero,
new IntPtr(4), false, (IntPtr)Atom.AnyPropertyType, out var _,
out var _, out var nitems, out var _, out var prop);
if (nitems.ToInt64() != 4)
{
// Window hasn't been mapped by the WM yet, so can't get the extents.
return null;
}
var data = (IntPtr*)prop.ToPointer();
var extents = new Thickness(data[0].ToInt32(), data[2].ToInt32(), data[1].ToInt32(), data[3].ToInt32());
XFree(prop);
return extents;
}
private bool UpdateScaling(bool skipResize = false) private bool UpdateScaling(bool skipResize = false)
{ {
double newScaling; double newScaling;
@ -564,7 +576,7 @@ namespace Avalonia.X11
else else
{ {
var monitor = _platform.X11Screens.Screens.OrderBy(x => x.Scaling) var monitor = _platform.X11Screens.Screens.OrderBy(x => x.Scaling)
.FirstOrDefault(m => m.Bounds.Contains(Position)); .FirstOrDefault(m => m.Bounds.Contains(_position ?? default));
newScaling = monitor?.Scaling ?? RenderScaling; newScaling = monitor?.Scaling ?? RenderScaling;
} }
@ -916,11 +928,11 @@ namespace Avalonia.X11
public void Hide() => XUnmapWindow(_x11.Display, _handle); public void Hide() => XUnmapWindow(_x11.Display, _handle);
public Point PointToClient(PixelPoint point) => new Point((point.X - Position.X) / RenderScaling, (point.Y - Position.Y) / RenderScaling); 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( public PixelPoint PointToScreen(Point point) => new PixelPoint(
(int)(point.X * RenderScaling + Position.X), (int)(point.X * RenderScaling + (_position ?? default).X),
(int)(point.Y * RenderScaling + Position.Y)); (int)(point.Y * RenderScaling + (_position ?? default).Y));
public void SetSystemDecorations(SystemDecorations enabled) public void SetSystemDecorations(SystemDecorations enabled)
{ {
@ -984,20 +996,36 @@ namespace Avalonia.X11
public PixelPoint Position public PixelPoint Position
{ {
get => _position ?? default; get
{
if(_position == null)
{
return default;
}
var extents = GetFrameExtents();
if(extents == null)
{
extents = default(Thickness);
}
return new PixelPoint(_position.Value.X - (int)extents.Value.Left, _position.Value.Y - (int)extents.Value.Top);
}
set set
{ {
if(!_usePositioningFlags) if (!_usePositioningFlags)
{ {
_usePositioningFlags = true; _usePositioningFlags = true;
UpdateSizeHints(null); UpdateSizeHints(null);
} }
var changes = new XWindowChanges var changes = new XWindowChanges
{ {
x = (int)value.X, x = value.X,
y = (int)value.Y y = (int)value.Y
}; };
XConfigureWindow(_x11.Display, _handle, ChangeWindowFlags.CWX | ChangeWindowFlags.CWY, XConfigureWindow(_x11.Display, _handle, ChangeWindowFlags.CWX | ChangeWindowFlags.CWY,
ref changes); ref changes);
XFlush(_x11.Display); XFlush(_x11.Display);
@ -1006,7 +1034,6 @@ namespace Avalonia.X11
_position = value; _position = value;
PositionChanged?.Invoke(value); PositionChanged?.Invoke(value);
} }
} }
} }

Loading…
Cancel
Save