From d9a8557568f0b7ed7c960b82d7637076b571959e Mon Sep 17 00:00:00 2001 From: nakst <> Date: Thu, 10 Mar 2022 14:36:05 +0000 Subject: [PATCH] desktop: use color scheme to determine wallpaper background; fade transition when changing color scheme --- desktop/desktop.cpp | 31 +++++++++------ desktop/gui.cpp | 20 +++++----- desktop/os.header | 1 + desktop/settings.cpp | 88 +++++++++++++++++++++++++++++++++++++------ kernel/syscall.cpp | 28 ++++++++++++++ res/Theme Source.dat | Bin 530988 -> 531296 bytes shared/common.cpp | 11 ++++-- util/build_common.h | 2 +- 8 files changed, 143 insertions(+), 38 deletions(-) diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp index e7feafe..241951e 100644 --- a/desktop/desktop.cpp +++ b/desktop/desktop.cpp @@ -201,9 +201,12 @@ struct { HashStore 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) ®ion, (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) ®ion, (uintptr_t) buffer, 0); + EsSyscall(ES_SYSCALL_SCREEN_FORCE_UPDATE, true, 0, 0, 0); + // TODO Fade wallpaper in. + + EsHeapFree(path); } ////////////////////////////////////////////////////// diff --git a/desktop/gui.cpp b/desktop/gui.cpp index 234be9c..7c3c903 100644 --- a/desktop/gui.cpp +++ b/desktop/gui.cpp @@ -499,9 +499,12 @@ struct EsWindow : EsElement { Array 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); diff --git a/desktop/os.header b/desktop/os.header index 54897e1..67f5a7d 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -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 diff --git a/desktop/settings.cpp b/desktop/settings.cpp index 230e6c8..d77213f 100644 --- a/desktop/settings.cpp +++ b/desktop/settings.cpp @@ -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) ®ion, (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) ®ion, (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 *) { diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index f1c2a3e..2935726 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -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); diff --git a/res/Theme Source.dat b/res/Theme Source.dat index 6908a4485f71915aeb58f022e20bf968e70b6757..ee47deb36d260d26d9d556bc16ff8c562ba4ab69 100644 GIT binary patch delta 146 zcmZ3pMd86V1ujMg28IG=28Mjr>2ebp%{Dr`m^b;s!iwev^V=89X9Qv@bAW}T{mdQ~AZ7((w(V#3uqVU{I~J#wlw{_m y7l#xj<`rj_Waj5h-nU4Gi7|h=;!bws$puR^CN~_4oZPuceX_+Og~=O^asU92#6FY& delta 94 zcmaE`O<~Oz1ujMg28MiQ28KM=>2ebp%{Dr`n8$c#^23GY%?swYFPP5=#7scUynVrZ vmgN#mjIrA= 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 diff --git a/util/build_common.h b/util/build_common.h index efb5962..a05bdf8 100644 --- a/util/build_common.h +++ b/util/build_common.h @@ -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" } },