Compare commits

..
Author SHA1 Message Date
Hanif Koh 4dd961d5b2 Refresh Dark Mode Colours When the System Theme Differs at Startup
On Linux and macOS the app follows the system theme: at startup it
overwrites the saved dark_color_mode with the system appearance. The label
colours and the cached dark mode flag were already set from the saved value
by then, and the later "changed" check reads the mode only after the
overwrite, so it never fires. For that session every dialog that maps its
colours through UpdateDlgDarkUI keeps the old mode, e.g. white dialogs on a
dark main window after switching the desktop to dark, or on a fresh install
on a dark desktop.

Refresh the label colours and the flag when the system theme differs from
the saved mode.
2026-10-12 15:10:56 +08:00
HanifKoh 4c2a63e11e Copy Plate Pick and Pattern File Paths When Loading a G-code 3MF (#16387)
The importer assigned pick_file.empty() and pattern_bbox_file.empty(), a bool, to the string fields, storing a one-character string instead of the path.
2026-10-12 14:14:28 +08:00
HanifKoh f8cf34c55b Reset the Fan Mover Instead of Releasing It (#16386)
Clearing per-export state called unique_ptr::release(), which gives up ownership without deleting. Every export uses a new GCode, so the pointer is still empty there today and nothing leaks; reset() states the intent and would free the object if a GCode were ever reused.
2026-10-12 13:42:19 +08:00
SoftFever d007134001 fix: update translation for Assistant(HMS) in Chinese localization 2026-10-12 12:53:16 +08:00
12 changed files with 75 additions and 117 deletions
@@ -569,16 +569,12 @@ on the **first** call. So:
#endif
```
**Before GTK starts**, only the environment exists. `CLI::run` (`src/OrcaSlicer.cpp`) sets the NVIDIA
DMABUF workaround and then branches on `GDK_BACKEND` (an `x11` prefix means the X11 opt-in). On both
paths, when `/proc/driver/nvidia/version` exists and the linked WebKitGTK honours the switch (>= 2.44,
`WebView::SupportsForceSharedMemory()`), it sets `WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` and
`WEBKIT_FORCE_DMABUF_RENDERER=1` (non-replacing): the proprietary driver cannot back WebKit's hardware
DMABUF renderer. On the default path it forces `GDK_BACKEND=x11` when wx lacks EGL and `WAYLAND_DISPLAY`
is set. It sets `WEBKIT_DISABLE_COMPOSITING_MODE=1` (non-replacing) only when both `DISPLAY` and
`WAYLAND_DISPLAY` are set and the linked WebKitGTK is older than 2.42, and calls `XInitThreads()`
**Before GTK starts**, only the environment exists. `CLI::run` (`src/OrcaSlicer.cpp`) branches on
`GDK_BACKEND` (an `x11` prefix means the X11 opt-in). On the default path it forces `GDK_BACKEND=x11`
when wx lacks EGL and `WAYLAND_DISPLAY` is set. It sets `WEBKIT_DISABLE_COMPOSITING_MODE=1`
(non-replacing) only when both `DISPLAY` and `WAYLAND_DISPLAY` are set, and calls `XInitThreads()`
only when `DISPLAY` is set. With neither variable set, the GUI refuses to start ("Neither DISPLAY nor
WAYLAND_DISPLAY set"). The details and the WebKit rules (c12912e0df) are in
WAYLAND_DISPLAY set"). The details and the WebKit rule (c12912e0df) are in
`references/webview-gl-aui-media.md` §WebKitGTK on Linux sessions.
**wx's own detectors**, for reference:
@@ -61,8 +61,7 @@ available; GTK2/WebKit1 is an opt-out configuration the GUI does not support.
11. A web host that re-themes in place handles `EVT_WEBVIEW_RECREATED` without `Skip()`; one that
needs a reload lets it through. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
12. Keep `WebViewWebKit`'s destructor removing the `"wx"` handler. §[Orca wrapper](#orca-webview-wrapper-widgetswebview)
13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case for
WebKitGTK older than 2.42, and never
13. Do not widen `WEBKIT_DISABLE_COMPOSITING_MODE` beyond Orca's default-path XWayland case, and never
make a page's progress depend only on a C++→JS callback. §[WebKitGTK on Linux](#webkitgtk-on-linux-sessions)
14. GL attribute lists: legacy `int[]` lists end with `0` and spell out `WX_GL_RGBA` and
`WX_GL_DOUBLEBUFFER`; `wxGLAttributes`/`wxGLContextAttrs` end with `EndList()`; MSAA is requested
@@ -568,66 +567,33 @@ vue-resize workaround script and sets a persistent SQLite cookie store on the vi
## WebKitGTK on Linux sessions
**Mechanism.** `CLI::run` (`src/OrcaSlicer.cpp`, under `#ifdef __WXGTK__`, before GTK initialises)
sets the NVIDIA DMABUF workaround and then branches on `GDK_BACKEND`:
- **Both paths**, before the split: when `/proc/driver/nvidia/version` exists and the linked WebKitGTK
honours the switch (>= 2.44, `WebView::SupportsForceSharedMemory()`), it sets
`WEBKIT_DMABUF_RENDERER_FORCE_SHM=1` and `WEBKIT_FORCE_DMABUF_RENDERER=1` non-replacing. The
proprietary driver cannot back WebKit's hardware DMABUF renderer, so the shared-memory transport keeps
accelerated compositing instead of dropping it; `WEBKIT_FORCE_DMABUF_RENDERER` clears the
Debian/Ubuntu/openSUSE `isNVIDIA()` early return, which otherwise returns before the FORCE_SHM check.
branches on `GDK_BACKEND`:
- **Default path** (`GDK_BACKEND` unset or not starting with `x11`): if wx lacks EGL (`!wxHAS_EGL`) and
`WAYLAND_DISPLAY` is set, it forces `GDK_BACKEND=x11`; it sets `WEBKIT_DISABLE_COMPOSITING_MODE=1`
non-replacing **only** when the linked WebKitGTK predates 2.42 (`WebView::NeedsCompositingWorkaround()`)
**and** both `DISPLAY` and `WAYLAND_DISPLAY` are non-empty (a Wayland session with
non-replacing **only** when both `DISPLAY` and `WAYLAND_DISPLAY` are non-empty (a Wayland session with
XWayland available — the session, not the backend GTK will pick); `XInitThreads()` runs only when
`DISPLAY` is set.
- **`GDK_BACKEND=x11…` opt-in path**: sets `DRI_PRIME=1` (and the NVIDIA PRIME variables when
`/proc/driver/nvidia/version` exists), calls `XInitThreads()`, and deliberately does **not** disable
compositing, which keeps hardware acceleration for Device / Setup Wizard / login pages.
compositing (the comment: the WebKit2GTK XWayland bug appears fixed in WebKit2GTK ≥ 2.42, and leaving
compositing on keeps hardware acceleration for Device / Setup Wizard / login pages).
Runtime backend detection elsewhere uses Orca's `is_running_on_wayland()` / `is_running_on_x11()`
(see `references/platforms.md`), not these environment variables.
**Pitfall.**
- **Rule:** On NVIDIA reach for `WEBKIT_DMABUF_RENDERER_FORCE_SHM` before
`WEBKIT_DISABLE_COMPOSITING_MODE`. **Why:** the proprietary driver cannot back WebKit's hardware
DMABUF renderer, leaving web views blank or slow; FORCE_SHM keeps accelerated compositing and only
skips the hardware path, while disabling compositing drops it. Threaded scrolling is a separate,
release-dependent default (off in 2.44/2.45, on from 2.46). `WEBKIT_DISABLE_DMABUF_RENDERER` is not a
substitute — it is read first, leaves the transport set empty (no compositing from 2.44 on, where the
X11/Wayland fallback renderers were removed) and has a reported crash path. On Debian/Ubuntu and
openSUSE the `isNVIDIA()` patch returns before the FORCE_SHM check, so `WEBKIT_FORCE_DMABUF_RENDERER=1`
must clear it first; that variable exists only in those patches. WebKit reads all of these once per
process, before the first WebView.
The test is `/proc/driver/nvidia/version`, so a hybrid laptop that renders on its iGPU also takes the
shared-memory path, which is a per-frame GPU readback rather than zero-copy; exporting
`WEBKIT_DMABUF_RENDERER_FORCE_SHM=0` in the environment restores the hardware path.
```cpp
// Wrong: kills compositing and threaded scrolling (and can crash on modern WebKit)
::setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", false);
// Right: keep compositing, skip only the hardware DMABUF path
if (::access("/proc/driver/nvidia/version", F_OK) == 0 && WebView::SupportsForceSharedMemory()) {
::setenv("WEBKIT_DMABUF_RENDERER_FORCE_SHM", "1", /*replace*/ false);
::setenv("WEBKIT_FORCE_DMABUF_RENDERER", "1", /*replace*/ false);
}
```
Cite: WebKit 2.52.6 `Source/WebKit/UIProcess/gtk/AcceleratedBackingStore.cpp`
(`rendererBufferTransportMode()`), Debian `disable-nvidia-dmabuf.patch`, WebKit bug 262607.
- **Rule:** Set `WEBKIT_DISABLE_COMPOSITING_MODE` only on the default path in Wayland sessions,
non-replacing (`setenv(..., false)`, so a value the user already exported wins), before GTK
initialises; never unconditionally, and only for the WebKitGTK releases that need it (older than
2.42, `WebView::NeedsCompositingWorkaround()`). Keep JS-side fallbacks so a page never
initialises; never unconditionally. Keep JS-side fallbacks so a page never
waits forever for a C++→JS call.
**Why:** WebKit2GTK accelerated compositing could fail silently under XWayland before 2.42, leaving
web views blank (Setup Wizard stuck on "Loading..."); the variable also turns off threaded scrolling,
so applying it on a newer WebKit needlessly drops both GPU compositing and async scrolling (the
Device tab loses its smoothness); without the JS timeout the user is stuck when the signal is lost.
**Why:** WebKit2GTK accelerated compositing could fail silently under XWayland, leaving web views
blank (Setup Wizard stuck on "Loading..."); disabling it everywhere needlessly drops hardware
acceleration; without the JS timeout the user is stuck when the signal is lost.
```cpp
// Wrong: unconditional, kills HW acceleration everywhere
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", false);
// Right (default path only): non-replacing, before GTK init, WebKitGTK < 2.42,
// Wayland session with XWayland
if (WebView::NeedsCompositingWorkaround() && display && *display && wayland && *wayland)
// Right (default path only): non-replacing, before GTK init, Wayland session with XWayland
if (display && *display && wayland && *wayland)
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /*replace*/ false);
```
Cite: c12912e0df (`src/OrcaSlicer.cpp`; `resources/web/guide/0/load.js` `OnInit`
+1 -1
View File
@@ -7478,7 +7478,7 @@ msgid "Update"
msgstr "更新"
msgid "Assistant(HMS)"
msgstr "助理(HMS)"
msgstr "助手(HMS)"
#, c-format, boost-format
msgid "Network plug-in v%s"
+2 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
# WebKit's NVIDIA DMABUF workaround (gnome-build-meta#754) is applied by the
# binary itself, gated on the runtime WebKitGTK version (src/OrcaSlicer.cpp).
# Work-around https://gitlab.gnome.org/GNOME/gnome-build-meta/-/issues/754
grep -q org.freedesktop.Platform.GL.nvidia /.flatpak-info && export WEBKIT_DISABLE_DMABUF_RENDERER=1
# Work-around https://github.com/bambulab/BambuStudio/issues/3440
# Use LC_NUMERIC instead of LC_ALL to prevent decimal separator issues
+8 -18
View File
@@ -161,7 +161,6 @@ using json = nlohmann::json;
#include <X11/Xlib.h>
#endif
#include <unistd.h>
#include "slic3r/GUI/Widgets/WebView.hpp"
#endif
#ifdef SLIC3R_GUI
@@ -1154,9 +1153,8 @@ int CLI::run(int argc, char **argv)
// opt-in path. The ~2020-era WebKit2GTK XWayland compositor bug it
// worked around appears fixed in WebKit2GTK >= 2.42; leaving it
// unset preserves WebKit hardware acceleration on Device / Setup
// Wizard / login / store. The default path applies it only on
// XWayland sessions and only when the linked WebKitGTK predates the
// fix (< 2.42), as a conservative fallback for older WebKit.
// Wizard / login / store. The default path still applies it on
// XWayland sessions as a conservative fallback for older WebKit.
// ------------------------------------------------------------------
{
const char* gdk_backend = ::getenv("GDK_BACKEND");
@@ -1164,14 +1162,6 @@ int CLI::run(int argc, char **argv)
// honours the first backend in the comma-separated list).
const bool x11_opt_in = gdk_backend && boost::starts_with(gdk_backend, "x11");
// NVIDIA's proprietary driver cannot back WebKitGTK's DMABUF renderer.
// Force the shared-memory transport, which keeps compositing and threaded
// scrolling; the second variable clears Debian/Ubuntu/openSUSE's isNVIDIA().
if (::access("/proc/driver/nvidia/version", F_OK) == 0 && WebView::SupportsForceSharedMemory()) {
::setenv("WEBKIT_DMABUF_RENDERER_FORCE_SHM", "1", /* replace */ false);
::setenv("WEBKIT_FORCE_DMABUF_RENDERER", "1", /* replace */ false);
}
if (x11_opt_in) {
// ===== X11 / XWayland (opted in via GDK_BACKEND=x11) =====
BOOST_LOG_TRIVIAL(info) << "GDK_BACKEND=x11 detected; applying v2.3.2 X11/XWayland workarounds.";
@@ -1215,15 +1205,15 @@ int CLI::run(int argc, char **argv)
}
#endif
// WebKit2GTK accelerated compositing could fail under XWayland
// on WebKit releases before 2.42. Disable it only then, and only
// when both DISPLAY and WAYLAND_DISPLAY are set (an XWayland
// session). Disabling it also turns off threaded scrolling, so on
// newer WebKit it only costs performance.
// WebKit2GTK compositing can fail under XWayland on older
// WebKit releases. Disable it only when both DISPLAY and
// WAYLAND_DISPLAY are set (i.e. an XWayland session is in
// use). On pure X11 or native Wayland, compositing is left
// enabled so WebKit retains HW acceleration.
{
const char* display_env_wk = ::getenv("DISPLAY");
const char* wayland_env_wk = ::getenv("WAYLAND_DISPLAY");
if (WebView::NeedsCompositingWorkaround() && display_env_wk && *display_env_wk && wayland_env_wk && *wayland_env_wk) {
if (display_env_wk && *display_env_wk && wayland_env_wk && *wayland_env_wk) {
::setenv("WEBKIT_DISABLE_COMPOSITING_MODE", "1", /* replace */ false);
}
}
@@ -429,8 +429,7 @@ if [ "\$XDG_SESSION_TYPE" = "wayland" ] && [ "\$ZINK_DISABLE_OVERRIDE" != "1" ];
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
export MESA_LOADER_DRIVER_OVERRIDE=zink
export GALLIUM_DRIVER=zink
# WebKit's NVIDIA DMABUF workaround is applied by the binary itself,
# gated on the runtime WebKitGTK version (src/OrcaSlicer.cpp).
export WEBKIT_DISABLE_DMABUF_RENDERER=1
fi
fi
fi
+2 -2
View File
@@ -1729,8 +1729,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//plate->pattern_file = it->second->pattern_file;
plate->no_light_thumbnail_file = it->second->no_light_thumbnail_file;
plate->top_file = it->second->top_file;
plate->pick_file = it->second->pick_file.empty();
plate->pattern_bbox_file = it->second->pattern_bbox_file.empty();
plate->pick_file = it->second->pick_file;
plate->pattern_bbox_file = it->second->pattern_bbox_file;
plate->config = it->second->config;
if (!plate->thumbnail_file.empty())
+1 -1
View File
@@ -3295,7 +3295,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_is_role_based_fan_on.fill(false);
m_role_based_fan_marker_layer.fill(-1);
m_fan_mover.release();
m_fan_mover.reset();
m_ordering_cache.clear();
// Belt printer: initialize belt-specific writer via virtual hook.
+7
View File
@@ -3232,9 +3232,16 @@ bool GUI_App::on_init_inner()
#ifdef _MSW_DARK_MODE
#ifndef __WINDOWS__
// The label colours and the dark mode flag were set above from the saved mode. When the system theme
// differs from it, refresh them, or dialogs that map their colours stay in the old mode for this session.
const bool saved_dark_mode = dark_mode();
wxSystemAppearance app = wxSystemSettings::GetAppearance();
GUI::wxGetApp().app_config->set("dark_color_mode", app.IsDark() ? "1" : "0");
GUI::wxGetApp().app_config->save();
if (dark_mode() != saved_dark_mode) {
init_label_colours();
Update_dark_mode_flag();
}
#endif // __APPLE__
-27
View File
@@ -69,10 +69,6 @@ webkit_web_view_run_javascript_finish (WebKitWebView
GError **error);
WEBKIT_API void
webkit_javascript_result_unref (WebKitJavascriptResult *js_result);
WEBKIT_API guint
webkit_get_major_version (void);
WEBKIT_API guint
webkit_get_minor_version (void);
}
#endif
@@ -405,29 +401,6 @@ bool WebView::NeedsRecreateOnShow()
return false;
#endif
}
bool WebView::NeedsCompositingWorkaround()
{
#ifdef __linux__
const guint major = webkit_get_major_version();
const guint minor = webkit_get_minor_version();
return major < 2 || (major == 2 && minor < 42);
#else
return false;
#endif
}
bool WebView::SupportsForceSharedMemory()
{
#ifdef __linux__
const guint major = webkit_get_major_version();
const guint minor = webkit_get_minor_version();
return major > 2 || (major == 2 && minor >= 44);
#else
return false;
#endif
}
#if wxUSE_WEBVIEW_EDGE
bool WebView::CheckWebViewRuntime()
{
-10
View File
@@ -30,16 +30,6 @@ public:
// ignoring every navigation. A panel that gets true here recreates its view on first Show().
static bool NeedsRecreateOnShow();
// True when the linked WebKitGTK predates 2.42, where accelerated compositing
// could fail silently on XWayland sessions, so it is forced off as a fallback.
// False on every other platform. Safe to call before GTK initialises.
static bool NeedsCompositingWorkaround();
// True when the linked WebKitGTK is new enough (>= 2.44) to honour
// WEBKIT_DMABUF_RENDERER_FORCE_SHM, the shared-memory transport switch.
// False on every other platform. Safe to call before GTK initialises.
static bool SupportsForceSharedMemory();
static void RecreateAll();
};
+37
View File
@@ -2043,3 +2043,40 @@ TEST_CASE("3MF XML entries declaring more than an int can hold fail to load", "[
CHECK_FALSE(parser.check_3mf_from_prusa(path));
}
}
TEST_CASE("Loading a gcode.3mf from a stream keeps the plate's pick and pattern file paths", "[3mf][Regression]")
{
Model model;
REQUIRE(load_stl((std::string(TEST_DATA_DIR) + "/test_3mf/Prusa.stl").c_str(), &model));
model.add_default_instances();
ScopedTemporaryDir backup_dir("orca_pick");
model.set_backup_path(backup_dir.string());
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
auto plate = std::make_unique<PlateData>();
plate->plate_index = 0;
plate->pick_file = (backup_dir.path() / "pick.png").string();
plate->pattern_bbox_file = (backup_dir.path() / "plate.json").string();
ScopedTemporaryFile temp(".3mf");
const std::string test_file = temp.string();
StoreParams store_params;
store_params.path = test_file.c_str();
store_params.model = &model;
store_params.config = &config;
store_params.plate_data_list.push_back(plate.get());
store_params.strategy = SaveStrategy::Zip64 | SaveStrategy::Silence;
REQUIRE(store_bbs_3mf(store_params));
boost::nowide::ifstream in(test_file, std::ios::binary);
Model dst_model;
DynamicPrintConfig dst_config;
PlateDataPtrs dst_plates;
Semver file_version;
dst_model.set_backup_path(backup_dir.string());
REQUIRE(load_gcode_3mf_from_stream(in, &dst_config, &dst_model, &dst_plates, &file_version));
REQUIRE(dst_plates.size() == 1);
CHECK(dst_plates.front()->pick_file == "Metadata/pick_1.png");
CHECK(dst_plates.front()->pattern_bbox_file == "Metadata/plate_1.json");
release_PlateData_list(dst_plates);
}