mirror of https://gitlab.com/nakst/essence
window color settings
This commit is contained in:
parent
f82e5d9a30
commit
9923c28ad9
|
@ -11,7 +11,6 @@ To support development, you can donate to my Patreon: https://www.patreon.com/na
|
|||
## Features
|
||||
|
||||
Kernel
|
||||
* Audio mixer.
|
||||
* Filesystem independent cache manager.
|
||||
* Memory manager with shared memory, memory-mapped files and multithreaded paging zeroing and working set balancing.
|
||||
* Networking stack for TCP/IP.
|
||||
|
@ -19,6 +18,7 @@ Kernel
|
|||
* On-demand module loading.
|
||||
* Virtual filesystem.
|
||||
* Window manager.
|
||||
* Audio mixer. (being rewritten)
|
||||
* Optional POSIX subsystem, capable of running GCC and some Busybox tools.
|
||||
|
||||
Applications
|
||||
|
@ -52,7 +52,9 @@ Desktop
|
|||
|
||||
## Discussion
|
||||
|
||||
Visit https://essence.handmade.network/forums.
|
||||
Join our Discord server: https://discord.gg/skeP9ZGDK8
|
||||
|
||||
Alternatively, visit the forums (not very active): https://essence.handmade.network/forums.
|
||||
|
||||
## Building
|
||||
|
||||
|
|
|
@ -1275,6 +1275,7 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
|
|||
EsHeapFree(path);
|
||||
|
||||
SettingsUpdateGlobalAndWindowManager();
|
||||
SettingsWindowColorUpdated();
|
||||
} else {
|
||||
EsHandle initialMountPointsBuffer = api.startupInformation->data.initialMountPoints;
|
||||
size_t initialMountPointCount = EsConstantBufferGetSize(initialMountPointsBuffer) / sizeof(EsMountPoint);
|
||||
|
|
|
@ -1953,7 +1953,7 @@ void ConfigurationWriteToFile() {
|
|||
if (ES_SUCCESS == EsPathDelete(EsLiteral(K_SYSTEM_CONFIGURATION))) {
|
||||
if (ES_SUCCESS == EsPathMove(EsLiteral(K_SYSTEM_CONFIGURATION "_"), EsLiteral(K_SYSTEM_CONFIGURATION))) {
|
||||
EsPrint("ConfigurationWriteToFile - New configuration successfully written.\n");
|
||||
desktop.configurationModified = true;
|
||||
desktop.configurationModified = false;
|
||||
} else {
|
||||
EsPrint("ConfigurationWriteToFile - Error while moving to final path.\n");
|
||||
}
|
||||
|
@ -1986,44 +1986,6 @@ void WallpaperLoad(EsGeneric) {
|
|||
EsRectangle region = ES_RECT_2S(desktop.wallpaperWindow->windowWidth, desktop.wallpaperWindow->windowHeight);
|
||||
EsSyscall(ES_SYSCALL_WINDOW_SET_BITS, desktop.wallpaperWindow->handle, (uintptr_t) ®ion, (uintptr_t) buffer, 0);
|
||||
EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0);
|
||||
|
||||
// Work out the most common hue on the wallpaper, and set the system hue.
|
||||
|
||||
uint32_t hueBuckets[36] = {};
|
||||
uint32_t hueSelected = 0;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.wallpaperWindow->windowWidth * desktop.wallpaperWindow->windowHeight; i += 7) {
|
||||
float h, s, v;
|
||||
EsColorConvertToHSV(((uint32_t *) buffer)[i], &h, &s, &v);
|
||||
uintptr_t bucket = (uintptr_t) (h * 6);
|
||||
hueBuckets[bucket] += 2;
|
||||
hueBuckets[bucket == 35 ? 0 : (bucket + 1)] += 1;
|
||||
hueBuckets[bucket == 0 ? 35 : (bucket - 1)] += 1;
|
||||
}
|
||||
|
||||
for (uintptr_t i = 1; i < 36; i++) {
|
||||
if (hueBuckets[i] > hueBuckets[hueSelected]) {
|
||||
hueSelected = i;
|
||||
}
|
||||
}
|
||||
|
||||
theming.systemHue = hueSelected / 6.0f;
|
||||
if (theming.systemHue < 0) theming.systemHue += 6.0f;
|
||||
|
||||
EsHeapFree(buffer);
|
||||
|
||||
// Tell all container windows to redraw with the new system hue.
|
||||
|
||||
EsMessageMutexAcquire();
|
||||
|
||||
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
|
||||
if (gui.allWindows[i]->windowStyle == ES_WINDOW_CONTAINER) {
|
||||
gui.allWindows[i]->Repaint(true);
|
||||
UIWindowNeedsUpdate(gui.allWindows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
EsMessageMutexRelease();
|
||||
}
|
||||
|
||||
// TODO Fade wallpaper in.
|
||||
|
|
|
@ -2067,6 +2067,7 @@ function double EsTimeStampMs();
|
|||
// Graphics.
|
||||
|
||||
function uint32_t EsColorBlend(uint32_t under, uint32_t over, bool fullAlpha);
|
||||
function bool EsColorIsLight(uint32_t color); // Returns true if you should black to draw atop the color.
|
||||
function uint32_t EsColorConvertToRGB(float h, float s, float v); // 0 <= hue < 6; 0 <= saturation <= 1; 0 <= value <= 1.
|
||||
function bool EsColorConvertToHSV(uint32_t color, float *h, float *s, float *v);
|
||||
function uint32_t EsColorParse(STRING string);
|
||||
|
|
|
@ -51,6 +51,16 @@ const EsStyle styleSettingsGroupContainer2 = {
|
|||
},
|
||||
};
|
||||
|
||||
const uint32_t windowColors[] = {
|
||||
0xFF0032, // Strawberry.
|
||||
0xFF7F24, // Bronze.
|
||||
0x77FFD4, // Grass.
|
||||
0x448CF5, // Ocean.
|
||||
0xAC00FF, // Violet.
|
||||
0xE8ECF9, // Polar.
|
||||
0xB7BBC5, // Space. TODO Looks bad deactivated.
|
||||
};
|
||||
|
||||
const EsStyle styleSettingsGroupContainer3 = {
|
||||
.inherit = ES_STYLE_BUTTON_GROUP_CONTAINER,
|
||||
|
||||
|
@ -74,8 +84,8 @@ const EsStyle styleSettingsNumberTextbox = {
|
|||
const EsStyle styleSettingsTable = {
|
||||
.metrics = {
|
||||
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
|
||||
.gapMajor = 5,
|
||||
.gapMinor = 5,
|
||||
.gapMajor = 7,
|
||||
.gapMinor = 7,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -556,11 +566,83 @@ void SettingsPageDisplay(EsElement *element, SettingsPage *page) {
|
|||
100, 400, INTERFACE_STRING(CommonUnitPercent), 0.05, 5);
|
||||
}
|
||||
|
||||
int SettingsColorButtonMessage(EsElement *element, EsMessage *message) {
|
||||
if (message->type == ES_MSG_PAINT_BACKGROUND) {
|
||||
// HACK This assumes a lot about the workings of the radiobox style...
|
||||
|
||||
EsRectangle bounds = EsPainterBoundsClient(message->painter);
|
||||
bounds.r = bounds.l + 14 * EsElementGetScaleFactor(element);
|
||||
bounds = EsRectangleFit(bounds, ES_RECT_2S(1, 1), true);
|
||||
uint32_t cornerRadius = Width(bounds);
|
||||
uint32_t cornerRadii[4] = { cornerRadius, cornerRadius, cornerRadius, cornerRadius };
|
||||
int32_t borderSize = 1 * EsElementGetScaleFactor(element);
|
||||
|
||||
uint32_t color = EsColorBlend(windowColors[element->userData.u] | 0xFF000000, 0x20FFFFFF, false);
|
||||
if (element->window->pressed == element) color = EsColorBlend(color, 0x40000000, false);
|
||||
EsDrawRoundedRectangle(message->painter, bounds, color, EsColorBlend(color, 0x40000000, false), ES_RECT_1(borderSize), cornerRadii);
|
||||
|
||||
if (EsButtonGetCheck((EsButton *) element) == ES_CHECK_CHECKED) {
|
||||
int32_t inset = 4 * EsElementGetScaleFactor(element);
|
||||
uint32_t bulletColor = EsColorIsLight(color) ? 0xFF000000 : 0xFFFFFFFF;
|
||||
EsDrawRoundedRectangle(message->painter, EsRectangleAdd(bounds, ES_RECT_1I(inset)), bulletColor, 0, ES_RECT_1(0), cornerRadii);
|
||||
}
|
||||
|
||||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SettingsWindowColorUpdated() {
|
||||
uint8_t index = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("window_color"));
|
||||
|
||||
if (index > sizeof(windowColors) / sizeof(windowColors[0])) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
EsColorConvertToHSV(windowColors[index], &theming.systemHue, &theming.systemSaturation, &theming.systemValue);
|
||||
|
||||
if (theming.systemHue > 0.3f && theming.systemHue < 3.3f) {
|
||||
theming.systemHueShift = -1.5f;
|
||||
} else {
|
||||
theming.systemHueShift = 1.0f;
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
|
||||
if (gui.allWindows[i]->windowStyle == ES_WINDOW_CONTAINER) {
|
||||
gui.allWindows[i]->Repaint(true);
|
||||
UIWindowNeedsUpdate(gui.allWindows[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsColorButtonCommand(EsInstance *, EsElement *element, EsCommand *) {
|
||||
if (EsButtonGetCheck((EsButton *) element) != ES_CHECK_CHECKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
EsMutexAcquire(&api.systemConfigurationMutex);
|
||||
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup("general", -1, true);
|
||||
|
||||
if (group) {
|
||||
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, "window_color", -1, true);
|
||||
|
||||
if (item) {
|
||||
EsHeapFree(item->value);
|
||||
item->value = (char *) EsHeapAllocate(65, true);
|
||||
item->valueBytes = EsStringFormat(item->value, 64, "%fd", ES_STRING_FORMAT_SIMPLE, element->userData.u);
|
||||
}
|
||||
}
|
||||
|
||||
EsMutexRelease(&api.systemConfigurationMutex);
|
||||
SettingsWindowColorUpdated();
|
||||
desktop.configurationModified = true;
|
||||
ConfigurationWriteToFile();
|
||||
}
|
||||
|
||||
void SettingsPageTheme(EsElement *element, SettingsPage *page) {
|
||||
// TODO Fonts, theme file, etc.
|
||||
|
||||
EsElementSetHidden(((SettingsInstance *) element->instance)->undoButton, false);
|
||||
|
||||
EsPanel *content = EsPanelCreate(element, ES_CELL_FILL | ES_PANEL_V_SCROLL_AUTO, &styleNewTabContent);
|
||||
EsPanel *container = EsPanelCreate(content, ES_PANEL_VERTICAL | ES_CELL_H_SHRINK, &styleSettingsGroupContainer2);
|
||||
SettingsAddTitle(container, page);
|
||||
|
@ -569,10 +651,15 @@ void SettingsPageTheme(EsElement *element, SettingsPage *page) {
|
|||
EsIconDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_WARNING);
|
||||
EsTextDisplayCreate(warningRow, ES_FLAGS_DEFAULT, 0, "Work in progress" ELLIPSIS);
|
||||
|
||||
EsPanel *table = EsPanelCreate(container, ES_CELL_H_FILL | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
||||
EsPanel *table = EsPanelCreate(container, ES_CELL_H_CENTER | ES_PANEL_TABLE | ES_PANEL_HORIZONTAL, &styleSettingsTable);
|
||||
EsPanelSetBands(table, 2);
|
||||
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, 0, "Wallpaper:", -1);
|
||||
|
||||
EsTextbox *textbox = EsTextboxCreate(table, ES_CELL_H_LEFT | ES_CELL_H_PUSH | ES_TEXTBOX_EDIT_BASED | ES_ELEMENT_FREE_USER_DATA, ES_STYLE_TEXTBOX_BORDERED_SINGLE);
|
||||
size_t currentWallpaperBytes;
|
||||
char *currentWallpaper = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("wallpaper"), ¤tWallpaperBytes);
|
||||
EsTextboxInsert(textbox, currentWallpaper, currentWallpaperBytes);
|
||||
EsHeapFree(currentWallpaper);
|
||||
|
||||
textbox->messageUser = [] (EsElement *element, EsMessage *message) {
|
||||
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
|
||||
|
@ -597,6 +684,18 @@ void SettingsPageTheme(EsElement *element, SettingsPage *page) {
|
|||
|
||||
return 0;
|
||||
};
|
||||
|
||||
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, 0, "Window color:", -1);
|
||||
EsPanel *panel = EsPanelCreate(table, ES_CELL_H_LEFT | ES_PANEL_HORIZONTAL);
|
||||
uint8_t windowColor = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("window_color"));
|
||||
|
||||
for (uintptr_t i = 0; i < sizeof(windowColors) / sizeof(windowColors[0]); i++) {
|
||||
EsButton *button = EsButtonCreate(panel, ES_CELL_H_LEFT | ES_BUTTON_RADIOBOX | ES_ELEMENT_NO_FOCUS_ON_CLICK);
|
||||
if (windowColor == i) EsButtonSetCheck(button, ES_CHECK_CHECKED);
|
||||
button->userData.u = i;
|
||||
button->messageUser = SettingsColorButtonMessage;
|
||||
EsButtonOnCommand(button, SettingsColorButtonCommand);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsPage settingsPages[] = {
|
||||
|
|
|
@ -110,7 +110,7 @@ typedef struct ThemeGradientStop {
|
|||
typedef struct ThemePaintLinearGradient {
|
||||
float transform[3];
|
||||
uint8_t stopCount;
|
||||
int8_t useGammaInterpolation : 1, useDithering : 1, useSystemHue : 1;
|
||||
int8_t useGammaInterpolation : 1, useDithering : 1, useSystemColor : 1;
|
||||
uint8_t repeatMode;
|
||||
uint8_t _unused0;
|
||||
// Followed by gradient stops.
|
||||
|
@ -368,7 +368,7 @@ struct {
|
|||
EsPaintTarget cursors;
|
||||
float scale;
|
||||
HashStore<UIStyleKey, struct UIStyle *> loadedStyles;
|
||||
float systemHue;
|
||||
float systemHue, systemSaturation, systemValue, systemHueShift;
|
||||
} theming;
|
||||
#endif
|
||||
|
||||
|
@ -630,12 +630,13 @@ void GradientCacheSetup(GradientCache *cache, const ThemePaintLinearGradient *gr
|
|||
uint32_t color1 = stop1->color;
|
||||
|
||||
#ifndef IN_DESIGNER
|
||||
if (gradient->useSystemHue) {
|
||||
if (gradient->useSystemColor) {
|
||||
float h, h2, s, v;
|
||||
EsColorConvertToHSV(color0, &h, &s, &v);
|
||||
color0 = (color0 & 0xFF000000) | EsColorConvertToRGB(theming.systemHue, s, v);
|
||||
color0 = (color0 & 0xFF000000) | EsColorConvertToRGB(theming.systemHue, s * theming.systemSaturation, v * theming.systemValue);
|
||||
EsColorConvertToHSV(color1, &h2, &s, &v);
|
||||
color1 = (color1 & 0xFF000000) | EsColorConvertToRGB(theming.systemHue + (h2 - h), s, v);
|
||||
color1 = (color1 & 0xFF000000) | EsColorConvertToRGB(theming.systemHue + (h2 - h) * theming.systemHueShift,
|
||||
s * theming.systemSaturation, v * theming.systemValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ click_chain_timeout_ms=500
|
|||
show_cursor_shadow=1
|
||||
scroll_lines_per_notch=3
|
||||
ui_scale=100
|
||||
window_color=3
|
||||
|
||||
[ui]
|
||||
font_fallback=Inter
|
||||
|
|
|
@ -196,6 +196,14 @@ bool EsColorConvertToHSV(uint32_t color, float *h, float *s, float *v) {
|
|||
}
|
||||
}
|
||||
|
||||
bool EsColorIsLight(uint32_t color) {
|
||||
float r = (color & 0xFF0000) >> 16;
|
||||
float g = (color & 0x00FF00) >> 8;
|
||||
float b = (color & 0x0000FF) >> 0;
|
||||
float brightness = EsCRTsqrt(r * r * 0.241f + g * g * 0.691f + b * b * 0.068f);
|
||||
return brightness >= 180.0f;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Standard mathematical functions.
|
||||
/////////////////////////////////
|
||||
|
|
|
@ -446,6 +446,7 @@ EsBufferReadInt32Endian=444
|
|||
EsBufferWriteInt32Endian=445
|
||||
EsSystemGetOptimalWorkQueueThreadCount=446
|
||||
EsDeviceControl=447
|
||||
EsColorIsLight=448
|
||||
EsListViewFixedItemRemove=449
|
||||
EsIconIDFromDriveType=450
|
||||
EsIconDisplaySetIcon=451
|
||||
|
|
|
@ -707,7 +707,7 @@ void PaintLinearGradientOp(RfState *state, RfItem *item, void *pointer) {
|
|||
EXPORT_FIELD(PaintLinearGradient, gradient, ThemePaintLinearGradient, themeGradient, transformStart, transform[2]);
|
||||
themeGradient.useGammaInterpolation = gradient->useGammaInterpolation;
|
||||
themeGradient.useDithering = gradient->useDithering;
|
||||
themeGradient.useSystemHue = gradient->useSystemHue;
|
||||
themeGradient.useSystemColor = gradient->useSystemHue;
|
||||
themeGradient.stopCount = arrlenu(gradient->stops);
|
||||
themeGradient.repeatMode = gradient->repeat == GRADIENT_REPEAT_CLAMP ? RAST_REPEAT_CLAMP
|
||||
: gradient->repeat == GRADIENT_REPEAT_NORMAL ? RAST_REPEAT_NORMAL
|
||||
|
|
Loading…
Reference in New Issue