desktop: use color scheme to determine wallpaper background; fade transition when changing color scheme

This commit is contained in:
nakst 2022-03-10 14:36:05 +00:00
parent 6f074e12f9
commit d9a8557568
8 changed files with 143 additions and 38 deletions

View File

@ -201,9 +201,12 @@ struct {
HashStore<EsObjectID, OpenDocument> openDocuments;
TaskBar taskBar;
EsWindow *wallpaperWindow;
EsButton *tasksButton;
EsWindow *wallpaperWindow;
uint32_t wallpaperBackgroundColor;
bool isWallpaperBackgroundColorVisible; // If true, then the wallpaper needs to be reloaded when the background color changes.
bool setupDesktopUIComplete;
uint8_t installationState;
bool desktopInspectorOpen;
@ -634,8 +637,8 @@ int CursorLocatorMessage(EsElement *element, EsMessage *message) {
EsWindow *window = element->window;
if (message->type == ES_MSG_ANIMATE) {
window->announcementTimeMs += message->animate.deltaMs;
double progress = window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration");
window->animationTime += message->animate.deltaMs;
double progress = window->animationTime / GetConstantNumber("cursorLocatorDuration");
if (progress > 1) {
EsElementDestroy(window);
@ -646,7 +649,7 @@ int CursorLocatorMessage(EsElement *element, EsMessage *message) {
}
} else if (message->type == ES_MSG_LAYOUT) {
EsElement *child = element->GetChild(0);
double progress = 1.0 - window->announcementTimeMs / GetConstantNumber("cursorLocatorDuration");
double progress = 1.0 - window->animationTime / GetConstantNumber("cursorLocatorDuration");
int width = progress * child->GetWidth(0), height = progress * child->GetHeight(0);
child->InternalMove(width, height, (element->width - width) / 2, (element->height - height) / 2);
}
@ -2600,17 +2603,23 @@ void WallpaperLoad(EsGeneric) {
size_t pathBytes;
char *path = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("wallpaper"), &pathBytes);
if (path) {
void *buffer = EsHeapAllocate(desktop.wallpaperWindow->windowWidth * desktop.wallpaperWindow->windowHeight * 4, false);
LoadImage(path, pathBytes, buffer, desktop.wallpaperWindow->windowWidth, desktop.wallpaperWindow->windowHeight, false);
EsHeapFree(path);
void *buffer = EsHeapAllocate(desktop.wallpaperWindow->windowWidth * desktop.wallpaperWindow->windowHeight * 4, false);
EsRectangle region = ES_RECT_2S(desktop.wallpaperWindow->windowWidth, desktop.wallpaperWindow->windowHeight);
EsSyscall(ES_SYSCALL_WINDOW_SET_BITS, desktop.wallpaperWindow->handle, (uintptr_t) &region, (uintptr_t) buffer, 0);
EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0);
for (uintptr_t i = 0; i < desktop.wallpaperWindow->windowWidth * desktop.wallpaperWindow->windowHeight; i++) {
((uint32_t *) buffer)[i] = desktop.wallpaperBackgroundColor;
}
bool coversDestination;
if (path) LoadImage(path, pathBytes, buffer, desktop.wallpaperWindow->windowWidth, desktop.wallpaperWindow->windowHeight, false, &coversDestination);
desktop.isWallpaperBackgroundColorVisible = !coversDestination;
EsRectangle region = ES_RECT_2S(desktop.wallpaperWindow->windowWidth, desktop.wallpaperWindow->windowHeight);
EsSyscall(ES_SYSCALL_WINDOW_SET_BITS, desktop.wallpaperWindow->handle, (uintptr_t) &region, (uintptr_t) buffer, 0);
EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0);
// TODO Fade wallpaper in.
EsHeapFree(path);
}
//////////////////////////////////////////////////////

View File

@ -499,9 +499,12 @@ struct EsWindow : EsElement {
Array<EsElement *> checkVisible;
bool processCheckVisible;
double animationTime;
EsRectangle beforeMaximiseBounds, targetBounds, animateFromBounds;
bool animateToTargetBoundsAfterResize;
double animateToTargetBoundsTimeMs;
EsPoint announcementBase;
EsRectangle updateRegion;
EsRectangle updateRegionInProgress; // For visualizePaintSteps.
@ -511,9 +514,6 @@ struct EsWindow : EsElement {
EsElement *source; // Menu source.
EsWindow *targetMenu; // The menu that keyboard events should be sent to.
EsPoint announcementBase;
double announcementTimeMs;
};
struct UpdateAction {
@ -634,7 +634,7 @@ void WindowChangeBounds(int direction, int newX, int newY, int *originalX, int *
window->isMaximised = false;
window->animateToTargetBoundsAfterResize = false;
window->animateToTargetBoundsTimeMs = -1;
window->animationTime = -1;
if (direction == RESIZE_MOVE) {
if (newY < screen.t + windowSnapRange && canSnap) {
@ -758,14 +758,14 @@ int ProcessWindowBorderMessage(EsWindow *window, EsMessage *message, EsRectangle
}
if (window->animateToTargetBoundsAfterResize) {
window->animateToTargetBoundsTimeMs = 0;
window->animationTime = 0;
window->StartAnimating();
}
gui.resizing = false;
} else if (message->type == ES_MSG_ANIMATE && window->animateToTargetBoundsAfterResize) {
double progress = window->animateToTargetBoundsTimeMs / 100.0;
window->animateToTargetBoundsTimeMs += message->animate.deltaMs;
double progress = window->animationTime / 100.0;
window->animationTime += message->animate.deltaMs;
if (progress > 1 || progress < 0) {
message->animate.complete = true;
@ -4318,9 +4318,9 @@ int AnnouncementMessage(EsElement *element, EsMessage *message) {
EsWindow *window = (EsWindow *) element;
if (message->type == ES_MSG_ANIMATE) {
window->announcementTimeMs += message->animate.deltaMs;
window->animationTime += message->animate.deltaMs;
double progress = window->announcementTimeMs / GetConstantNumber("announcementDuration");
double progress = window->animationTime / GetConstantNumber("announcementDuration");
if (progress > 1) {
EsElementDestroy(window);

View File

@ -953,6 +953,7 @@ private inttype EsSyscallType enum none {
ES_SYSCALL_SCREEN_WORK_AREA_SET
ES_SYSCALL_SCREEN_WORK_AREA_GET
ES_SYSCALL_SCREEN_BOUNDS_GET
ES_SYSCALL_SCREEN_GET_BITS
ES_SYSCALL_SCREEN_FORCE_UPDATE
ES_SYSCALL_WINDOW_CREATE

View File

@ -58,17 +58,17 @@ const EsStyle styleSettingsGroupContainer2 = {
},
};
const uint32_t windowColors[][7] = {
{ 0xFF67EFC4, 0xFFA9E7D3, 0xFF94D1BD, 0xFF6BA996, 0xFFD0E2DD, 0xFFD1EAE2, 0xFFBAD1C9 },
{ 0xFF54ACE5, 0xFF9BC3DD, 0xFF87AEC8, 0xFF6784A2, 0xFFC5D1D9, 0xFFC6D6E0, 0xFFB0BEC8 },
{ 0xFF448CF5, 0xFF9CBDED, 0xFF87A7D6, 0xFF5E7FB8, 0xFFD0DAE8, 0xFFD0DDF0, 0xFFB9C4D6 },
{ 0xFF044CF5, 0xFF7FA0ED, 0xFF6A8AD6, 0xFF4065B4, 0xFFC8D1E8, 0xFFC4D1F0, 0xFFAEBAD6 },
{ 0xFFAC00FF, 0xFFD183F7, 0xFFB96DDF, 0xFF8F41B5, 0xFFE6D0F2, 0xFFEBCCFA, 0xFFD1B5DF },
{ 0xFFFF0032, 0xFFF78399, 0xFFDF6D83, 0xFFC0436B, 0xFFF2D0D6, 0xFFFACCD5, 0xFFDFB5BD },
{ 0xFFFF6042, 0xFFF7AEA1, 0xFFDF978A, 0xFFB5525F, 0xFFF2DCD8, 0xFFFADDD7, 0xFFDFC4BF },
{ 0xFFFF7F24, 0xFFF7BC93, 0xFFDFA57D, 0xFFC7825F, 0xFFF2E0D4, 0xFFFAE2D2, 0xFFDFC9BA },
{ 0xFFE8ECF9, 0xFFE9EBF1, 0xFFD2D3D9, 0xFFA9AAB0, 0xFFEAEAEC, 0xFFF1F1F4, 0xFFD6D7D9 },
{ 0xFFB7BBC5, 0xFFB8BABE, 0xFF9A9BA0, 0xFF85878B, 0xFFE9E9EA, 0xFFDEDFE1, 0xFFB9BABC },
const uint32_t windowColors[][8] = {
{ 0xFF67EFC4, 0xCEF2E6, 0xFFA9E7D3, 0xFF94D1BD, 0xFF6BA996, 0xFFD0E2DD, 0xFFD1EAE2, 0xFFBAD1C9 },
{ 0xFF54ACE5, 0xB1CEE1, 0xFF9BC3DD, 0xFF87AEC8, 0xFF6784A2, 0xFFC5D1D9, 0xFFC6D6E0, 0xFFB0BEC8 },
{ 0xFF448CF5, 0x77B9F9, 0xFF9CBDED, 0xFF87A7D6, 0xFF5E7FB8, 0xFFD0DAE8, 0xFFD0DDF0, 0xFFB9C4D6 },
{ 0xFF044CF5, 0x8FABEB, 0xFF7FA0ED, 0xFF6A8AD6, 0xFF4065B4, 0xFFC8D1E8, 0xFFC4D1F0, 0xFFAEBAD6 },
{ 0xFFAC00FF, 0xD899F6, 0xFFD183F7, 0xFFB96DDF, 0xFF8F41B5, 0xFFE6D0F2, 0xFFEBCCFA, 0xFFD1B5DF },
{ 0xFFFF0032, 0xF9A0B1, 0xFFF78399, 0xFFDF6D83, 0xFFC0436B, 0xFFF2D0D6, 0xFFFACCD5, 0xFFDFB5BD },
{ 0xFFFF6042, 0xF9BBAF, 0xFFF7AEA1, 0xFFDF978A, 0xFFB5525F, 0xFFF2DCD8, 0xFFFADDD7, 0xFFDFC4BF },
{ 0xFFFF7F24, 0xF5C5A3, 0xFFF7BC93, 0xFFDFA57D, 0xFFC7825F, 0xFFF2E0D4, 0xFFFAE2D2, 0xFFDFC9BA },
{ 0xFFE8ECF9, 0xE5E7ED, 0xFFE9EBF1, 0xFFD2D3D9, 0xFFA9AAB0, 0xFFEAEAEC, 0xFFF1F1F4, 0xFFD6D7D9 },
{ 0xFFB7BBC5, 0xA4A5AA, 0xFFB8BABE, 0xFF9A9BA0, 0xFF85878B, 0xFFE9E9EA, 0xFFDEDFE1, 0xFFB9BABC },
};
const EsStyle styleSettingsCheckboxGroup = {
@ -710,14 +710,74 @@ int SettingsColorButtonMessage(EsElement *element, EsMessage *message) {
return 0;
}
int SettingsTransitionWindowMessage(EsElement *element, EsMessage *message) {
EsWindow *window = element->window;
if (message->type == ES_MSG_ANIMATE) {
window->animationTime += message->animate.deltaMs;
double progress = window->animationTime / GetConstantNumber("settingsTransitionDuration");
if (progress > 1) {
EsElementDestroy(window);
} else {
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, 0xFF * (1 - progress), 0, ES_WINDOW_PROPERTY_ALPHA);
EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0);
message->animate.complete = false;
message->animate.waitMs = 10;
return ES_HANDLED;
}
}
return 0;
}
void SettingsCreateTransitionWindow() {
if (!desktop.setupDesktopUIComplete) {
return;
}
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
EsRectangle region = ES_RECT_2S(ES_RECT_WIDTH(screen), ES_RECT_HEIGHT(screen));
uint32_t *screenshot = (uint32_t *) EsHeapAllocate(region.r * region.b * 4, false);
if (!screenshot) {
return;
}
EsSyscall(ES_SYSCALL_SCREEN_GET_BITS, 0, (uintptr_t) &region, (uintptr_t) screenshot, 0);
for (intptr_t i = 0; i < region.r * region.b; i++) {
screenshot[i] |= 0xFF000000;
}
EsWindow *transition = EsWindowCreate(nullptr, ES_WINDOW_PLAIN);
if (transition) {
transition->messageUser = SettingsTransitionWindowMessage;
transition->doNotPaint = true;
transition->StartAnimating();
EsSyscall(ES_SYSCALL_WINDOW_MOVE, transition->handle, (uintptr_t) &screen, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, transition->handle, 0, 0, ES_WINDOW_PROPERTY_SOLID);
EsSyscall(ES_SYSCALL_WINDOW_SET_BITS, transition->handle, (uintptr_t) &region, (uintptr_t) screenshot, 0);
EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0);
}
EsHeapFree(screenshot);
}
void SettingsWindowColorUpdated() {
SettingsCreateTransitionWindow();
uint8_t index = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("window_color"));
if (index > sizeof(windowColors) / sizeof(windowColors[0])) {
index = 0;
}
EsMemoryCopy(theming.windowColors, &windowColors[index][1], sizeof(theming.windowColors));
EsMemoryCopy(theming.windowColors, &windowColors[index][2], sizeof(theming.windowColors));
desktop.wallpaperBackgroundColor = windowColors[index][1];
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
if (gui.allWindows[i]->windowStyle == ES_WINDOW_CONTAINER) {
@ -725,6 +785,10 @@ void SettingsWindowColorUpdated() {
UIWindowNeedsUpdate(gui.allWindows[i]);
}
}
if (desktop.isWallpaperBackgroundColorVisible) {
EsThreadCreate(WallpaperLoad, nullptr, 0);
}
}
void SettingsColorButtonCommand(EsInstance *, EsElement *element, EsCommand *) {

View File

@ -1359,14 +1359,42 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_GET_TLS) {
SYSCALL_RETURN(currentThread->tlsAddress, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_SCREEN_GET_BITS) {
SYSCALL_PERMISSION(ES_PERMISSION_SCREEN_MODIFY);
EsRectangle rectangle;
SYSCALL_READ(&rectangle, argument1, sizeof(EsRectangle));
SYSCALL_BUFFER(argument2, Width(rectangle) * Height(rectangle) * 4, 1, false);
KMutexAcquire(&windowManager.mutex);
EsRectangle source = EsRectangleIntersection(rectangle, ES_RECT_2S(graphics.frameBuffer.width, graphics.frameBuffer.height));
uint32_t *bits = (uint32_t *) graphics.frameBuffer.bits;
uint32_t *destination = (uint32_t *) argument2;
if (ES_RECT_VALID(source)) {
for (int32_t y = source.t; y < source.b; y++) {
for (int32_t x = source.l; x < source.r; x++) {
uint32_t p = bits[x + y * graphics.frameBuffer.stride / sizeof(uint32_t)];
destination[(x - (source.l - rectangle.l)) + (y - (source.t - rectangle.t)) * (rectangle.r - rectangle.l)] = p;
}
}
}
KMutexRelease(&windowManager.mutex);
SYSCALL_RETURN(ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_SCREEN_BOUNDS_GET) {
EsRectangle rectangle;
EsMemoryZero(&rectangle, sizeof(EsRectangle));
KMutexAcquire(&windowManager.mutex);
rectangle.l = 0;
rectangle.t = 0;
rectangle.r = graphics.width;
rectangle.b = graphics.height;
KMutexRelease(&windowManager.mutex);
SYSCALL_WRITE(argument1, &rectangle, sizeof(EsRectangle));
SYSCALL_RETURN(ES_SUCCESS, false);

Binary file not shown.

View File

@ -1608,7 +1608,8 @@ uint8_t *EsImageLoad(const void *file, size_t fileSize, uint32_t *imageX, uint32
#endif
}
void LoadImage(const void *path, ptrdiff_t pathBytes, void *destination, int destinationWidth, int destinationHeight, bool fromMemory) {
void LoadImage(const void *path, ptrdiff_t pathBytes, void *destination, int destinationWidth, int destinationHeight,
bool fromMemory, bool *_coversDestination = nullptr) {
int width = 0, height = 0;
uint32_t *image = nullptr;
@ -1625,19 +1626,21 @@ void LoadImage(const void *path, ptrdiff_t pathBytes, void *destination, int des
}
int cx = destinationWidth / 2 - width / 2, cy = destinationHeight / 2 - height / 2;
bool coversDestination = true;
for (int j = 0; j < destinationHeight; j++) {
uint32_t *pixel = (uint32_t *) ((uint8_t *) destination + j * destinationWidth * 4);
for (int i = 0; i < destinationWidth; i++, pixel++) {
if (i - cx < 0 || i - cx >= width || j - cy < 0 || j - cy >= height) {
*pixel = 0x77B9F9;
} else {
if (i - cx >= 0 && i - cx < width && j - cy >= 0 && j - cy < height) {
*pixel = image[i - cx + (j - cy) * width];
} else {
coversDestination = false;
}
}
}
if (_coversDestination) *_coversDestination = coversDestination;
EsHeapFree(image);
}
#endif

View File

@ -326,7 +326,7 @@ Option options[] = {
{ "BuildCore.RequiredFontsOnly", OPTION_TYPE_BOOL, { .b = false } },
{ "General.first_application", OPTION_TYPE_STRING, { .s = NULL } },
{ "General.wallpaper", OPTION_TYPE_STRING, { .s = NULL } },
{ "General.window_color", OPTION_TYPE_STRING, { .s = "9" } },
{ "General.window_color", OPTION_TYPE_STRING, { .s = "2" } },
{ "General.installation_state", OPTION_TYPE_STRING, { .s = "0" } },
{ "General.ui_scale", OPTION_TYPE_STRING, { .s = "100" } },
{ "General.keyboard_layout", OPTION_TYPE_STRING, { .s = "us" } },