mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
179 lines
4 KiB
C++
179 lines
4 KiB
C++
#include "CtrlLib.h"
|
|
|
|
#ifdef GUI_X11
|
|
|
|
namespace Upp {
|
|
|
|
#define LLOG(x)
|
|
|
|
VectorMap<String, Value> GetXSettings()
|
|
{
|
|
VectorMap<String, Value> map;
|
|
|
|
Window owner = XGetSelectionOwner(Xdisplay, XAtom("_XSETTINGS_S0"));
|
|
|
|
if(owner == None) {
|
|
LLOG("No XSettings manager found for screen " << screen);
|
|
return map;
|
|
}
|
|
|
|
Atom settings_atom = XAtom("_XSETTINGS_SETTINGS");
|
|
String data = GetProperty(owner, settings_atom, settings_atom);
|
|
|
|
if(data.IsEmpty()) {
|
|
LLOG("Failed to read XSettings property or property is empty.");
|
|
return map;
|
|
}
|
|
|
|
const char *ptr = data.Begin();
|
|
const char *lim = data.End();
|
|
|
|
if(data.GetCount() < 12)
|
|
return map;
|
|
|
|
byte be = ptr[0];
|
|
|
|
auto Peek32 = [&](const char *p) {
|
|
return be ? Peek32be(p) : Peek32le(p);
|
|
};
|
|
|
|
auto Peek16 = [&](const char *p) {
|
|
return be ? Peek16be(p) : Peek16le(p);
|
|
};
|
|
|
|
int n_settings = Peek32(ptr + 8);
|
|
ptr += 12;
|
|
|
|
for(int i = 0; i < n_settings && ptr < lim; i++) {
|
|
if(lim - ptr < 4)
|
|
break;
|
|
|
|
byte type = *ptr++; // 0 = Integer, 1 = String, 2 = Color
|
|
ptr++; // unused
|
|
|
|
int name_len = Peek16(ptr);
|
|
ptr += 2;
|
|
if(lim - ptr < name_len)
|
|
break;
|
|
String name(ptr, name_len);
|
|
ptr += (name_len + 3) & ~3;
|
|
|
|
ptr += 4; // Last-change serial
|
|
|
|
if(type == 0) { // Integer
|
|
if(lim - ptr < 4)
|
|
break;
|
|
map.GetAdd(name) = (int)Peek32(ptr);
|
|
ptr += 4;
|
|
}
|
|
else
|
|
if(type == 1) { // String
|
|
if(lim - ptr < 4)
|
|
break;
|
|
int str_len = Peek32(ptr);
|
|
ptr += 4;
|
|
if(lim - ptr < str_len)
|
|
break;
|
|
map.GetAdd(name) = String(ptr, str_len);
|
|
ptr += (str_len + 3) & ~3; // Align to 4 bytes
|
|
}
|
|
else
|
|
if(type == 2) { // Color - ignored
|
|
if(lim - ptr < 8)
|
|
break;
|
|
ptr += 8;
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
void ChHostSkin()
|
|
{
|
|
VectorMap<String, Value> map = GetXSettings();
|
|
try {
|
|
String font_name = map.Get("Gtk/FontName", "");
|
|
String theme = map.Get("Net/ThemeName", "");
|
|
//int scaling = map.Get("Gdk/WindowScalingFactor", 1);
|
|
int xdpi = map.Get("Xft/DPI", 98347);
|
|
|
|
int fontface = Font::ARIAL;
|
|
int fontheight = 13;
|
|
bool bold = false;
|
|
bool italic = false;
|
|
|
|
const char *q = strrchr(font_name, ' ');
|
|
if(q) {
|
|
int h = atoi(q);
|
|
if(h)
|
|
fontheight = h;
|
|
String face(font_name, q);
|
|
fontface = Font::FindFaceNameIndex(face);
|
|
|
|
if(fontface == 0) {
|
|
for(;;) {
|
|
const char *q = strrchr(face, ' ');
|
|
if(!q) break;
|
|
const char *s = q + 1;
|
|
if(stricmp(s, "Bold") == 0 || stricmp(s, "Heavy") == 0)
|
|
bold = true;
|
|
else
|
|
if(stricmp(s, "Italic") == 0 || stricmp(s, "Oblique") == 0)
|
|
italic = true;
|
|
else
|
|
if(stricmp(s, "Regular") == 0 || stricmp(s, "Light") || stricmp(s, "Medium"))
|
|
;
|
|
else
|
|
continue;
|
|
face = String(~face, q);
|
|
}
|
|
fontface = Font::FindFaceNameIndex(face);
|
|
if(fontface == 0) {
|
|
if(ToUpper(face[0]) == 'M')
|
|
fontface = Font::COURIER;
|
|
else
|
|
if(ToUpper(face[0]) == 'S' && ToUpper(face[1]) == 'e')
|
|
fontface = Font::ROMAN;
|
|
else
|
|
fontface = Font::ARIAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
Font gui_font = Font(fontface, fround(fontheight * xdpi / (72*1024.0))).Bold(bold).Italic(italic);
|
|
Font::SetDefaultFont(gui_font);
|
|
|
|
SColorFace_Write(Color(242, 241, 240));
|
|
SColorMenu_Write(Color(242, 241, 240));
|
|
SColorHighlight_Write(Color(50, 50, 250));
|
|
|
|
auto ThemeHasWord = [&](const char *text) {
|
|
int q = ToLower(theme).Find(text);
|
|
if(q >= 0) {
|
|
if(q > 0) {
|
|
int pc = theme[q - 1];
|
|
if(!(IsUpper(theme[q]) && IsLower(pc) || !IsLetter(pc)))
|
|
return false;
|
|
}
|
|
int l = strlen(text);
|
|
int nc = theme[q + l];
|
|
if(!(IsLower(text[l - 1]) && IsUpper(nc) || !IsLetter(nc)))
|
|
return false;
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
if(ThemeHasWord("dark") || ThemeHasWord("inverse") || ThemeHasWord("black"))
|
|
ChDarkSkin();
|
|
else
|
|
ChStdSkin();
|
|
}
|
|
catch(ValueTypeError) {}
|
|
|
|
SwapOKCancel_Write(Environment().Get("KDE_FULL_SESSION", String()) != "true");
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|