mirror of https://github.com/adamdruppe/arsd.git
mixed mode dpi awareness
This commit is contained in:
parent
51747d64ba
commit
cb8acc5d2b
363
simpledisplay.d
363
simpledisplay.d
|
@ -136,6 +136,9 @@ interface->SetProgressValue(hwnd, 40, 100);
|
||||||
operating system and `color.d`, so it should just work most the
|
operating system and `color.d`, so it should just work most the
|
||||||
time, but there are a few caveats on some systems:
|
time, but there are a few caveats on some systems:
|
||||||
|
|
||||||
|
On Win32, you can pass `-L/subsystem:windows` if you don't want a
|
||||||
|
console to be automatically allocated.
|
||||||
|
|
||||||
Please note when compiling on Win64, you need to explicitly list
|
Please note when compiling on Win64, you need to explicitly list
|
||||||
`-Lgdi32.lib -Luser32.lib` on the build command. If you want the Windows
|
`-Lgdi32.lib -Luser32.lib` on the build command. If you want the Windows
|
||||||
subsystem too, use `-L/subsystem:windows -L/entry:mainCRTStartup`.
|
subsystem too, use `-L/subsystem:windows -L/entry:mainCRTStartup`.
|
||||||
|
@ -143,8 +146,9 @@ interface->SetProgressValue(hwnd, 40, 100);
|
||||||
If using ldc instead of dmd, use `-L/entry:wmainCRTStartup` instead of `mainCRTStartup`;
|
If using ldc instead of dmd, use `-L/entry:wmainCRTStartup` instead of `mainCRTStartup`;
|
||||||
note the "w".
|
note the "w".
|
||||||
|
|
||||||
On Win32, you can pass `-L/subsystem:windows` if you don't want a
|
I provided a `mixin EnableWindowsSubsystem;` helper to do those linker flags for you,
|
||||||
console to be automatically allocated.
|
but you still need to use dmd -m32mscoff or -m64 (which dub does by default too fyi).
|
||||||
|
See [EnableWindowsSubsystem] for more information.
|
||||||
|
|
||||||
On Mac, when compiling with X11, you need XQuartz and -L-L/usr/X11R6/lib passed to dmd. If using the Cocoa implementation on Mac, you need to pass `-L-framework -LCocoa` to dmd. For OpenGL, add `-L-framework -LOpenGL` to the build command.
|
On Mac, when compiling with X11, you need XQuartz and -L-L/usr/X11R6/lib passed to dmd. If using the Cocoa implementation on Mac, you need to pass `-L-framework -LCocoa` to dmd. For OpenGL, add `-L-framework -LOpenGL` to the build command.
|
||||||
|
|
||||||
|
@ -591,9 +595,24 @@ interface->SetProgressValue(hwnd, 40, 100);
|
||||||
/>
|
/>
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- old style -->
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> <!-- new style -->
|
||||||
|
<!-- Un-comment the line below to enable GDI-scaling in this project. This will enable text -->
|
||||||
|
<!-- to render crisply in DPI-unaware contexts -->
|
||||||
|
<!--<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>-->
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
</assembly>
|
</assembly>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also just distribute yourapp.exe.manifest as a separate file alongside yourapp.exe, or link it in to the exe with linker command lines `/manifest:embed` and `/manifestinput:yourfile.exe.manifest`.
|
||||||
|
|
||||||
|
Doing this lets you opt into various new things since Windows XP.
|
||||||
|
|
||||||
|
See: https://docs.microsoft.com/en-us/windows/win32/SbsCs/application-manifests
|
||||||
|
|
||||||
$(H2 Tips)
|
$(H2 Tips)
|
||||||
|
|
||||||
$(H3 Name conflicts)
|
$(H3 Name conflicts)
|
||||||
|
@ -1304,6 +1323,32 @@ version(without_opengl)
|
||||||
else
|
else
|
||||||
enum bool OpenGlEnabled = true;
|
enum bool OpenGlEnabled = true;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Adds the necessary pragmas to your application to use the Windows gui subsystem.
|
||||||
|
If you mix this in above your `main` function, you no longer need to use the linker
|
||||||
|
flags explicitly. It does the necessary version blocks for various compilers and runtimes.
|
||||||
|
|
||||||
|
It does nothing if not compiling for Windows, so you need not version it out yourself.
|
||||||
|
|
||||||
|
Please note that Windows gui subsystem applications must NOT use std.stdio's stdout and
|
||||||
|
stderr writeln. It will fail and throw an exception.
|
||||||
|
|
||||||
|
This will NOT work with plain `dmd` on Windows; you must use `dmd -m32mscoff` or `dmd -m64`.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 24, 2021 (dub v10.4)
|
||||||
|
+/
|
||||||
|
mixin template EnableWindowsSubsystem() {
|
||||||
|
version(Windows)
|
||||||
|
version(CRuntime_Microsoft) {
|
||||||
|
pragma(linkerDirective, "/subsystem:windows");
|
||||||
|
version(LDC)
|
||||||
|
pragma(linkerDirective, "/entry:wmainCRTStartup");
|
||||||
|
else
|
||||||
|
pragma(linkerDirective, "/entry:mainCRTStartup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
After selecting a type from [WindowTypes], you may further customize
|
After selecting a type from [WindowTypes], you may further customize
|
||||||
|
@ -1460,6 +1505,8 @@ string sdpyWindowClass () {
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Returns the DPI of the default monitor. [0] is width, [1] is height (they are usually the same though). You may wish to round the numbers off.
|
Returns the DPI of the default monitor. [0] is width, [1] is height (they are usually the same though). You may wish to round the numbers off.
|
||||||
|
|
||||||
|
If you want per-monitor dpi values, check [SimpleWindow.actualDpi], but you can fall back to this if it returns 0.
|
||||||
+/
|
+/
|
||||||
float[2] getDpi() {
|
float[2] getDpi() {
|
||||||
float[2] dpi;
|
float[2] dpi;
|
||||||
|
@ -1574,6 +1621,32 @@ TrueColorImage trueColorImageFromNativeHandle(NativeWindowHandle handle, int wid
|
||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(Windows) extern(Windows) private alias SetProcessDpiAwarenessContext_t = BOOL function(HANDLE);
|
||||||
|
version(Windows) extern(Windows) private __gshared UINT function(HWND) GetDpiForWindow;
|
||||||
|
version(Windows) extern(Windows) private __gshared BOOL function(UINT, UINT, PVOID, UINT, UINT) SystemParametersInfoForDpi;
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
shared static this() {
|
||||||
|
auto lib = LoadLibrary("User32.dll");
|
||||||
|
if(lib is null)
|
||||||
|
return;
|
||||||
|
scope(exit)
|
||||||
|
FreeLibrary(lib);
|
||||||
|
|
||||||
|
SetProcessDpiAwarenessContext_t SetProcessDpiAwarenessContext = cast(SetProcessDpiAwarenessContext_t) GetProcAddress(lib, "SetProcessDpiAwarenessContext");
|
||||||
|
|
||||||
|
if(SetProcessDpiAwarenessContext is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
enum DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = cast(HANDLE) -4;
|
||||||
|
if(!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
|
||||||
|
//writeln(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
GetDpiForWindow = cast(typeof(GetDpiForWindow)) GetProcAddress(lib, "GetDpiForWindow");
|
||||||
|
SystemParametersInfoForDpi = cast(typeof(SystemParametersInfoForDpi)) GetProcAddress(lib, "SystemParametersInfoForDpi");
|
||||||
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
The flagship window class.
|
The flagship window class.
|
||||||
|
|
||||||
|
@ -1612,6 +1685,154 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
||||||
return trueColorImageFromNativeHandle(impl.window, width, height);
|
return trueColorImageFromNativeHandle(impl.window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Returns the actual physical DPI for the window on its current display monitor. If the window
|
||||||
|
straddles monitors, it will return the value of one or the other in a platform-defined manner.
|
||||||
|
|
||||||
|
Please note this function may return zero if it doesn't know the answer!
|
||||||
|
|
||||||
|
|
||||||
|
On Windows, it returns the dpi per monitor if the operating system supports it (Windows 10),
|
||||||
|
or a system dpi value if not, which will live-update if the OS supports it (Windows 8 and up).
|
||||||
|
|
||||||
|
On X, it reads the xrandr extension to determine monitor positions and sizes. On some systems,
|
||||||
|
this is not provided, meaning it will return 0. Otherwise, it will determine which monitor the
|
||||||
|
window primarily resides on by checking the center point of the window against the monitor map.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
0 if unknown. Otherwise, a rounded value of dots per inch reported by the monitor. It
|
||||||
|
assumes the X and Y dpi are the same.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 26, 2021 (dub v10.4)
|
||||||
|
|
||||||
|
Bugs:
|
||||||
|
Probably plenty. I haven't done a lot of tests on this. I know it doesn't
|
||||||
|
|
||||||
|
See_Also:
|
||||||
|
[getDpi] gives the value provided for the default monitor. Not necessarily the same
|
||||||
|
as this since the window many be on a different monitor, but it is a reasonable fallback
|
||||||
|
to use if `actualDpi` returns 0.
|
||||||
|
|
||||||
|
[onDpiChanged] is changed when `actualDpi` has changed.
|
||||||
|
+/
|
||||||
|
int actualDpi() {
|
||||||
|
if(!actualDpiLoadAttempted) {
|
||||||
|
// FIXME: do the actual monitor we are on
|
||||||
|
// and on X this is a good chance to load the monitor map.
|
||||||
|
version(Windows) {
|
||||||
|
if(GetDpiForWindow)
|
||||||
|
actualDpi_ = GetDpiForWindow(impl.hwnd);
|
||||||
|
} else version(X11) {
|
||||||
|
if(!xRandrInfoLoadAttemped) {
|
||||||
|
xRandrInfoLoadAttemped = true;
|
||||||
|
if(!XRandrLibrary.attempted) {
|
||||||
|
XRandrLibrary.loadDynamicLibrary();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(XRandrLibrary.loadSuccessful) {
|
||||||
|
auto display = XDisplayConnection.get;
|
||||||
|
int scratch;
|
||||||
|
int major, minor;
|
||||||
|
if(!XRRQueryExtension(display, &xrrEventBase, &scratch))
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
XRRQueryVersion(display, &major, &minor);
|
||||||
|
if(major <= 1 && minor < 5)
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
int count;
|
||||||
|
XRRMonitorInfo *monitors = XRRGetMonitors(display, RootWindow(display, DefaultScreen(display)), true, &count);
|
||||||
|
if(monitors is null)
|
||||||
|
goto fallback;
|
||||||
|
scope(exit) XRRFreeMonitors(monitors);
|
||||||
|
|
||||||
|
MonitorInfo.info = MonitorInfo.info[0 .. 0];
|
||||||
|
MonitorInfo.info.assumeSafeAppend();
|
||||||
|
foreach(monitor; monitors[0 .. count]) {
|
||||||
|
MonitorInfo.info ~= MonitorInfo(
|
||||||
|
Rectangle(Point(monitor.x, monitor.y), Size(monitor.width, monitor.height)),
|
||||||
|
Size(monitor.mwidth, monitor.mheight),
|
||||||
|
minInternal(
|
||||||
|
// millimeter to int then rounding up.
|
||||||
|
cast(int)(monitor.width * 25.4 / monitor.mwidth + 0.5),
|
||||||
|
cast(int)(monitor.height * 25.4 / monitor.mheight + 0.5)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//import std.stdio; writeln("Here", MonitorInfo.info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(XRandrLibrary.loadSuccessful) {
|
||||||
|
updateActualDpi(true);
|
||||||
|
//import std.stdio; writeln("updated");
|
||||||
|
|
||||||
|
if(!requestedInput) {
|
||||||
|
// this is what requests live updates should the configuration change
|
||||||
|
// each time you select input, it sends an initial event, so very important
|
||||||
|
// to not get into a loop of selecting input, getting event, updating data,
|
||||||
|
// and reselecting input...
|
||||||
|
requestedInput = true;
|
||||||
|
XRRSelectInput(display, impl.window, RRScreenChangeNotifyMask);
|
||||||
|
//import std.stdio; writeln("requested input");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fallback:
|
||||||
|
// make sure we disable events that aren't coming
|
||||||
|
xrrEventBase = -1;
|
||||||
|
// best guess...
|
||||||
|
actualDpi_ = cast(int) getDpi()[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actualDpiLoadAttempted = true;
|
||||||
|
}
|
||||||
|
return actualDpi_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actualDpi_;
|
||||||
|
private bool actualDpiLoadAttempted;
|
||||||
|
|
||||||
|
version(X11) private {
|
||||||
|
bool requestedInput;
|
||||||
|
static bool xRandrInfoLoadAttemped;
|
||||||
|
struct MonitorInfo {
|
||||||
|
Rectangle position;
|
||||||
|
Size size;
|
||||||
|
int dpi;
|
||||||
|
|
||||||
|
static MonitorInfo[] info;
|
||||||
|
}
|
||||||
|
int screenPositionX;
|
||||||
|
int screenPositionY;
|
||||||
|
void updateActualDpi(bool loadingNow = false) {
|
||||||
|
if(!loadingNow && !actualDpiLoadAttempted)
|
||||||
|
actualDpi(); // just to make it do the load
|
||||||
|
foreach(idx, m; MonitorInfo.info) {
|
||||||
|
if(m.position.contains(Point(screenPositionX + this.width / 2, screenPositionY + this.height / 2))) {
|
||||||
|
bool changed = actualDpi_ && actualDpi_ != m.dpi;
|
||||||
|
actualDpi_ = m.dpi;
|
||||||
|
//import std.stdio; writeln("monitor ", idx);
|
||||||
|
if(changed && onDpiChanged)
|
||||||
|
onDpiChanged();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sent when the window is moved to a new DPI context, for example, when it is dragged between monitors
|
||||||
|
or if the window is moved to a new remote connection or a monitor is hot-swapped.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 26, 2021 (dub v10.4)
|
||||||
|
|
||||||
|
See_Also:
|
||||||
|
[actualDpi]
|
||||||
|
+/
|
||||||
|
void delegate() onDpiChanged;
|
||||||
|
|
||||||
version(X11) {
|
version(X11) {
|
||||||
void recreateAfterDisconnect() {
|
void recreateAfterDisconnect() {
|
||||||
if(!stateDiscarded) return;
|
if(!stateDiscarded) return;
|
||||||
|
@ -1623,6 +1844,10 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
||||||
|
|
||||||
activeScreenPainter = null; // should already be done but just to confirm
|
activeScreenPainter = null; // should already be done but just to confirm
|
||||||
|
|
||||||
|
actualDpi_ = 0;
|
||||||
|
actualDpiLoadAttempted = false;
|
||||||
|
xRandrInfoLoadAttemped = false;
|
||||||
|
|
||||||
impl.createWindow(_width, _height, _title, openglMode, _parent);
|
impl.createWindow(_width, _height, _title, openglMode, _parent);
|
||||||
|
|
||||||
if(auto dh = dropHandler) {
|
if(auto dh = dropHandler) {
|
||||||
|
@ -11014,12 +11239,22 @@ version(Windows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
int oldWidth;
|
private int oldWidth;
|
||||||
int oldHeight;
|
private int oldHeight;
|
||||||
bool inSizeMove;
|
private bool inSizeMove;
|
||||||
|
|
||||||
int bmpWidth;
|
/++
|
||||||
int bmpHeight;
|
If this is true, the live resize events will trigger all the size things as they drag. If false, those events only come when the size is complete; when the user lets go of the mouse button.
|
||||||
|
|
||||||
|
History:
|
||||||
|
Added November 23, 2021
|
||||||
|
|
||||||
|
Not fully stable, may be moved out of the impl struct.
|
||||||
|
+/
|
||||||
|
bool doLiveResizing;
|
||||||
|
|
||||||
|
private int bmpWidth;
|
||||||
|
private int bmpHeight;
|
||||||
|
|
||||||
// the extern(Windows) wndproc should just forward to this
|
// the extern(Windows) wndproc should just forward to this
|
||||||
LRESULT windowProcedure(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
|
LRESULT windowProcedure(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
@ -11057,6 +11292,40 @@ version(Windows) {
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x02E0 /*WM_DPICHANGED*/:
|
||||||
|
this.actualDpi_ = LOWORD(wParam); // hiword is the y param but it is the same per docs
|
||||||
|
|
||||||
|
RECT* prcNewWindow = cast(RECT*)lParam;
|
||||||
|
// docs say this is the recommended position and we should honor it
|
||||||
|
SetWindowPos(hwnd,
|
||||||
|
null,
|
||||||
|
prcNewWindow.left,
|
||||||
|
prcNewWindow.top,
|
||||||
|
prcNewWindow.right - prcNewWindow.left,
|
||||||
|
prcNewWindow.bottom - prcNewWindow.top,
|
||||||
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
// doing this because of https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/DPIAwarenessPerWindow/client/DpiAwarenessContext.cpp
|
||||||
|
// im not sure it is completely correct
|
||||||
|
// but without it the tabs and such do look weird as things change.
|
||||||
|
{
|
||||||
|
LOGFONT lfText;
|
||||||
|
SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, lfText.sizeof, &lfText, FALSE, this.actualDpi_);
|
||||||
|
HFONT hFontNew = CreateFontIndirect(&lfText);
|
||||||
|
if (hFontNew)
|
||||||
|
{
|
||||||
|
//DeleteObject(hFontOld);
|
||||||
|
static extern(Windows) BOOL helper(HWND hWnd, LPARAM lParam) {
|
||||||
|
SendMessage(hWnd, WM_SETFONT, cast(WPARAM)lParam, MAKELPARAM(TRUE, 0));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
EnumChildWindows(hwnd, &helper, cast(LPARAM) hFontNew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.onDpiChanged)
|
||||||
|
this.onDpiChanged();
|
||||||
|
break;
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
if(wParam == 1 /* SIZE_MINIMIZED */)
|
if(wParam == 1 /* SIZE_MINIMIZED */)
|
||||||
break;
|
break;
|
||||||
|
@ -11066,7 +11335,7 @@ version(Windows) {
|
||||||
// I want to avoid tearing in the windows (my code is inefficient
|
// I want to avoid tearing in the windows (my code is inefficient
|
||||||
// so this is a hack around that) so while sizing, we don't trigger,
|
// so this is a hack around that) so while sizing, we don't trigger,
|
||||||
// but we do want to trigger on events like mazimize.
|
// but we do want to trigger on events like mazimize.
|
||||||
if(!inSizeMove)
|
if(!inSizeMove || doLiveResizing)
|
||||||
goto size_changed;
|
goto size_changed;
|
||||||
break;
|
break;
|
||||||
/+
|
/+
|
||||||
|
@ -12177,10 +12446,64 @@ extern(C) @nogc:
|
||||||
__gshared bool XRenderLibrarySuccessfullyLoaded = true;
|
__gshared bool XRenderLibrarySuccessfullyLoaded = true;
|
||||||
mixin DynamicLoad!(XRender, "Xrender", 1, XRenderLibrarySuccessfullyLoaded) XRenderLibrary;
|
mixin DynamicLoad!(XRender, "Xrender", 1, XRenderLibrarySuccessfullyLoaded) XRenderLibrary;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* XRender } */
|
/* XRender } */
|
||||||
|
|
||||||
|
/* Xrandr { */
|
||||||
|
|
||||||
|
struct XRRMonitorInfo {
|
||||||
|
Atom name;
|
||||||
|
Bool primary;
|
||||||
|
Bool automatic;
|
||||||
|
int noutput;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int mwidth;
|
||||||
|
int mheight;
|
||||||
|
/*RROutput*/ void *outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct XRRScreenChangeNotifyEvent {
|
||||||
|
int type; /* event base */
|
||||||
|
c_ulong serial; /* # of last request processed by server */
|
||||||
|
Bool send_event; /* true if this came from a SendEvent request */
|
||||||
|
Display *display; /* Display the event was read from */
|
||||||
|
Window window; /* window which selected for this event */
|
||||||
|
Window root; /* Root window for changed screen */
|
||||||
|
Time timestamp; /* when the screen change occurred */
|
||||||
|
Time config_timestamp; /* when the last configuration change */
|
||||||
|
ushort/*SizeID*/ size_index;
|
||||||
|
ushort/*SubpixelOrder*/ subpixel_order;
|
||||||
|
ushort/*Rotation*/ rotation;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int mwidth;
|
||||||
|
int mheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RRScreenChangeNotify = 0;
|
||||||
|
|
||||||
|
enum RRScreenChangeNotifyMask = 1;
|
||||||
|
|
||||||
|
__gshared int xrrEventBase = -1;
|
||||||
|
|
||||||
|
|
||||||
|
interface XRandr {
|
||||||
|
extern(C) @nogc:
|
||||||
|
Bool XRRQueryExtension (Display *dpy, int *event_base_return, int *error_base_return);
|
||||||
|
Status XRRQueryVersion (Display *dpy, int *major_version_return, int *minor_version_return);
|
||||||
|
|
||||||
|
XRRMonitorInfo * XRRGetMonitors(Display *dpy, Window window, Bool get_active, int *nmonitors);
|
||||||
|
void XRRFreeMonitors(XRRMonitorInfo *monitors);
|
||||||
|
|
||||||
|
void XRRSelectInput(Display *dpy, Window window, int mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
__gshared bool XRandrLibrarySuccessfullyLoaded = true;
|
||||||
|
mixin DynamicLoad!(XRandr, "Xrandr", 2, XRandrLibrarySuccessfullyLoaded) XRandrLibrary;
|
||||||
|
/* Xrandr } */
|
||||||
|
|
||||||
/* Xft { */
|
/* Xft { */
|
||||||
|
|
||||||
// actually freetype
|
// actually freetype
|
||||||
|
@ -13893,6 +14216,18 @@ version(X11) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(xrrEventBase != -1 && e.type == xrrEventBase + RRScreenChangeNotify) {
|
||||||
|
if(auto win = e.xany.window in SimpleWindow.nativeMapping) {
|
||||||
|
// we get this because of the RRScreenChangeNotifyMask
|
||||||
|
|
||||||
|
// this isn't actually an ideal way to do it since it wastes time
|
||||||
|
// but meh it is simple and it works.
|
||||||
|
win.actualDpiLoadAttempted = false;
|
||||||
|
SimpleWindow.xRandrInfoLoadAttemped = false;
|
||||||
|
win.updateActualDpi(); // trigger a reload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch(e.type) {
|
switch(e.type) {
|
||||||
case EventType.SelectionClear:
|
case EventType.SelectionClear:
|
||||||
if(auto win = e.xselectionclear.window in SimpleWindow.nativeMapping) {
|
if(auto win = e.xselectionclear.window in SimpleWindow.nativeMapping) {
|
||||||
|
@ -14029,6 +14364,10 @@ version(X11) {
|
||||||
if(auto win = event.window in SimpleWindow.nativeMapping) {
|
if(auto win = event.window in SimpleWindow.nativeMapping) {
|
||||||
//version(sdddd) { import std.stdio; writeln(" w=", event.width, "; h=", event.height); }
|
//version(sdddd) { import std.stdio; writeln(" w=", event.width, "; h=", event.height); }
|
||||||
|
|
||||||
|
win.screenPositionX = event.x;
|
||||||
|
win.screenPositionY = event.y;
|
||||||
|
win.updateActualDpi();
|
||||||
|
|
||||||
recordX11Resize(display, *win, event.width, event.height);
|
recordX11Resize(display, *win, event.width, event.height);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -20516,4 +20855,8 @@ void guiAbortProcess(string msg) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int minInternal(int a, int b) {
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
private alias scriptable = arsd_jsvar_compatible;
|
private alias scriptable = arsd_jsvar_compatible;
|
||||||
|
|
Loading…
Reference in New Issue