Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,6 @@ option(FETCH_EFSW "Fetch efsw" ON)
option(NUI_SFT_ENABLE_LANGUAGE_TOOLING "Enable building language tooling, which includes a command line tool for checking language files" OFF)
option(TAR_ARCHIVE_HAS_XZ "Enable xz (liblzma) compression in the tar-archive library" ON)

if (OFFLINE_BUILD)
include("${CMAKE_CURRENT_LIST_DIR}/_cmake/offline_build.cmake")
endif()

if (OMIT_FRONTEND_BUILD)
set(NUI_OMIT_FRONTEND ON CACHE BOOL "Do not build the frontend, sometimes useful for environments where emscripten is hard to use" FORCE)
endif()

if (NOT EMSCRIPTEN)
set(BACKEND_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
endif()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/_cmake/configured_files/build_environment.hpp.in"
"${CMAKE_BINARY_DIR}/include/build_environment.hpp"
)

include (${CMAKE_CURRENT_LIST_DIR}/_cmake/common_options.cmake)

# Webkit from custom build
if (NOT EMSCRIPTEN)
if (WEBKIT_PATH)
Expand All @@ -62,6 +44,37 @@ if (NOT EMSCRIPTEN)
endif()
endif()

# Nui and webview both look up WebKitGTK, with different preferences they linked GTK 3 and GTK 4 at once.
# One API for both: webkitgtk-6.0 (GTK 4) where it is installed, otherwise webkit2gtk-4.1 (GTK 3).
if (NOT EMSCRIPTEN AND UNIX AND NOT APPLE)
find_package(PkgConfig REQUIRED)
if (WEBKIT_PATH)
pkg_search_module(webkit REQUIRED IMPORTED_TARGET ${WEBKIT_PACKAGE_NAME})
else()
pkg_search_module(webkit REQUIRED IMPORTED_TARGET webkitgtk-6.0 webkit2gtk-4.1 webkit2gtk-4.0)
endif()
set(WEBVIEW_WEBKITGTK_MODULE_NAME "${webkit_MODULE_NAME}")
message(STATUS "WebKitGTK API: ${webkit_MODULE_NAME}")
endif()

if (OFFLINE_BUILD)
include("${CMAKE_CURRENT_LIST_DIR}/_cmake/offline_build.cmake")
endif()

if (OMIT_FRONTEND_BUILD)
set(NUI_OMIT_FRONTEND ON CACHE BOOL "Do not build the frontend, sometimes useful for environments where emscripten is hard to use" FORCE)
endif()

if (NOT EMSCRIPTEN)
set(BACKEND_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
endif()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/_cmake/configured_files/build_environment.hpp.in"
"${CMAKE_BINARY_DIR}/include/build_environment.hpp"
)

include (${CMAKE_CURRENT_LIST_DIR}/_cmake/common_options.cmake)

# Nui Dependency
add_subdirectory("${CMAKE_SOURCE_DIR}/dependencies/Nui" EXCLUDE_FROM_ALL)

