Compare commits

..
Author SHA1 Message Date
Hanif Koh 64035de87e Restore Plugin HTML After a Webview Reload
Plugin dialog content is injected with SetPage, so the webview's current URL
stays the base URL and the injected document has none of its own. Reloading the
page (context menu or keyboard shortcut) therefore re-fetches the base URL and
the plugin UI disappears, permanently: load_plugin_content() returned early once
m_content_loaded was set.

Re-inject the plugin HTML whenever a main-frame load arrives after the initial
swap. m_own_page_load marks the load caused by our own SetPage so it is not
mistaken for a reload, and in-document navigation is ignored: the MSW backend
synthesises a wxEVT_WEBVIEW_LOADED when a page changes location.hash, which
would otherwise wipe the page under the user. A post-load error is left alone
too, as it only ever means a failed subresource.
2026-09-16 14:09:46 +08:00
3 changed files with 44 additions and 76 deletions
+13 -70
View File
@@ -8,7 +8,7 @@ SCRIPT_PATH=$(dirname "$(readlink -f "${0}")")
pushd "${SCRIPT_PATH}" > /dev/null
function usage() {
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L [lld|mold]]"
echo "Usage: ./${SCRIPT_NAME} [-1][-b][-c][-d][-D][-e][-F][-g][-h][-i][-j N][-p][-r][-s][-t][-u][-l][-L]"
echo " -1: limit builds to one core (where possible)"
echo " -j N: limit builds to N cores (where possible)"
echo " -b: build in Debug mode"
@@ -27,7 +27,7 @@ function usage() {
echo " -t: build tests (optional), requires -s flag"
echo " -u: install system dependencies (asks for sudo password; build prerequisite)"
echo " -l: use Clang instead of GCC (default: GCC)"
echo " -L [lld|mold]: use an alternate linker (if available) (default: lld)"
echo " -L: use ld.lld as linker (if available)"
echo "For a first use, you want to './${SCRIPT_NAME} -u'"
echo " and then './${SCRIPT_NAME} -dsi'"
echo "For a GitHub Actions-like Linux build locally, use './${SCRIPT_NAME} -g -istrlL'"
@@ -115,24 +115,8 @@ while getopts ":1j:bcCdDeFghiprstulL" opt ; do
FORWARDED_ARGS+=("-l")
;;
L )
# -L takes an optional argument. getopts has no native support for
# this, so L is declared bare (no ':') in the optstring above, and we
# manually peek at the next unconsumed argv token via ${!OPTIND}. If
# it's a bare 'lld' or 'mold' (not another option, i.e. doesn't start
# with '-'), consume it as the explicit choice and advance OPTIND so
# getopts doesn't reprocess it as a new flag. Otherwise, leave it
# alone (it isn't meant for -L) and default to lld.
LINKER_NAME="lld"
next_arg="${!OPTIND-}"
if [[ -n "${next_arg}" ]] && [[ "${next_arg}" != -* ]] ; then
case "${next_arg}" in
lld|mold )
LINKER_NAME="${next_arg}"
OPTIND=$((OPTIND + 1))
;;
esac
fi
FORWARDED_ARGS+=("-L" "${LINKER_NAME}")
USE_LLD="1"
FORWARDED_ARGS+=("-L")
;;
* )
echo "Unknown argument '${opt}', aborting."
@@ -151,12 +135,6 @@ if [[ -n "${CLEAN_DOCKER_IMAGE}" ]] && [[ -z "${USE_DOCKER}" ]] ; then
exit 1
fi
if [[ -n "${USE_DOCKER}" ]] && [[ "${LINKER_NAME}" == "mold" ]] ; then
echo "Error: -L mold is not available in the Docker/Podman build image, so -g and -L mold cannot be combined."
echo "Omit -L mold when using -g (the container build defaults to GCC without mold), or drop -g and build with -L mold directly on a host with mold installed."
exit 1
fi
function check_available_memory_and_disk() {
FREE_MEM_GB=$(free --gibi --total | grep 'Mem' | rev | cut --delimiter=" " --fields=1 | rev)
MIN_MEM_GB=10
@@ -514,49 +492,14 @@ if [[ -n "${USE_CLANG}" ]] ; then
export CMAKE_C_CXX_COMPILER_CLANG=(-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++)
fi
# Configure use of an alternate linker (-L lld or -L mold) when requested
export CMAKE_LINKER_ARGS=()
if [[ -n "${LINKER_NAME}" ]] ; then
case "${LINKER_NAME}" in
lld )
LINKER_BIN_NAME="ld.lld"
;;
mold )
LINKER_BIN_NAME="mold"
# -fuse-ld=mold requires GCC 12.1+. Older GCC (e.g. GCC 11, shipped
# for Ubuntu 22.x via scripts/linux.d/debian) doesn't understand the
# flag, and cmake's compiler check then fails with a confusing
# generic "is not able to compile a simple test program" error
# instead of naming the real cause. Catch it here instead.
if [[ -z "${USE_CLANG}" ]] ; then
GCC_BIN="${CC:-gcc}"
if ! command -v "${GCC_BIN}" >/dev/null 2>&1 ; then
GCC_BIN="cc"
fi
if command -v "${GCC_BIN}" >/dev/null 2>&1 ; then
GCC_VERSION=$("${GCC_BIN}" -dumpfullversion 2>/dev/null)
if [[ -n "${GCC_VERSION}" ]] && [[ "$(printf '%s\n%s\n' "${GCC_VERSION}" "12.1" | sort -V | head -n1)" != "12.1" ]] ; then
echo "Error: -L mold requires GCC 12.1 or newer to support -fuse-ld=mold (found GCC ${GCC_VERSION} via '${GCC_BIN}')."
echo "Use -l to build with Clang instead, upgrade your GCC toolchain, or omit -L mold."
exit 1
fi
fi
fi
;;
esac
if command -v "${LINKER_BIN_NAME}" >/dev/null 2>&1 ; then
LINKER_BIN=$(command -v "${LINKER_BIN_NAME}")
export CMAKE_LINKER_ARGS=(-DCMAKE_LINKER="${LINKER_BIN}" "-DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=${LINKER_NAME}" "-DCMAKE_SHARED_LINKER_FLAGS=-fuse-ld=${LINKER_NAME}" "-DCMAKE_MODULE_LINKER_FLAGS=-fuse-ld=${LINKER_NAME}")
# Configure use of ld.lld as the linker when requested
export CMAKE_LLD_LINKER_ARGS=()
if [[ -n "${USE_LLD}" ]] ; then
if command -v ld.lld >/dev/null 2>&1 ; then
LLD_BIN=$(command -v ld.lld)
export CMAKE_LLD_LINKER_ARGS=(-DCMAKE_LINKER="${LLD_BIN}" -DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=lld -DCMAKE_SHARED_LINKER_FLAGS=-fuse-ld=lld -DCMAKE_MODULE_LINKER_FLAGS=-fuse-ld=lld)
else
case "${LINKER_NAME}" in
lld )
echo "Error: ld.lld not found. Please install the 'lld' package (e.g., sudo apt install lld) or omit -L lld."
;;
mold )
echo "Error: mold not found. Please install the 'mold' package or omit -L mold."
;;
esac
echo "Error: ld.lld not found. Please install the 'lld' package (e.g., sudo apt install lld) or omit -L."
exit 1
fi
fi
@@ -593,7 +536,7 @@ if [[ -n "${BUILD_DEPS}" ]] ; then
BUILD_ARGS+=(-DCMAKE_BUILD_TYPE="${BUILD_CONFIG}")
fi
print_and_run cmake -S deps -B deps/$BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G Ninja "${COLORED_OUTPUT}" "${BUILD_ARGS[@]}"
print_and_run cmake -S deps -B deps/$BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G Ninja "${COLORED_OUTPUT}" "${BUILD_ARGS[@]}"
print_and_run cmake --build deps/$BUILD_DIR -j1
fi
@@ -613,7 +556,7 @@ if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
BUILD_ARGS+=(-DORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY}")
fi
print_and_run cmake -S . -B $BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G "Ninja Multi-Config" \
print_and_run cmake -S . -B $BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G "Ninja Multi-Config" \
-DSLIC3R_PCH=${SLIC3R_PRECOMPILED_HEADERS} \
-DORCA_TOOLS=ON \
"${COLORED_OUTPUT}" \
+29 -6
View File
@@ -55,6 +55,16 @@ wxString web_base_url()
return wxString("file://") + from_u8(dir) + "/";
}
// True when two consecutive main-frame URLs name the same document, i.e. they differ
// only in the fragment. The MSW backend synthesises a wxEVT_WEBVIEW_LOADED for such
// in-document navigation (a page setting location.hash), which must not be mistaken
// for a reload; an identical URL is a genuine reload and is not fragment navigation.
bool is_fragment_navigation(const wxString& from, const wxString& to)
{
return from != to && from.BeforeFirst('#') == to.BeforeFirst('#');
}
} // namespace
PluginWebDialog::PluginWebDialog(wxWindow* parent,
@@ -139,19 +149,32 @@ void PluginWebDialog::destroy_for_plugin(PluginWebDialog* dialog)
void PluginWebDialog::on_bootstrap_event(wxWebViewEvent& event)
{
// The first bootstrap load (or its error) triggers the swap to plugin HTML;
// the resulting plugin-page load is ignored (guarded by m_content_loaded).
load_plugin_content();
// The first bootstrap load (or its error) triggers the swap to plugin HTML. Once that
// page has settled, a further main-frame load is a browser reload (context menu or
// keyboard shortcut): the injected page has no URL of its own, so the reload fetches
// the base URL instead and the plugin HTML has to be put back. In-document navigation
// is not a reload and must be left alone, as is a post-load error, which only ever
// means a failed subresource.
if (!m_content_loaded)
load_plugin_content();
else if (event.GetEventType() == wxEVT_WEBVIEW_LOADED) {
const wxString previous_url = m_last_url;
m_last_url = event.GetURL();
if (m_own_page_load)
m_own_page_load = false;
else if (!is_fragment_navigation(previous_url, m_last_url))
load_plugin_content();
}
event.Skip();
}
void PluginWebDialog::load_plugin_content()
{
if (m_content_loaded)
return;
m_content_loaded = true;
if (wxWebView* wv = browser())
if (wxWebView* wv = browser()) {
m_own_page_load = true;
wv->SetPage(wxString::FromUTF8(m_html), web_base_url());
}
}
void PluginWebDialog::on_script_message(const nlohmann::json& payload)
+2
View File
@@ -72,6 +72,8 @@ private:
std::string m_html;
bool m_content_loaded{false};
bool m_own_page_load{false}; // a SetPage of the plugin HTML is in flight
wxString m_last_url; // URL of the last main-frame load, to spot fragment navigation
bool m_open{true};
bool m_close_fired{false};
std::optional<nlohmann::json> m_result;