diff --git a/resources/web/dialog/SpeedDial/style.css b/resources/web/dialog/SpeedDial/style.css index 8afc33d98c..5c29e68cdb 100644 --- a/resources/web/dialog/SpeedDial/style.css +++ b/resources/web/dialog/SpeedDial/style.css @@ -21,6 +21,7 @@ body { flex-direction: column; background: var(--panel, var(--orca-bg, #fff)); border: 1px solid var(--border, var(--orca-border, #ddd)); + border-radius: 7px; overflow: hidden; /* why: no height cap here - the launcher reports its true natural height to C++, which sizes the popup to match (HTML is source of truth). The list's own max-height is what diff --git a/src/slic3r/GUI/SpeedDialDialog.cpp b/src/slic3r/GUI/SpeedDialDialog.cpp index 5fafac4a1a..aa857d0963 100644 --- a/src/slic3r/GUI/SpeedDialDialog.cpp +++ b/src/slic3r/GUI/SpeedDialDialog.cpp @@ -11,7 +11,9 @@ #include +#include #include +#include #include #include #include @@ -142,6 +144,7 @@ SpeedDialWebDialog::SpeedDialWebDialog(wxWindow* parent) SetSizer(sizer); SetClientSize(FromDIP(wxSize(kPopupWidth, kPopupMinHeight))); } + apply_rounded_shape(); } SpeedDialWebDialog::~SpeedDialWebDialog() { m_alive->store(false, std::memory_order_release); } @@ -168,6 +171,7 @@ void SpeedDialWebDialog::request_show() Show(); Raise(); + apply_rounded_shape(); if (m_page_ready) send_actions(); // Grab focus now and again on wxEVT_ACTIVATE; grabbing directly on the WebKit widget is @@ -245,6 +249,39 @@ void SpeedDialWebDialog::resize_to_content(int height) const int height_dip = std::max(kPopupMinHeight, std::min(height, max_dip)); SetClientSize(FromDIP(wxSize(kPopupWidth, height_dip))); Layout(); + apply_rounded_shape(); +} + +// Rounded corners: the webview paints an opaque rectangle, so round the whole top-level window +// with a shape region (same mask trick as FilamentPickerDialog). Binary edges, no anti-aliasing. +void SpeedDialWebDialog::apply_rounded_shape() +{ + const wxSize size = GetSize(); + if (size.GetWidth() <= 0 || size.GetHeight() <= 0) + return; + + m_shape_bmp.Create(size.GetWidth(), size.GetHeight(), 32); + if (!m_shape_bmp.IsOk()) + return; + + wxMemoryDC dc; + dc.SelectObject(m_shape_bmp); + dc.SetBackground(wxBrush(wxColour(0, 0, 0))); + dc.Clear(); + dc.SetBrush(wxBrush(wxColour(255, 255, 255, 255))); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRoundedRectangle(0, 0, size.GetWidth(), size.GetHeight(), FromDIP(m_corner_radius)); + dc.SelectObject(wxNullBitmap); + + wxRegion region(m_shape_bmp, wxColour(0, 0, 0)); + if (region.IsOk()) + SetShape(region); +} + +void SpeedDialWebDialog::on_dpi_changed(const wxRect&) +{ + apply_rounded_shape(); + Refresh(); } void SpeedDialWebDialog::run_action(const std::string& id, const std::string& title, const std::string& param) diff --git a/src/slic3r/GUI/SpeedDialDialog.hpp b/src/slic3r/GUI/SpeedDialDialog.hpp index f044652089..e7a4060e16 100644 --- a/src/slic3r/GUI/SpeedDialDialog.hpp +++ b/src/slic3r/GUI/SpeedDialDialog.hpp @@ -7,6 +7,8 @@ #include #include +#include + namespace Slic3r { namespace GUI { class SpeedDialWebDialog : public WebViewHostDialog @@ -25,8 +27,13 @@ private: void open_wiki(const std::string& id); void send_actions(); void search_tabs(); + void apply_rounded_shape(); + void on_dpi_changed(const wxRect& suggested_rect) override; bool m_page_ready{false}; + // Rounded corners via a window shape region, since the webview itself is opaque. + int m_corner_radius{7}; + wxBitmap m_shape_bmp; // Guards the CallAfter in on_script_message across dialog destruction, same as // PluginsDialog::m_alive (PluginsDialog.hpp:249). std::shared_ptr> m_alive = std::make_shared>(true);