Browse Source

Changing XRRMonitorInfo.Outputs from IntPtr to IntPtr*

Change XRRMonitorInfo.Outputs from IntPtr to IntPtr* and iterate over
all Outputs to detect the smallest pixeldensity.
pull/5178/head
Robin Dostal 6 years ago
parent
commit
4ce630e71a
  1. 43
      src/Avalonia.X11/X11Screens.cs
  2. 4
      src/Avalonia.X11/X11Structs.cs
  3. 4
      src/Avalonia.X11/XLib.cs

43
src/Avalonia.X11/X11Screens.cs

@ -66,7 +66,8 @@ namespace Avalonia.X11
private X11Screen[] _cache; private X11Screen[] _cache;
private X11Info _x11; private X11Info _x11;
private IntPtr _window; private IntPtr _window;
const int EDIDStructureLength = 32; // Length of a EDID-Block-Length(128 bytes), XRRGetOutputProperty multiplies offset and length by 4
public Randr15ScreensImpl(AvaloniaX11Platform platform, X11ScreensUserSettings settings) public Randr15ScreensImpl(AvaloniaX11Platform platform, X11ScreensUserSettings settings)
{ {
_settings = settings; _settings = settings;
@ -86,8 +87,7 @@ namespace Avalonia.X11
{ {
if(rrOutput == IntPtr.Zero) if(rrOutput == IntPtr.Zero)
return null; return null;
var output = Marshal.ReadInt64(rrOutput); var properties = XRRListOutputProperties(_x11.Display,rrOutput, out int propertyCount);
var properties = XRRListOutputProperties(_x11.Display,output, out int propertyCount);
var hasEDID = false; var hasEDID = false;
for(var pc = 0; pc < propertyCount; pc++) for(var pc = 0; pc < propertyCount; pc++)
{ {
@ -96,20 +96,20 @@ namespace Avalonia.X11
} }
if(!hasEDID) if(!hasEDID)
return null; return null;
XRRGetOutputProperty(_x11.Display, output, _x11.Atoms.RR_PROPERTY_RANDR_EDID, 0, 128, false, false, _x11.Atoms.AnyPropertyType, out int actualType, out int actualFormat, out int nItems, out _, out IntPtr prop); XRRGetOutputProperty(_x11.Display, rrOutput, _x11.Atoms.RR_PROPERTY_RANDR_EDID, 0, EDIDStructureLength, false, false, _x11.Atoms.AnyPropertyType, out IntPtr actualType, out int actualFormat, out int bytesAfter, out _, out IntPtr prop);
if(actualType != 19) // XA_INTEGER if(actualType != _x11.Atoms.XA_INTEGER)
return null; return null;
if(actualFormat != 8) if(actualFormat != 8) // Expecting an byte array
return null; return null;
var edid = new byte[nItems]; var edid = new byte[bytesAfter];
Marshal.Copy(prop,edid,0,nItems); Marshal.Copy(prop,edid,0,bytesAfter);
XFree(prop); XFree(prop);
XFree(new IntPtr(properties)); XFree(new IntPtr(properties));
if(edid.Length < 22) if(edid.Length < 22)
return null; return null;
var width = edid[21]; var width = edid[21]; // 0x15 1 Max. Horizontal Image Size cm.
var height = edid[22]; var height = edid[22]; // 0x16 1 Max. Vertical Image Size cm.
if(width == 0 && height == 0) if(width == 0 && height == 0)
return null; return null;
return new Size(width * 10, height * 10); return new Size(width * 10, height * 10);
@ -131,10 +131,25 @@ namespace Avalonia.X11
var name = Marshal.PtrToStringAnsi(namePtr); var name = Marshal.PtrToStringAnsi(namePtr);
XFree(namePtr); XFree(namePtr);
var bounds = new PixelRect(mon.X, mon.Y, mon.Width, mon.Height); var bounds = new PixelRect(mon.X, mon.Y, mon.Width, mon.Height);
var density = 1d; Size? pSize = null;
var pSize = GetPhysicalMonitorSizeFromEDID(mon.Outputs); double density = 0;
if (_settings.NamedScaleFactors?.TryGetValue(name, out density) != true && pSize != null) if (_settings.NamedScaleFactors?.TryGetValue(name, out density) != true)
density = X11Screen.GuessPixelDensity(bounds, pSize.Value); {
for(int o = 0; o < mon.NOutput; o++)
{
var outputSize = GetPhysicalMonitorSizeFromEDID(mon.Outputs[o]);
var outputDensity = 1d;
if(outputSize != null)
outputDensity = X11Screen.GuessPixelDensity(bounds, outputSize.Value);
if(density == 0 || density > outputDensity)
{
density = outputDensity;
pSize = outputSize;
}
}
}
if(density == 0)
density = 1;
density *= _settings.GlobalScaleFactor; density *= _settings.GlobalScaleFactor;
screens[c] = new X11Screen(bounds, mon.Primary != 0, name, pSize, density); screens[c] = new X11Screen(bounds, mon.Primary != 0, name, pSize, density);
} }

4
src/Avalonia.X11/X11Structs.cs

@ -1870,7 +1870,7 @@ namespace Avalonia.X11 {
public const string XNFontSet = "fontSet"; public const string XNFontSet = "fontSet";
} }
struct XRRMonitorInfo { unsafe struct XRRMonitorInfo {
public IntPtr Name; public IntPtr Name;
public int Primary; public int Primary;
public int Automatic; public int Automatic;
@ -1881,6 +1881,6 @@ namespace Avalonia.X11 {
public int Height; public int Height;
public int MWidth; public int MWidth;
public int MHeight; public int MHeight;
public IntPtr Outputs; public IntPtr* Outputs;
} }
} }

4
src/Avalonia.X11/XLib.cs

@ -502,10 +502,10 @@ namespace Avalonia.X11
XRRGetMonitors(IntPtr dpy, IntPtr window, bool get_active, out int nmonitors); XRRGetMonitors(IntPtr dpy, IntPtr window, bool get_active, out int nmonitors);
[DllImport(libX11Randr)] [DllImport(libX11Randr)]
public static extern IntPtr* XRRListOutputProperties(IntPtr dpy, long output, out int count); public static extern IntPtr* XRRListOutputProperties(IntPtr dpy, IntPtr output, out int count);
[DllImport(libX11Randr)] [DllImport(libX11Randr)]
public static extern int XRRGetOutputProperty(IntPtr dpy, long output, IntPtr atom, long offset, long length, bool _delete, bool pending, IntPtr req_type, out int actual_type, out int actual_format, out int nitems, out long bytes_after, out IntPtr prop); public static extern int XRRGetOutputProperty(IntPtr dpy, IntPtr output, IntPtr atom, int offset, int length, bool _delete, bool pending, IntPtr req_type, out IntPtr actual_type, out int actual_format, out int nitems, out long bytes_after, out IntPtr prop);
[DllImport(libX11Randr)] [DllImport(libX11Randr)]
public static extern void XRRSelectInput(IntPtr dpy, IntPtr window, RandrEventMask mask); public static extern void XRRSelectInput(IntPtr dpy, IntPtr window, RandrEventMask mask);

Loading…
Cancel
Save