Expand Down
8 changes: 8 additions & 0 deletions _cmake/copy_styles_to_build_dir.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ if (NOT OMIT_FRONTEND_BUILD)
add_custom_command(
OUTPUT
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid.css"
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background.png"
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background_light.png"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/button.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/carousel.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/color_picker.css"
Expand All @@ -27,6 +29,8 @@ if (NOT OMIT_FRONTEND_BUILD)
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/styles/5cript-nui-components"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/themes"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid.css" "${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background.png" "${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background.png"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background_light.png" "${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background_light.png"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/button.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/button.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/carousel.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/carousel.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/color_picker.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/color_picker.css"
Expand All @@ -50,6 +54,8 @@ if (NOT OMIT_FRONTEND_BUILD)
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/themes/light.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/themes/light.css"
DEPENDS
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid.css"
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background.png"
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background_light.png"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/button.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/carousel.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/color_picker.css"
Expand Down Expand Up @@ -78,6 +84,8 @@ if (NOT OMIT_FRONTEND_BUILD)
ALL
DEPENDS
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid.css"
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background.png"
"${CMAKE_BINARY_DIR}/styles/nui-file-explorer/file_grid_background_light.png"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/button.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/carousel.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/color_picker.css"
Expand Down
6 changes: 6 additions & 0 deletions backend/source/backend/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#else
# include <backend/linux/main_linux.hpp>
# include <backend/process/fork_pool.hpp>

# include <glib.h>
#endif

#include <backend/inspector_environment.hpp>
Expand Down Expand Up @@ -476,6 +478,10 @@ int main(int const argc, char const* const* argv)

#ifdef __linux__
setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", 0);
// GTK 4 does not take it from argv like GTK 3, it names the X11 WM_CLASS and the Wayland app id.
// In a flatpak WebKit has to use the app id, the portal refuses to spawn its sandboxed web process otherwise.
const char* const flatpakApplicationId = std::getenv("FLATPAK_ID");
g_set_prgname(flatpakApplicationId != nullptr && *flatpakApplicationId != '\0' ? flatpakApplicationId : "nui-sftp");
#endif

ssh_init();
Expand Down
2 changes: 2 additions & 0 deletions frontend/source/frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ nui_prepare_emscripten_target(
OBSERVED_BUNDLE_FILES
"${CMAKE_SOURCE_DIR}/static/index.html"
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid.css"
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background.png"
"${CMAKE_SOURCE_DIR}/nui-file-explorer/styles/file_grid_background_light.png"
"${CMAKE_SOURCE_DIR}/static/source/content_panels/file_explorer.ts"
"${CMAKE_SOURCE_DIR}/static/source/content_panels/terminal.ts"
"${CMAKE_SOURCE_DIR}/static/source/content_panel_manager.ts"
Expand Down
27 changes: 8 additions & 19 deletions nui-file-explorer/styles/file_grid.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,13 @@
}

.nui-file-grid-background {
/* Makes glass work */
--background-image:
radial-gradient(at 56% 8%, hsla(323, 64%, 77%, 1) 0px, transparent 50%),
radial-gradient(at 88% 7%, hsla(186, 94%, 76%, 1) 0px, transparent 50%),
radial-gradient(at 67% 1%, hsla(321, 80%, 79%, 1) 0px, transparent 50%),
radial-gradient(at 60% 69%, hsla(39, 75%, 79%, 1) 0px, transparent 50%),
radial-gradient(at 22% 33%, hsla(314, 83%, 65%, 1) 0px, transparent 50%),
radial-gradient(at 7% 91%, hsla(200, 78%, 70%, 1) 0px, transparent 50%),
radial-gradient(at 19% 86%, hsla(137, 62%, 74%, 1) 0px, transparent 50%);

background-image: var(--background-image);
/* Makes glass work. Radial gradients multiplied over the background color, pre-rendered by
scripts/render_file_grid_background.py because WebKitGTK paints live gradients slowly */
background-image: var(--background-image, url("data-url:./file_grid_background.png"));
background-size: 100% 100%;

/* Darken overlay to improve contrast (doesn't affect child elements) */
background-color: rgba(0, 0, 0, 0.55);
background-blend-mode: multiply;
}

.nui-file-grid-content:first-child {
Expand Down Expand Up @@ -212,8 +204,8 @@
overflow: hidden;
isolation: isolate;

box-shadow: 0 10px 25px rgba(0, 0, 0, 0.35);
transition: transform 120ms ease, box-shadow 120ms ease;
/* WebKitGTK paints without compositing: blurry shadows and hover transitions repaint the whole grid */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.35);

&[data-type="Symbolic Link"] {
color: var(--nui-file-grid-symbolic-link-color, rgb(0, 242, 255));
Expand Down Expand Up @@ -261,8 +253,6 @@
linear-gradient(145deg,
rgba(255, 255, 255, 0.32),
rgba(255, 255, 255, 0.05));

transition: background 120ms ease;
}

/* ── Specular highlight border ── */
Expand All @@ -277,7 +267,6 @@
inset 2px 2px 0px -1px rgba(255, 255, 255, 0.75),
inset 0 0 4px 1px rgba(255, 255, 255, 0.45);
pointer-events: none;
transition: box-shadow 120ms ease, border-color 120ms ease;
}

/* ── Content above pseudo layers ── */
Expand All @@ -288,7 +277,7 @@

.nui-file-grid-item-icons.is-muted {
opacity: 0.55;
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.45);
filter: saturate(70%) brightness(85%);
}

Expand Down Expand Up @@ -343,7 +332,7 @@

.nui-file-grid-item-icons:hover {
transform: translateY(-2px);
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.45);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.45);
}

