mirror of https://github.com/adamdruppe/arsd.git
mroe dpi stuff
This commit is contained in:
parent
28f09ae118
commit
49829f3f48
60
minigui.d
60
minigui.d
|
@ -604,7 +604,19 @@ class Widget : ReflectableProperties {
|
|||
// avoid this it just forwards to a soon-to-be-deprecated function and is not remotely stable
|
||||
// I'll think up something better eventually
|
||||
protected final int defaultLineHeight() {
|
||||
return scaleWithDpi(Window.lineHeight);
|
||||
auto cs = getComputedStyle();
|
||||
if(cs.font && !cs.font.isNull)
|
||||
return cs.font.height() * 5 / 4;
|
||||
else
|
||||
return scaleWithDpi(Window.lineHeight);
|
||||
}
|
||||
|
||||
protected final int defaultTextWidth(const(char)[] text) {
|
||||
auto cs = getComputedStyle();
|
||||
if(cs.font && !cs.font.isNull)
|
||||
return cs.font.stringWidth(text);
|
||||
else
|
||||
return scaleWithDpi(Window.lineHeight * cast(int) text.length / 2);
|
||||
}
|
||||
|
||||
/++
|
||||
|
@ -3951,8 +3963,16 @@ struct StyleInformation {
|
|||
this.visualTheme = WidgetPainter.visualTheme;
|
||||
}
|
||||
|
||||
/// Forwards to [Widget.Style]
|
||||
// through the [VisualTheme]
|
||||
/++
|
||||
Forwards to [Widget.Style]
|
||||
|
||||
Bugs:
|
||||
It is supposed to fall back to the [VisualTheme] if
|
||||
the style doesn't override the default, but that is
|
||||
not generally implemented. Many of them may end up
|
||||
being explicit overloads instead of the generic
|
||||
opDispatch fallback, like [font] is now.
|
||||
+/
|
||||
public @property opDispatch(string name)() {
|
||||
typeof(__traits(getMember, Widget.Style.init, name)()) prop;
|
||||
w.useStyleProperties((scope Widget.Style props) {
|
||||
|
@ -3962,6 +3982,25 @@ struct StyleInformation {
|
|||
return prop;
|
||||
}
|
||||
|
||||
/++
|
||||
Returns the cached font object associated with the widget,
|
||||
if overridden by the [Widget.Style|Style], or the [VisualTheme] if not.
|
||||
|
||||
History:
|
||||
Prior to March 21, 2022 (dub v10.7), `font` went through
|
||||
[opDispatch], which did not use the cache. You can now call it
|
||||
repeatedly without guilt.
|
||||
+/
|
||||
public @property OperatingSystemFont font() {
|
||||
OperatingSystemFont prop;
|
||||
w.useStyleProperties((scope Widget.Style props) {
|
||||
prop = props.fontCached;
|
||||
});
|
||||
if(prop is null)
|
||||
prop = visualTheme.defaultFontCached;
|
||||
return prop;
|
||||
}
|
||||
|
||||
@property {
|
||||
// Layout helpers. Currently just forwarding since I haven't made up my mind on a better way.
|
||||
/** */ int paddingLeft() { return w.paddingLeft(); }
|
||||
|
@ -8982,6 +9021,8 @@ class Labeled(T) : Widget {
|
|||
override int marginTop() { return 4; }
|
||||
override int marginBottom() { return 4; }
|
||||
|
||||
// FIXME: i should prolly call it value as well as content tbh
|
||||
|
||||
///
|
||||
@property string content() {
|
||||
return lineEdit.content;
|
||||
|
@ -10265,10 +10306,10 @@ class MenuItem : MouseActivatedWidget {
|
|||
|
||||
override int maxHeight() { return defaultLineHeight + 4; }
|
||||
override int minHeight() { return defaultLineHeight + 4; }
|
||||
override int minWidth() { return defaultLineHeight * cast(int) label.length + 8; }
|
||||
override int minWidth() { return defaultTextWidth(label) + 8 + scaleWithDpi(12); }
|
||||
override int maxWidth() {
|
||||
if(cast(MenuBar) parent) {
|
||||
return defaultLineHeight / 2 * cast(int) label.length + 8;
|
||||
return minWidth();
|
||||
}
|
||||
return int.max;
|
||||
}
|
||||
|
@ -11417,6 +11458,8 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
|
|||
});
|
||||
}
|
||||
|
||||
private string lastContentBlur;
|
||||
|
||||
override void defaultEventHandler_blur(Event ev) {
|
||||
super.defaultEventHandler_blur(ev);
|
||||
if(parentWindow.win.closed) return;
|
||||
|
@ -11430,8 +11473,11 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
|
|||
}
|
||||
}
|
||||
|
||||
auto evt = new ChangeEvent!string(this, &this.content);
|
||||
evt.dispatch();
|
||||
if(this.content != lastContentBlur) {
|
||||
auto evt = new ChangeEvent!string(this, &this.content);
|
||||
evt.dispatch();
|
||||
lastContentBlur = this.content;
|
||||
}
|
||||
}
|
||||
|
||||
version(custom_widgets)
|
||||
|
|
120
simpledisplay.d
120
simpledisplay.d
|
@ -559,6 +559,10 @@ interface->SetProgressValue(hwnd, 40, 100);
|
|||
|
||||
$(H2 Platform-specific tips and tricks)
|
||||
|
||||
X_tips:
|
||||
|
||||
On X11, if you set an environment variable, `ARSD_SCALING_FACTOR`, you can control the per-monitor DPI scaling returned to the application. The format is `ARSD_SCALING_FACTOR=2;1`, for example, to set 2x scaling on your first monitor and 1x scaling on your second monitor. Support for this was added on March 22, 2022, the dub 10.7 release.
|
||||
|
||||
Windows_tips:
|
||||
|
||||
You can add icons or manifest files to your exe using a resource file.
|
||||
|
@ -1506,7 +1510,7 @@ 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 logical 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. This isn't necessarily related to the physical side of the screen; it is associated with a user-defined scaling factor.
|
||||
|
||||
If you want per-monitor dpi values, check [SimpleWindow.actualDpi], but you can fall back to this if it returns 0.
|
||||
+/
|
||||
|
@ -1521,37 +1525,52 @@ float[2] getDpi() {
|
|||
auto screen = DefaultScreen(display);
|
||||
|
||||
void fallback() {
|
||||
/+
|
||||
// 25.4 millimeters in an inch...
|
||||
dpi[0] = cast(float) DisplayWidth(display, screen) / DisplayWidthMM(display, screen) * 25.4;
|
||||
dpi[1] = cast(float) DisplayHeight(display, screen) / DisplayHeightMM(display, screen) * 25.4;
|
||||
+/
|
||||
|
||||
// the physical size isn't actually as important as the logical size since this is
|
||||
// all about scaling really
|
||||
dpi[0] = 96;
|
||||
dpi[1] = 96;
|
||||
}
|
||||
|
||||
char* resourceString = XResourceManagerString(display);
|
||||
XrmInitialize();
|
||||
|
||||
if (resourceString) {
|
||||
auto db = XrmGetStringDatabase(resourceString);
|
||||
XrmValue value;
|
||||
char* type;
|
||||
if (XrmGetResource(db, "Xft.dpi", "String", &type, &value) == true) {
|
||||
if (value.addr) {
|
||||
import core.stdc.stdlib;
|
||||
dpi[0] = atof(cast(char*) value.addr);
|
||||
dpi[1] = dpi[0];
|
||||
} else {
|
||||
fallback();
|
||||
}
|
||||
} else {
|
||||
fallback();
|
||||
}
|
||||
} else {
|
||||
auto xft = getXftDpi();
|
||||
if(xft is float.init)
|
||||
fallback();
|
||||
else {
|
||||
dpi[0] = xft;
|
||||
dpi[1] = xft;
|
||||
}
|
||||
}
|
||||
|
||||
return dpi;
|
||||
}
|
||||
|
||||
version(X11)
|
||||
float getXftDpi() {
|
||||
auto display = XDisplayConnection.get;
|
||||
|
||||
char* resourceString = XResourceManagerString(display);
|
||||
XrmInitialize();
|
||||
|
||||
if (resourceString) {
|
||||
auto db = XrmGetStringDatabase(resourceString);
|
||||
XrmValue value;
|
||||
char* type;
|
||||
if (XrmGetResource(db, "Xft.dpi", "String", &type, &value) == true) {
|
||||
if (value.addr) {
|
||||
import core.stdc.stdlib;
|
||||
return atof(cast(char*) value.addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return float.init;
|
||||
}
|
||||
|
||||
/++
|
||||
Implementation used by [SimpleWindow.takeScreenshot].
|
||||
|
||||
|
@ -1804,7 +1823,14 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
|||
|
||||
MonitorInfo.info = MonitorInfo.info[0 .. 0];
|
||||
MonitorInfo.info.assumeSafeAppend();
|
||||
foreach(monitor; monitors[0 .. count]) {
|
||||
foreach(idx, monitor; monitors[0 .. count]) {
|
||||
MonitorInfo.info ~= MonitorInfo(
|
||||
Rectangle(Point(monitor.x, monitor.y), Size(monitor.width, monitor.height)),
|
||||
Size(monitor.mwidth, monitor.mheight),
|
||||
cast(int) (customScalingFactorForMonitor(cast(int) idx) * 96)
|
||||
);
|
||||
|
||||
/+
|
||||
if(monitor.mwidth == 0 || monitor.mheight == 0)
|
||||
// unknown physical size, just guess 96 to avoid divide by zero
|
||||
MonitorInfo.info ~= MonitorInfo(
|
||||
|
@ -1823,8 +1849,9 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
|||
cast(int)(monitor.height * 25.4 / monitor.mheight + 0.5)
|
||||
)
|
||||
);
|
||||
+/
|
||||
}
|
||||
//import std.stdio; writeln("Here", MonitorInfo.info);
|
||||
// import std.stdio; writeln("Here", MonitorInfo.info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1845,8 +1872,8 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
|
|||
fallback:
|
||||
// make sure we disable events that aren't coming
|
||||
xrrEventBase = -1;
|
||||
// best guess...
|
||||
actualDpi_ = cast(int) getDpi()[0];
|
||||
// best guess... respect the custom scaling user command to some extent at least though
|
||||
actualDpi_ = cast(int) (getDpi()[0] * customScalingFactorForMonitor(0));
|
||||
}
|
||||
}
|
||||
actualDpiLoadAttempted = true;
|
||||
|
@ -9902,6 +9929,7 @@ void sdpyPrintDebugString(string fileOverride = null, T...)(T t) nothrow @truste
|
|||
str ~= "\n";
|
||||
|
||||
fwrite(str.ptr, 1, str.length, fp);
|
||||
fflush(fp);
|
||||
} catch(Exception e) {
|
||||
// sorry no hope
|
||||
}
|
||||
|
@ -21491,6 +21519,50 @@ private struct CleanupQueue {
|
|||
}
|
||||
private __gshared CleanupQueue cleanupQueue;
|
||||
|
||||
version(X11)
|
||||
/++
|
||||
Returns the custom scaling factor read out of environment["ARSD_SCALING_FACTOR"].
|
||||
|
||||
$(WARNING
|
||||
This function is exempted from stability guarantees.
|
||||
)
|
||||
+/
|
||||
float customScalingFactorForMonitor(int monitorNumber) {
|
||||
import core.stdc.stdlib;
|
||||
auto val = getenv("ARSD_SCALING_FACTOR");
|
||||
|
||||
if(val is null)
|
||||
return 1.0;
|
||||
|
||||
char[16] buffer = 0;
|
||||
int pos;
|
||||
|
||||
const(char)* at = val;
|
||||
|
||||
foreach(item; 0 .. monitorNumber + 1) {
|
||||
if(*at == 0)
|
||||
break; // reuse the last number when we at the end of the string
|
||||
pos = 0;
|
||||
while(pos + 1 < buffer.length && *at && *at != ';') {
|
||||
buffer[pos++] = *at;
|
||||
at++;
|
||||
}
|
||||
if(*at)
|
||||
at++; // skip the semicolon
|
||||
buffer[pos] = 0;
|
||||
}
|
||||
|
||||
//sdpyPrintDebugString(buffer[0 .. pos]);
|
||||
|
||||
import core.stdc.math;
|
||||
auto f = atof(buffer.ptr);
|
||||
|
||||
if(f <= 0.0 || isnan(f) || isinf(f))
|
||||
return 1.0;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void guiAbortProcess(string msg) {
|
||||
import core.stdc.stdlib;
|
||||
version(Windows) {
|
||||
|
|
21
terminal.d
21
terminal.d
|
@ -8245,7 +8245,9 @@ version(TerminalDirectToEmulator) {
|
|||
|
||||
On January 12, 2022, I changed the font size to be auto-scaled
|
||||
with detected dpi by default. You can undo this by setting
|
||||
`scaleFontSizeWithDpi` to false.
|
||||
`scaleFontSizeWithDpi` to false. On March 22, 2022, I tweaked
|
||||
this slightly to only scale if the font point size is not already
|
||||
scaled (e.g. by Xft.dpi settings) to avoid double scaling.
|
||||
+/
|
||||
string fontName = defaultFont;
|
||||
/// ditto
|
||||
|
@ -8954,7 +8956,22 @@ version(TerminalDirectToEmulator) {
|
|||
}
|
||||
auto fontSize = integratedTerminalEmulatorConfiguration.fontSize;
|
||||
if(integratedTerminalEmulatorConfiguration.scaleFontSizeWithDpi) {
|
||||
fontSize = widget.scaleWithDpi(fontSize);
|
||||
static if(UsingSimpledisplayX11) {
|
||||
// if it is an xft font and xft is already scaled, we should NOT double scale.
|
||||
import std.algorithm;
|
||||
if(integratedTerminalEmulatorConfiguration.fontName.startsWith("core:")) {
|
||||
// core font doesn't use xft anyway
|
||||
fontSize = widget.scaleWithDpi(fontSize);
|
||||
} else {
|
||||
auto xft = getXftDpi();
|
||||
if(xft is float.init)
|
||||
xft = 96;
|
||||
fontSize = widget.scaleWithDpi(fontSize, cast(int) xft);
|
||||
|
||||
}
|
||||
} else {
|
||||
fontSize = widget.scaleWithDpi(fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
if(integratedTerminalEmulatorConfiguration.fontName.length) {
|
||||
|
|
Loading…
Reference in New Issue