linux: better method of getting DPI info
parent
d0dbf70e48
commit
e3c83c8f09
161
linux_4ed.cpp
161
linux_4ed.cpp
|
@ -1975,7 +1975,8 @@ LinuxSetIcon(Display* d, Window w)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
LinuxX11ConnectionWatch(Display* dpy, XPointer cdata, int fd, Bool opening, XPointer* wdata){
|
LinuxX11ConnectionWatch(Display* dpy, XPointer cdata, int fd, Bool opening, XPointer* wdata)
|
||||||
|
{
|
||||||
struct epoll_event e = {};
|
struct epoll_event e = {};
|
||||||
e.events = EPOLLIN | EPOLLET;
|
e.events = EPOLLIN | EPOLLET;
|
||||||
e.data.u64 = LINUX_4ED_EVENT_X11_INTERNAL | fd;
|
e.data.u64 = LINUX_4ED_EVENT_X11_INTERNAL | fd;
|
||||||
|
@ -1984,6 +1985,118 @@ LinuxX11ConnectionWatch(Display* dpy, XPointer cdata, int fd, Bool opening, XPoi
|
||||||
epoll_ctl(linuxvars.epoll, op, fd, &e);
|
epoll_ctl(linuxvars.epoll, op, fd, &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal int
|
||||||
|
LinuxGetXSettingsDPI(Display* dpy, int screen)
|
||||||
|
{
|
||||||
|
struct XSettingHeader {
|
||||||
|
u8 type;
|
||||||
|
u8 pad0;
|
||||||
|
u16 name_len;
|
||||||
|
char name[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XSettings {
|
||||||
|
u8 byte_order;
|
||||||
|
u8 pad[3];
|
||||||
|
u32 serial;
|
||||||
|
u32 num_settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { XSettingsTypeInt, XSettingsTypeString, XSettingsTypeColor };
|
||||||
|
|
||||||
|
int dpi = -1;
|
||||||
|
unsigned char* prop = NULL;
|
||||||
|
char sel_buffer[64];
|
||||||
|
struct XSettings* xs;
|
||||||
|
const char* p;
|
||||||
|
|
||||||
|
snprintf(sel_buffer, sizeof(sel_buffer), "_XSETTINGS_S%d", screen);
|
||||||
|
|
||||||
|
Atom XSET_SEL = XInternAtom(dpy, sel_buffer, True);
|
||||||
|
Atom XSET_SET = XInternAtom(dpy, "_XSETTINGS_SETTINGS", True);
|
||||||
|
|
||||||
|
if(XSET_SEL == None || XSET_SET == None){
|
||||||
|
fputs("XSETTINGS unavailable.\n", stderr);
|
||||||
|
return dpi;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window xset_win = XGetSelectionOwner(dpy, XSET_SEL);
|
||||||
|
if(xset_win == None){
|
||||||
|
// TODO(inso): listen for the ClientMessage about it becoming available?
|
||||||
|
// there's not much point atm if DPI scaling is only done at startup
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
int fmt;
|
||||||
|
unsigned long pad, num;
|
||||||
|
|
||||||
|
if(XGetWindowProperty(dpy, xset_win, XSET_SET, 0, 1024, False, XSET_SET, &type, &fmt, &num, &pad, &prop) != Success){
|
||||||
|
fputs("XSETTINGS: GetWindowProperty failed.\n", stderr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fmt != 8){
|
||||||
|
fputs("XSETTINGS: Wrong format.\n", stderr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xs = (struct XSettings*)prop;
|
||||||
|
p = (char*)(xs + 1);
|
||||||
|
|
||||||
|
if(xs->byte_order != 0){
|
||||||
|
fputs("FIXME: XSETTINGS not host byte order?\n", stderr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < xs->num_settings; ++i){
|
||||||
|
struct XSettingHeader* h = (struct XSettingHeader*)p;
|
||||||
|
|
||||||
|
// const char* strs[] = { "Int", "String", "Color" };
|
||||||
|
// printf("%s:\t\"%.*s\"\n", strs[h->type], h->name_len, h->name);
|
||||||
|
|
||||||
|
p += sizeof(struct XSettingHeader);
|
||||||
|
p += h->name_len;
|
||||||
|
p += ((4 - (h->name_len & 3)) & 3);
|
||||||
|
p += 4; // serial
|
||||||
|
|
||||||
|
switch(h->type){
|
||||||
|
case XSettingsTypeInt: {
|
||||||
|
if(strncmp(h->name, "Xft/DPI", h->name_len) == 0){
|
||||||
|
dpi = *(i32*)p;
|
||||||
|
if(dpi != -1) dpi /= 1024;
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case XSettingsTypeString: {
|
||||||
|
u32 len = *(u32*)p;
|
||||||
|
p += 4;
|
||||||
|
p += len;
|
||||||
|
p += ((4 - (len & 3)) & 3);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case XSettingsTypeColor: {
|
||||||
|
p += 8;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
fputs("XSETTINGS: Got invalid type...\n", stderr);
|
||||||
|
goto out;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(prop){
|
||||||
|
XFree(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dpi;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// X11 window init
|
// X11 window init
|
||||||
//
|
//
|
||||||
|
@ -2002,8 +2115,8 @@ LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
|
||||||
*WinWidth = linuxvars.settings.window_w;
|
*WinWidth = linuxvars.settings.window_w;
|
||||||
*WinHeight = linuxvars.settings.window_h;
|
*WinHeight = linuxvars.settings.window_h;
|
||||||
} else {
|
} else {
|
||||||
*WinWidth = BASE_W;
|
*WinWidth = BASE_W * size_change(linuxvars.dpi_x, linuxvars.dpi_y);
|
||||||
*WinHeight = BASE_H;
|
*WinHeight = BASE_H * size_change(linuxvars.dpi_x, linuxvars.dpi_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GLXCanUseFBConfig(linuxvars.XDisplay)){
|
if (!GLXCanUseFBConfig(linuxvars.XDisplay)){
|
||||||
|
@ -2722,6 +2835,28 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
#undef LOAD_ATOM
|
#undef LOAD_ATOM
|
||||||
|
|
||||||
|
#if SUPPORT_DPI
|
||||||
|
linuxvars.dpi_x = linuxvars.dpi_y = LinuxGetXSettingsDPI(linuxvars.XDisplay, DefaultScreen(linuxvars.XDisplay));
|
||||||
|
|
||||||
|
// fallback
|
||||||
|
if(linuxvars.dpi_x == -1){
|
||||||
|
int scr = DefaultScreen(linuxvars.XDisplay);
|
||||||
|
|
||||||
|
int dw = DisplayWidth(linuxvars.XDisplay, scr);
|
||||||
|
int dh = DisplayHeight(linuxvars.XDisplay, scr);
|
||||||
|
|
||||||
|
int dw_mm = DisplayWidthMM(linuxvars.XDisplay, scr);
|
||||||
|
int dh_mm = DisplayHeightMM(linuxvars.XDisplay, scr);
|
||||||
|
|
||||||
|
linuxvars.dpi_x = dw_mm ? dw / (dw_mm / 25.4) : 96;
|
||||||
|
linuxvars.dpi_y = dh_mm ? dh / (dh_mm / 25.4) : 96;
|
||||||
|
|
||||||
|
fprintf(stderr, "%dx%d - %dmmx%dmm DPI: %dx%d\n", dw, dh, dw_mm, dh_mm, linuxvars.dpi_x, linuxvars.dpi_y);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "DPI from XSETTINGS: %d\n", linuxvars.dpi_x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int WinWidth, WinHeight;
|
int WinWidth, WinHeight;
|
||||||
if(!LinuxX11WindowInit(argc, argv, &WinWidth, &WinHeight)){
|
if(!LinuxX11WindowInit(argc, argv, &WinWidth, &WinHeight)){
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2774,26 +2909,6 @@ main(int argc, char **argv)
|
||||||
XFreePixmap(linuxvars.XDisplay, p);
|
XFreePixmap(linuxvars.XDisplay, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// DPI
|
|
||||||
//
|
|
||||||
|
|
||||||
#if SUPPORT_DPI
|
|
||||||
{
|
|
||||||
int scr = DefaultScreen(linuxvars.XDisplay);
|
|
||||||
|
|
||||||
int dw = DisplayWidth(linuxvars.XDisplay, scr);
|
|
||||||
int dh = DisplayHeight(linuxvars.XDisplay, scr);
|
|
||||||
|
|
||||||
int dw_mm = DisplayWidthMM(linuxvars.XDisplay, scr);
|
|
||||||
int dh_mm = DisplayHeightMM(linuxvars.XDisplay, scr);
|
|
||||||
|
|
||||||
linuxvars.dpi_x = dw_mm ? dw / (dw_mm / 25.4) : 96;
|
|
||||||
linuxvars.dpi_y = dh_mm ? dh / (dh_mm / 25.4) : 96;
|
|
||||||
|
|
||||||
fprintf(stderr, "%dx%d - %dmmx%dmm DPI: %dx%d\n", dw, dh, dw_mm, dh_mm, linuxvars.dpi_x, linuxvars.dpi_y);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Epoll init
|
// Epoll init
|
||||||
|
|
Loading…
Reference in New Issue