#include "CtrlLib.h" #ifdef GUI_X11 namespace Upp { #define LLOG(x) #define LDUMP(x) VectorMap GetXSettings() { VectorMap 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 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; double fontheight = 12; bool bold = false; bool italic = false; const char *q = strrchr(font_name, ' '); if(q) { double h = Atof(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