.nui-file-grid-item-icons:hover::before {
Expand Down
Binary file added nui-file-explorer/styles/file_grid_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"webpage:serve": "npm --prefix webpage run serve"
},
"devDependencies": {
"@parcel/optimizer-data-url": "^2.13.0",
"@parcel/transformer-inline-string": "^2.13.0",
"cross-env": "^7.0.3",
"dotenv": "^16.4.5",
"less": "^4.2.2",
Expand Down
71 changes: 71 additions & 0 deletions scripts/render_file_grid_background.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
# Renders the file grid background images into nui-file-explorer/styles.
# Seven radial gradients multiplied over the grid background color, following CSS Images 3 (farthest-corner
# ellipses, premultiplied interpolation) and Compositing 1 (separable blend, then source-over) in sRGB.
# The image holds only what the gradients add, drawn over that same background color it reproduces the blend.
# WebKitGTK paints the live gradients on the CPU on every repaint, a stretched image is far cheaper.
# Usage: render_file_grid_background.py [width] [height]
import colorsys
import sys
from pathlib import Path

import numpy as np
from PIL import Image

styles = Path(__file__).resolve().parent.parent / "nui-file-explorer/styles"
width = int(sys.argv[1]) if len(sys.argv) > 1 else 160
height = int(sys.argv[2]) if len(sys.argv) > 2 else 128

# (x %, y %, hue, saturation %, lightness %), first entry is the top layer
spots = [
(56, 8, 323, 64, 77),
(88, 7, 186, 94, 76),
(67, 1, 321, 80, 79),
(60, 69, 39, 75, 79),
(22, 33, 314, 83, 65),
(7, 91, 200, 78, 70),
(19, 86, 137, 62, 74),
]

# file name -> background color (r, g, b, a) of .nui-file-grid-background in that theme
variants = {
"file_grid_background.png": (0, 0, 0, 0.55),
"file_grid_background_light.png": (224 / 255, 224 / 255, 224 / 255, 1),
}


def blendedGradients(backdropColor, backdropAlpha):
rows, columns = np.mgrid[0:height, 0:width].astype(np.float64) + 0.5
premultiplied = np.broadcast_to(np.array(backdropColor) * backdropAlpha, (height, width, 3)).copy()
alpha = np.full((height, width), backdropAlpha)
for spotX, spotY, hue, saturation, lightness in reversed(spots):
source = np.array(colorsys.hls_to_rgb(hue / 360, lightness / 100, saturation / 100))
centerX = spotX / 100 * width
centerY = spotY / 100 * height
radiusX = max(centerX, width - centerX) * np.sqrt(2)
radiusY = max(centerY, height - centerY) * np.sqrt(2)
distance = np.sqrt(((columns - centerX) / radiusX) ** 2 + ((rows - centerY) / radiusY) ** 2)
sourceAlpha = np.clip(1 - distance / 0.5, 0, 1)[..., None]

layerAlpha = alpha[..., None]
backdrop = premultiplied / np.maximum(layerAlpha, 1e-9)
blended = (1 - layerAlpha) * source + layerAlpha * source * backdrop
premultiplied = sourceAlpha * blended + (1 - sourceAlpha) * premultiplied
alpha = sourceAlpha[..., 0] + alpha * (1 - sourceAlpha[..., 0])
return premultiplied, alpha


for fileName, (red, green, blue, backdropAlpha) in variants.items():
backdropColor = np.array([red, green, blue])
premultiplied, alpha = blendedGradients(backdropColor, backdropAlpha)
if backdropAlpha >= 1:
imageAlpha = np.ones_like(alpha)
imagePremultiplied = premultiplied
else:
# Solve image over backdrop == blended result
imageAlpha = np.clip((alpha - backdropAlpha) / (1 - backdropAlpha), 0, 1)
imagePremultiplied = premultiplied - (1 - imageAlpha[..., None]) * backdropAlpha * backdropColor
color = np.clip(imagePremultiplied / np.maximum(imageAlpha[..., None], 1e-9), 0, 1)
pixels = np.round(np.dstack([color, imageAlpha]) * 255).astype(np.uint8)
Image.fromarray(pixels, "RGBA").save(styles / fileName, optimize=True)
print(f"{styles / fileName} {width}x{height}")
1 change: 1 addition & 0 deletions static/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@

& .nui-file-grid-background {
background-color: var(--background-color);
background-image: var(--background-image, url("data-url:../../../styles/nui-file-explorer/file_grid_background_light.png"));
}

& .nui-file-grid-item-icons:is(.selected)::after {
Expand Down
8 changes: 7 additions & 1 deletion static/styles/main_page.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@
.main-page-wrap {
width: 100%;
height: 100%;
}
}
/* WebKitGTK paints without compositing and repaints whatever lies under an overlay repaint, skip the covered session area */
.settings-page-background-blocker[style*="display: flex"] ~ .main-page .session-area,
.licenses-page-background-blocker[style*="display: flex"] ~ .main-page .session-area,
.notification-log-background-blocker[style*="display: flex"] ~ .main-page .session-area {
content-visibility: hidden;
}
2 changes: 1 addition & 1 deletion themes/Plain.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
}

.nui-file-grid-background {
--background-image: unset !important;
--background-image: none !important;
}
Loading