mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-11 18:01:14 +00:00
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c97343811 | ||
|
|
cff514cd15 | ||
|
|
7369674d8f | ||
|
|
70da7e89bb | ||
|
|
a671bf605d | ||
|
|
bae8f64b8b | ||
|
|
2df07b7ed8 | ||
|
|
295094a594 | ||
|
|
210bc927bc | ||
|
|
00cfb5b259 | ||
|
|
2bd105b0ce | ||
|
|
b81d761605 | ||
|
|
6922edfc20 | ||
|
|
7ec147603f | ||
|
|
8ee9e5915a | ||
|
|
cd5b786704 | ||
|
|
d715bb760c | ||
|
|
63918b44a8 | ||
|
|
64d09c9bca |
@@ -6,7 +6,7 @@ description: Use when writing, modifying, reviewing or debugging any OrcaSlicer
|
||||
# OrcaSlicer wxWidgets GUI
|
||||
|
||||
This skill is how OrcaSlicer's wxWidgets GUI is written, changed, fixed and reviewed. Its core is
|
||||
**wxWidgets 3.3.2 API usage** — the documented contracts, the per-platform behaviour and the known
|
||||
**wxWidgets 3.3.4 API usage** — the documented contracts, the per-platform behaviour and the known
|
||||
limitations of the wx version Orca pins — layered with the OrcaSlicer conventions, wrappers, custom
|
||||
widget library and stable component designs a contributor must follow. Every reference file opens
|
||||
with a numbered **Rules** checklist (what a diff is checked against), followed by sections that give
|
||||
@@ -15,9 +15,12 @@ wrong → right pairs with the commit that fixed each one.
|
||||
|
||||
## Ground truth: the wx tree in deps/
|
||||
|
||||
Orca pins **wxWidgets 3.3.2** from the fork `github.com/SoftFever/Orca-deps-wxWidgets` (tag `v3.3.2`,
|
||||
`deps/wxWidgets/wxWidgets.cmake`), built static (Flatpak: shared). Facts about this build that change
|
||||
how you read the wx docs:
|
||||
Orca pins upstream **wxWidgets 3.3.4** (`github.com/wxWidgets/wxWidgets`, tag `v3.3.4`,
|
||||
`deps/wxWidgets/wxWidgets.cmake`), built static (Flatpak: shared). Two in-tree patches are applied: an
|
||||
Apple-only sRGB colour-component fix (`0001-macos-use-srgb-colour-components.patch`) and a Windows-only
|
||||
clang-cl sibling-compiler search fix for the installed `wxWidgetsConfig.cmake`
|
||||
(`0002-clang-cl-sibling-compiler-prefix.patch`); neither applies on Linux. Facts about this build that
|
||||
change how you read the wx docs:
|
||||
|
||||
- **Linux builds against GTK3** (`DEP_WX_GTK3` defaults ON in `deps/CMakeLists.txt`). Target GTK3 on
|
||||
both X11 and Wayland; GTK-guarded code must still compile on GTK2, an opt-out build Orca does not ship.
|
||||
@@ -33,7 +36,7 @@ Look things up in the source the app is built from — it beats memory, and 3.3
|
||||
WX=$(find -L deps -maxdepth 5 -type d -path '*dep_wxWidgets-prefix/src/dep_wxWidgets' 2>/dev/null | head -1)
|
||||
# macOS: deps/build/<arch>/dep_wxWidgets-prefix/src/dep_wxWidgets Linux, Windows: deps/<tree>/dep_wxWidgets-prefix/...
|
||||
# -L follows a worktree's deps/<tree> symlinked to the main checkout. Not a glob: zsh aborts on one that matches nothing.
|
||||
# If deps are not built: git clone --depth 1 -b v3.3.2 https://github.com/SoftFever/Orca-deps-wxWidgets
|
||||
# If deps are not built: git clone --depth 1 -b v3.3.4 https://github.com/wxWidgets/wxWidgets
|
||||
grep -n "CaptureMouse" -A 30 $WX/interface/wx/window.h # documented contract (doxygen source)
|
||||
grep -rn "@onlyfor\|not implemented" $WX/interface/wx/popupwin.h # documented platform limits
|
||||
ls $WX/docs/doxygen/overviews/ # eventhandling.h, sizer.h, high_dpi.md, windowdeletion.h, ...
|
||||
@@ -219,14 +222,15 @@ known class with a pitfall entry and a fixing commit.
|
||||
any wx key event; Control+click arrives as a right-click.
|
||||
- **Windows:** `IsDark()` and `wxSYS_COLOUR_*` follow the system app mode, not Orca's theme — use
|
||||
`dark_mode()`; menu bitmaps follow `check_dark_mode()`; windows are not double-buffered by default in
|
||||
3.3.2; `ProcessLeftDown` is never called for popups; a popup that must close with the frame calls
|
||||
3.3.4; `ProcessLeftDown` is never called for popups; a popup that must close with the frame calls
|
||||
`BindUnfocusEvent()`.
|
||||
- **Linux GTK3:** dialogs without size hints collapse (only sizer-fitting calls, not `Fit()`, are
|
||||
replayed at the first `Show()`); command events from a popup's children are not stopped at the popup
|
||||
(MSW/macOS stop them); chained popups need `transient_for` set to the mapped parent right before
|
||||
showing; native borders leak through custom widgets (`RemoveButtonBorder`/`RemoveInputBorder`).
|
||||
- **Wayland:** no global pointer position, no window positioning, `wxClientDC`, `Update()` and `SetIcon`
|
||||
do nothing, no floating AUI panes, GL is EGL only.
|
||||
do nothing, AUI floating is disabled (wx 3.3.4 can drag a floating frame via system drag sessions, but
|
||||
its docking hints still need global positions), GL is EGL only.
|
||||
|
||||
## Editing this skill
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ Contents: [Rules](#rules) · [wxColour](#wxcolour) · [System colours and appear
|
||||
|
||||
**Contract.** Constructors: `()`, `(r, g, b, a = wxALPHA_OPAQUE)`, `(unsigned long|long|int|unsigned int)` ("A
|
||||
packed RGB value", `interface/wx/colour.h:98-101`), `(const wxString&|const char*|const wchar_t*)`;
|
||||
`wxColour(bool) = delete` (`include/wx/colour.h:225-240`; `docs/changes.txt:246-248`: code "unintentionally
|
||||
`wxColour(bool) = delete` (`include/wx/colour.h:225-240`; `docs/changes.txt:278-280`: code "unintentionally
|
||||
and mistakenly using wxColour ctor from bool … doesn't compile any longer").
|
||||
|
||||
| Fact | Cite |
|
||||
@@ -121,7 +121,7 @@ returned colour is always valid" (`interface/wx/settings.h:44-48`, `:398-407`).
|
||||
|
||||
| Method | Contract |
|
||||
|---|---|
|
||||
| `IsDark()` | "checks the appearance of the current application and not the other applications on the system, so under MSW … will return false even if dark mode is used system-wide unless the application opted in using dark mode using wxApp::MSWEnableDarkMode()" (`:332-346`). An incompatible 3.3 change (`docs/changes.txt:71-73`). |
|
||||
| `IsDark()` | "checks the appearance of the current application and not the other applications on the system, so under MSW … will return false even if dark mode is used system-wide unless the application opted in using dark mode using wxApp::MSWEnableDarkMode()" (`:332-346`). An incompatible 3.3 change (`docs/changes.txt:77-79`). |
|
||||
| `AreAppsDark()` (3.3.0) | system-wide app dark mode "even if it's not enabled for this particular application"; same as `IsDark()` off MSW (`:308-321`). |
|
||||
| `IsSystemDark()` (3.3.0) | the "Windows mode", which can differ from the "app mode" (`:348-358`). |
|
||||
| `IsUsingDarkBackground()` | luminance fallback, "generally not very useful to call directly" (`:360-370`). |
|
||||
@@ -233,25 +233,25 @@ child handlers.
|
||||
`@onlyfor{wxmsw}`, `interface/wx/app.h:1418-1465`):
|
||||
- "experimental"; uses "undocumented, and unsupported by Microsoft, functions"; works on Windows 10 later than
|
||||
v1809 (including LTSC 2019) and all Windows 11; testing before 20H1 (v2004) "has been limited".
|
||||
- Flags: default follows the system ("dark mode is only used if it is the default mode for the applications on
|
||||
the current system"); `DarkMode_Always` forces dark. **[source]** `DarkMode_Auto = 0` exists in
|
||||
`include/wx/msw/app.h:48` although only `DarkMode_Always` is documented.
|
||||
- Flags: `DarkMode_Auto` (default) follows the system ("dark mode is only used if it is the default mode
|
||||
for the applications on the current system"); `DarkMode_Always` forces dark, `DarkMode_Never` forces
|
||||
light. **[source]** the enum also names `DarkMode_Auto = 0` in `include/wx/msw/app.h:46-52`;
|
||||
`DarkMode_Never` is new in 3.3.4 (documented at `interface/wx/app.h:1450-1454`).
|
||||
- Returns `true` if enabled, `false` "most likely because the system doesn't support dark mode".
|
||||
- Alternatives: the `msw.dark-mode` system option (1 = `MSWEnableDarkMode()`, 2 = `DarkMode_Always`, settable by
|
||||
environment variable from outside the app, `interface/wx/sysopt.h:85-89`), or `SetAppearance(System|Dark)`.
|
||||
- Known limitations (`interface/wx/app.h:1434-1448`): anything `TaskDialog()`-based has no dark mode —
|
||||
`wxMessageBox()`, `wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`, simple `wxAboutBox()` (wx suggests
|
||||
`wxGenericMessageDialog`/`wxGenericProgressDialog`); common-dialog wrappers `wxColourDialog`, `wxFindReplaceDialog`,
|
||||
`wxFontDialog`, `wxPageSetupDialog`, `wxPrintDialog`; `wxTimePickerCtrl`, `wxDatePickerCtrl`, `wxCalendarCtrl`
|
||||
stay light; toolbar items with `wxToolBar::SetDropdownMenu()` draw the drop-down "almost invisible".
|
||||
environment variable from outside the app, `interface/wx/sysopt.h:85-89`), or `SetAppearance(System|Light|Dark)`.
|
||||
- Known limitations (`interface/wx/app.h:1442-1448`): `wxTimePickerCtrl`, `wxDatePickerCtrl` and
|
||||
`wxCalendarCtrl` stay light; `wxPrintDialog` on Windows 10 stays light; MDI applications are not
|
||||
recommended in dark mode. `wxMessageDialog` gained dark mode in 3.3.3 (#26570) and the common dialogs
|
||||
in 3.3.4 (#26780), so the older "anything `TaskDialog()`-based and the common dialogs stay light" note
|
||||
no longer applies.
|
||||
|
||||
`AppearanceResult wxApp::SetAppearance(Appearance::System|Light|Dark)` (3.3.0, `interface/wx/app.h:1152-1190`):
|
||||
`AppearanceResult wxApp::SetAppearance(Appearance::System|Light|Dark)` (3.3.0, `interface/wx/app.h:1130-1187`):
|
||||
GTK/macOS follow the system by default and the call is immediate and "affects all the existing windows as well
|
||||
as any windows created after this call"; "Under MSW, the default appearance is always light" and an app that
|
||||
wants to follow the system must call it with `Appearance::System`; "the appearance can be only set before any
|
||||
windows are created and calling this function too late will return AppearanceResult::CannotChange" (only wxMSW
|
||||
returns it);
|
||||
`Failure` e.g. "because `GTK_THEME` is defined".
|
||||
wants to follow the system must call it with `Appearance::System`; on MSW it maps to `MSWEnableDarkMode()` and
|
||||
returns `Ok`/`Failure` (`interface/wx/app.h:1166-1169`). `Failure` e.g. "because `GTK_THEME` is defined";
|
||||
`AppearanceResult::CannotChange` is "currently never returned" (`interface/wx/app.h:1151, 1179-1183`).
|
||||
|
||||
`wxDarkModeSettings` (`interface/wx/msw/darkmode.h:30-111`), passed to `MSWEnableDarkMode()`: `GetColour(wxSystemColour)`
|
||||
(defaults "not documented and are subject to change"; the doc example names `0x202020` as the default background);
|
||||
@@ -260,34 +260,40 @@ returns it);
|
||||
which "doesn't look very well in dark mode"; the base returns grey.
|
||||
|
||||
**[source] facts the docs do not state:**
|
||||
- `SetAppearance` on MSW returns `CannotChange` when any TLW exists **or `MSWEnableDarkMode` was already called**
|
||||
(`gs_appMode != AppMode_Default`); `SetAppearance(Light)` returns `Ok` without doing anything
|
||||
(`src/msw/darkmode.cpp` `wxApp::SetAppearance`). macOS `System` sets `NSApp.appearance` to
|
||||
`[NSAppearance currentAppearance]` rather than nil, pinning the current look (`src/osx/cocoa/utils.mm:485-513`);
|
||||
GTK3 maps to the portal colour-scheme machinery; GTK2 always returns `Failure` (`src/gtk/app.cpp:355-381`).
|
||||
- `MSWEnableDarkMode` may be called any time, but dark title bars are applied only to TLWs **created** afterwards
|
||||
- As of 3.3.3 (#26516) and 3.3.4 (#26734), MSW dark mode can be switched at runtime: `SetAppearance()` maps to
|
||||
`MSWEnableDarkMode()` and returns `Ok`/`Failure`, never `CannotChange` (`src/msw/darkmode.cpp:354-375`).
|
||||
`MSWEnableDarkMode()` re-applies the mode to an existing window by sending it `WM_SYSCOLORCHANGE` (`:345-349`),
|
||||
and the window restyles through `wxMSWDarkMode::HasChanged()`/`NotifySysColorChange()`
|
||||
(`src/msw/window.cpp:5337, 5528-5534`), so a control created before the switch is re-themed too. macOS `System`
|
||||
sets `NSApp.appearance` to `[NSAppearance currentAppearance]` rather than nil, pinning the current look
|
||||
(`src/osx/cocoa/utils.mm:485-513`); GTK3 maps to the portal colour-scheme machinery; GTK2 always returns
|
||||
`Failure` (`src/gtk/app.cpp:355-381`).
|
||||
- `MSWEnableDarkMode` may be called any time; dark title bars are applied when a TLW is created
|
||||
(`EnableForTLW` at the end of TLW creation, `src/msw/toplevel.cpp:513`) and controls are dark-enabled at creation
|
||||
(`MSWCreateControl` → `AllowForWindow` and, for some controls, `SetForegroundColour(LISTBOXTEXT)`,
|
||||
`src/msw/control.cpp:133-140`). wx cannot flip existing windows — the reason `SetAppearance` refuses late calls.
|
||||
`src/msw/control.cpp:133-140`).
|
||||
- wx takes ownership of the settings pointer (`wxDarkModeModule::SetSettings`) — allocate it with `new`.
|
||||
- `msw.dark-mode` is read in `wxApp::Initialize` (`src/msw/app.cpp:492-494`): a user's `WX_MSW_DARK_MODE`
|
||||
environment variable enables wx dark mode before Orca's own call.
|
||||
- wx's owner-drawn menu path keys on `wxMSWDarkMode::IsActive()` (`src/msw/menuitem.cpp` `wxMenuItem::OnDrawItem`,
|
||||
`GetColourToUse`; `src/msw/menu.cpp`; menu-bar UAH drawing in `src/msw/darkmode.cpp`).
|
||||
|
||||
3.3.x dark-mode fix log: 3.3.2 wxMSW (`docs/changes.txt:297-308`: checkbox accessibility in dark mode, rendering of
|
||||
several controls, toolbar, menus; also "Revert use of WS_EX_COMPOSITED"), 3.3.1 (`:358-372`: wxStaticBitmap-in-notebook
|
||||
crash, disabled wxButton bitmaps and wxStaticText, notebook high-contrast background, wxDataViewCtrl light-mode
|
||||
border regression, selected toolbar buttons, wxComboCtrl, wxTE_RICH wxTextCtrl), 3.3.0 (`:385` "Add experimental dark
|
||||
mode support to wxMSW"); XRC dark colour variants (`:494`).
|
||||
3.3.x dark-mode fix log: 3.3.4 wxMSW (`docs/changes.txt:349-358`: dynamic dark mode, dark mode for
|
||||
wxFontPickerCtrl, wxNotebook, wxSpinButton and the common dialogs), 3.3.3 (`:433` "Implement support for
|
||||
switching between light/dark modes"; `:426` wxMessageDialog, `:429` combo/listbox on Windows 11, `:431`
|
||||
wxCheckBox label in screen readers), 3.3.2 (`:492-501`: checkbox accessibility in dark mode, rendering of
|
||||
several controls, toolbar, menus; also "Revert use of WS_EX_COMPOSITED"), 3.3.1 (`:553-565`:
|
||||
wxStaticBitmap-in-notebook crash, disabled wxButton bitmaps and wxStaticText, notebook high-contrast
|
||||
background, wxDataViewCtrl light-mode border regression, selected toolbar buttons, wxComboCtrl, wxTE_RICH
|
||||
wxTextCtrl), 3.3.0 (`:578` "Add experimental dark mode support to wxMSW"); XRC dark colour variants (`:687`).
|
||||
|
||||
**OrcaSlicer.** `GUI_App::on_init_inner` (`#ifdef __WINDOWS__`) calls `MSWEnableDarkMode(DarkMode_Auto)` and then
|
||||
`NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled)`. wx's call exists only so that wx-drawn
|
||||
menus get dark borders; NppDarkMode does the theming (title bars, explorer theme, scrollbars, list headers) because
|
||||
it can switch live and wx cannot. The code comment "Orca: todo switch to native dark mode support in wxWidgets and
|
||||
remove NppDarkMode" records the intent; the blocker is that a live Preferences toggle would become restart-only
|
||||
(`SetAppearance` returns `CannotChange` after startup, existing windows cannot be restyled) and TaskDialog/common
|
||||
dialogs/pickers stay light anyway — which is also why Orca has its own `MsgDialog` family and `ProgressDialog`.
|
||||
`NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled)`. wx's call exists so that wx-drawn
|
||||
menus get dark borders; NppDarkMode does Orca's theming (title bars, explorer theme, scrollbars, list headers).
|
||||
The code comment "Orca: todo switch to native dark mode support in wxWidgets and remove NppDarkMode" records the
|
||||
intent. The old blocker — a live Preferences toggle would be restart-only because `SetAppearance` returned
|
||||
`CannotChange` and existing windows could not be restyled — is gone as of 3.3.3/3.3.4 (above). Orca still keeps
|
||||
NppDarkMode, and Orca's own `MsgDialog` family and `ProgressDialog` remain its message/progress UI.
|
||||
**[source]** consequences of `DarkMode_Auto`: wx's internal "dark" stays `AllowDark` and follows the **system app
|
||||
mode**; NppDarkMode's later `SetPreferredAppMode` call does not touch wx's `gs_appMode`. So with Windows light +
|
||||
Orca dark, wx's dark machinery (menus, `GetColour()`, `IsDark()`) stays off; with Windows dark + Orca light it is
|
||||
@@ -312,11 +318,15 @@ on: `GetColour()` returns the dark palette, new native controls are dark-enabled
|
||||
```
|
||||
Cite: bf397a0632 (`GUI_App.cpp`, `GUI_App::on_init_inner`).
|
||||
- **Rule:** Do not call `wxTheApp->SetAppearance(...)` in Orca.
|
||||
**Why:** MSW returns `CannotChange` (Orca already called `MSWEnableDarkMode`), GTK2 fails, and macOS pins
|
||||
**Why:** MSW would switch wx's own mode out of step with NppDarkMode and `dark_color_mode` (wx's mode is driven
|
||||
by `MSWEnableDarkMode(DarkMode_Auto)` and follows the system), GTK2 fails, and macOS pins
|
||||
`NSApp.appearance` while `GUI_App::dark_mode()` keeps reading the system `AppleInterfaceStyle` — the two would
|
||||
disagree.
|
||||
- **Rule:** Do not show wx's TaskDialog-based or common dialogs where dark mode matters; use `MessageDialog` and
|
||||
friends (`MsgDialog.hpp`, see `references/windows-dialogs.md`).
|
||||
- **Rule:** Do not show wx's TaskDialog-based or common dialogs; use `MessageDialog` and friends
|
||||
(`MsgDialog.hpp`, see `references/windows-dialogs.md`).
|
||||
**Why:** Orca's dialogs are owner-drawn and consistent with the rest of the UI. The old dark-mode gap
|
||||
closed — `wxMessageDialog` gained dark mode in 3.3.3 (#26570) and the common dialogs in 3.3.4 (#26780) —
|
||||
but the convention stands.
|
||||
|
||||
## Window colours, inheritance and native-control limits
|
||||
|
||||
@@ -371,7 +381,7 @@ macOS paints the system grey.
|
||||
|
||||
| Port | Behaviour |
|
||||
|---|---|
|
||||
| MSW | `wxButton`/`wxToggleButton` `SetBackgroundColour`/`SetForegroundColour` switch the native button to `BS_OWNERDRAW` (`src/msw/anybutton.cpp` `wxAnyButton::MakeOwnerDrawn`, `:1324-1390`) — the colour works but native theming is gone. `wxCheckBox`/`wxRadioButton` foreground makes them owner-drawn when themes are active (`src/msw/control.cpp` `MSWMakeOwnerDrawnIfNecessary`); 3.3.2 fixed checkbox accessibility in that mode (`docs/changes.txt:299-300`). Static-text-like children paint the ancestor brush only if that ancestor's background is inheritable. |
|
||||
| MSW | `wxButton`/`wxToggleButton` `SetBackgroundColour`/`SetForegroundColour` switch the native button to `BS_OWNERDRAW` (`src/msw/anybutton.cpp` `wxAnyButton::MakeOwnerDrawn`, `:1324-1390`) — the colour works but native theming is gone. `wxCheckBox`/`wxRadioButton` foreground makes them owner-drawn when themes are active (`src/msw/control.cpp` `MSWMakeOwnerDrawnIfNecessary`); 3.3.2 fixed checkbox accessibility in that mode (`docs/changes.txt:492-493`). Static-text-like children paint the ancestor brush only if that ancestor's background is inheritable. |
|
||||
| macOS | `SetBackgroundColour` reaches the NSView only if it `respondsToSelector:setBackgroundColor:` and the style is not `wxBG_STYLE_TRANSPARENT` (`src/osx/cocoa/window.mm:3514-3531`): **NSButton (`wxButton`) ignores the background colour**. Foreground uses `setTextColor:` when the view has it (`:3885-3887`); stock NSButton has none. `wxStaticText` is an NSTextField with `setDrawsBackground:NO` — its background is never painted (`src/osx/cocoa/stattext.mm:154`). `wxTextCtrl`'s `setEnabled:` resets the text colour: multi-line (`wxNSTextView`) always, to `controlTextColor`/`disabledControlTextColor`; single-line (`wxNSTextField`) when it does not draw its background, to `controlTextColor`/`secondarySelectedControlColor` (`src/osx/cocoa/textctrl.mm`). |
|
||||
| GTK3 | `SetBackgroundColour/SetForegroundColour/SetFont` install a per-widget CSS provider `*{color:..;background:..;font:..}` at `GTK_STYLE_PROVIDER_PRIORITY_APPLICATION` (`src/gtk/window.cpp` `wxWindowGTK::GTKApplyStyle`); `wxButton`/`wxCheckBox` apply it to their inner label too (`src/gtk/button.cpp:325-335`, `src/gtk/checkbox.cpp:233-237`). User CSS (priority USER) can still override. |
|
||||
| GTK2 | colours applied with `gtk_widget_modify_style` — pixmap-engine themes may ignore them. |
|
||||
|
||||
@@ -106,7 +106,7 @@ The general wx rule is that setters do not send events. The exceptions are the b
|
||||
| `wxTextEntry::SetValue(s)` | **yes**, one `wxEVT_TEXT`, even when `s` equals the current text | `interface/wx/textentry.h:539-542`; [source] `src/common/textentrycmn.cpp:236-254`, `src/msw/textctrl.cpp:1133-1145` |
|
||||
| `wxTextEntry::ChangeValue(s)` | no | `interface/wx/textentry.h:177-178` |
|
||||
| `wxTextEntry::Clear()` | yes (= `SetValue("")`) | `interface/wx/textentry.h:193-194` |
|
||||
| `wxTextCtrl::SetLabel/SetLabelText` | nothing at all (3.3) | `docs/changes.txt:111-113`; `src/common/textcmn.cpp:934-937` |
|
||||
| `wxTextCtrl::SetLabel/SetLabelText` | nothing at all (3.3) | `docs/changes.txt:117-119`; `src/common/textcmn.cpp:934-937` |
|
||||
| `SetSelection/SetStringSelection` on wxChoice, wxComboBox, wxListBox, wxRadioBox | no | `interface/wx/ctrlsub.h:102-103,126` |
|
||||
| `wxComboBox::SetValue` | `wxEVT_TEXT` if editable; none with `wxCB_READONLY` | `interface/wx/combobox.h:256-272` |
|
||||
| `wxComboBox::Popup()/Dismiss()` | DROPDOWN/CLOSEUP, except on wxOSX | `interface/wx/combobox.h:279-281,292-294` |
|
||||
@@ -184,7 +184,7 @@ Pitfalls:
|
||||
ctrl->GetTextCtrl()->SetLabel(s); // Wrong: no-op
|
||||
ctrl->GetTextCtrl()->ChangeValue(s); // Right (or SetValue if listeners must react)
|
||||
```
|
||||
Cite: `docs/changes.txt:111-113`.
|
||||
Cite: `docs/changes.txt:117-119`.
|
||||
- **Rule:** Handle `wxEVT_TEXT_ENTER` without `Skip()` unless you want the default button activated as well.
|
||||
**Why:** a skipped Enter falls through to the dialog's default button and closes it.
|
||||
```cpp
|
||||
@@ -213,7 +213,7 @@ Contract:
|
||||
verbatim, and `wxControl::EscapeMnemonics()` escapes it (`interface/wx/control.h:174-195, 379-387`). This applies
|
||||
to `wxStaticText`, `wxCheckBox`, `wxRadioButton`, `wxButton` labels and to book page titles: all `wx*book`
|
||||
classes interpret mnemonics in page text (`interface/wx/bookctrl.h:141-147`), and since 3.3 wxListbook and
|
||||
wxChoicebook do too (`docs/changes.txt:128-130`).
|
||||
wxChoicebook do too (`docs/changes.txt:134-136`).
|
||||
- `SetLabelMarkup()` needs well-formed markup or the label "won't be shown at all" (returns false, keeps the old
|
||||
label). A bare `&` is still a mnemonic. Multi-line markup works only on GTK and macOS; the generic version used on
|
||||
MSW handles single lines (`interface/wx/control.h:338-347`). Quote untrusted text with
|
||||
@@ -383,10 +383,10 @@ Pitfalls:
|
||||
|
||||
- Virtual list (`wxLC_REPORT|wxLC_VIRTUAL`): call `SetItemCount()` and override `OnGetItemText` (optionally
|
||||
`OnGetItemImage`/`OnGetItemAttr`) (`interface/wx/listctrl.h:128-134`). `EditLabel()` asserts without
|
||||
`wxLC_EDIT_LABELS` (`docs/changes.txt:68-69`).
|
||||
`wxLC_EDIT_LABELS` (`docs/changes.txt:74-75`).
|
||||
- Images: prefer `SetImages(std::vector<wxBitmapBundle>)`; `wxImageList` is discouraged
|
||||
(`interface/wx/withimages.h:21-40`) and is measured in physical pixels in 3.3 (`docs/changes.txt:85-88`); calling
|
||||
its methods on an invalid (unsized) list now asserts, i.e. fails silently in Orca (`docs/changes.txt:53-56`).
|
||||
(`interface/wx/withimages.h:21-40`) and is measured in physical pixels in 3.3 (`docs/changes.txt:91-94`); calling
|
||||
its methods on an invalid (unsized) list now asserts, i.e. fails silently in Orca (`docs/changes.txt:59-62`).
|
||||
`Assign*` transfers ownership, `Set*ImageList` does not (`interface/wx/withimages.h:90-110`). Sizing:
|
||||
`references/dpi-bitmaps-fonts.md`.
|
||||
- `wxTreeCtrl`: `SelectItem` emits events ([table](#events-from-programmatic-changes)).
|
||||
@@ -402,7 +402,7 @@ Contract:
|
||||
selection's blocks).
|
||||
- `FreezeTo(row, col)` returns false (an assert, silent in Orca) for out-of-range values, merged cells or the native
|
||||
header (`interface/wx/grid.h:5747-5772`); [source] also when rows/columns were reordered or drag-moving is enabled
|
||||
(`src/generic/grid.cpp:5742-5750`). In 3.3 it freezes even when the grid is too small (`docs/changes.txt:48-51`).
|
||||
(`src/generic/grid.cpp:5742-5750`). In 3.3 it freezes even when the grid is too small (`docs/changes.txt:54-57`).
|
||||
- Editor contract: `EndEdit` must not modify the grid — it stores the value and returns true if it changed;
|
||||
`ApplyEdit` writes it after `wxEVT_GRID_CELL_CHANGING` was not vetoed (`interface/wx/grid.h:610-638`). Editors,
|
||||
renderers and attrs are ref-counted and the setters take ownership (`:1263-1305, 1739-1770, 2681-2701`).
|
||||
@@ -492,7 +492,7 @@ All cites `interface/wx/dataview.h`. MSW uses the generic implementation; wxGTK
|
||||
Other per-port facts: editing starts on a slow double-click or a platform key — "F2 is typical on Windows, Space
|
||||
and/or Enter is common elsewhere" (2604-2607, 1915-1918); a custom renderer's `StartDrag()` is "Not yet supported"
|
||||
(2717-2719); `RenderText()` should be used inside `Render()` so text matches native renderers (2708-2714). Calling
|
||||
`Collapse()` from an event handler was fixed in 3.3.1 (`docs/changes.txt:346`; the generic re-check is described
|
||||
`Collapse()` from an event handler was fixed in 3.3.1 (`docs/changes.txt:539`; the generic re-check is described
|
||||
under [DVC control API](#wxdataviewctrl-control-api)).
|
||||
|
||||
OrcaSlicer: `ParamsViewCtrl` (`EditGCodeDialog`) and `DiffViewCtrl` (`UnsavedChangesDialog`) use
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# DPI, bitmaps and fonts
|
||||
|
||||
How wx 3.3.2 maps DIP, logical and physical pixels on each platform, how DPI changes reach a window,
|
||||
How wx 3.3.4 maps DIP, logical and physical pixels on each platform, how DPI changes reach a window,
|
||||
and how OrcaSlicer sizes layout (`FromDIP`, `em_unit`), rescales (`DPIAware`), rasterizes icons
|
||||
(`BitmapCache`, `create_scaled_bitmap`, `ScalableBitmap`) and chooses fonts (`Label` table). Read it
|
||||
for any fixed size, icon, bitmap, image list, font, or `on_dpi_changed` work, and when a bug looks
|
||||
@@ -488,7 +488,7 @@ handler bound there runs once more after every DPI change.
|
||||
inherits the DC's scale (`interface/wx/bitmap.h:370-385`).
|
||||
- `wxBitmap(const wxCursor&)` is invalid on GTK under Wayland (`interface/wx/bitmap.h:388-401`).
|
||||
- wxMSW `wxBitmap::Create(size, dc)` no longer multiplies by the DC's content scale
|
||||
(`docs/changes.txt:94-96`).
|
||||
(`docs/changes.txt:100-102`).
|
||||
|
||||
**Offscreen drawing.** "The scaling factor of the bitmap determines the scaling factor used by
|
||||
this device context" (`interface/wx/dcmemory.h:41-58`); `wxMemoryDC(wxDC*)` does **not** inherit
|
||||
@@ -740,7 +740,7 @@ are in `references/popups-menus.md`.
|
||||
in the new code as it doesn't support showing DPI-dependent bitmaps. Please use
|
||||
wxWithImages::SetImages() instead"; "the size is specified in physical pixels and must correspond
|
||||
to the size of bitmaps … that will be added". 3.3 made the size physical and makes calls on an
|
||||
invalid list assert (`docs/changes.txt:53-56, 85-88`) — silently in Orca's assert-free build.
|
||||
invalid list assert (`docs/changes.txt:59-62, 91-94`) — silently in Orca's assert-free build.
|
||||
When a list is unavoidable, `wxBitmapBundle::CreateImageList(win, bundles)` builds one at the
|
||||
consensus size (public but undocumented, [source] `include/wx/bmpbndl.h`).
|
||||
```cpp
|
||||
@@ -761,7 +761,7 @@ wxArtProvider::GetBitmapBundle(wxART_WARNING, wxART_OTHER, wxSize(16, 16));
|
||||
```
|
||||
|
||||
**`wxImage`** resizing (`interface/wx/image.h:28-89`): `wxIMAGE_QUALITY_NEAREST` is no longer an
|
||||
alias of `NORMAL` since 3.3.0 (`docs/changes.txt:98-99`; `wxIMAGE_QUALITY_FAST` is the speed
|
||||
alias of `NORMAL` since 3.3.0 (`docs/changes.txt:104-105`; `wxIMAGE_QUALITY_FAST` is the speed
|
||||
synonym). `NORMAL` (default) = bilinear down to an integer multiple, then box average; `HIGH` =
|
||||
box average when shrinking, bicubic when enlarging; `BILINEAR`, `BICUBIC`, `BOX_AVERAGE` explicit.
|
||||
High-quality scaling "may not work as expected when using a single mask colour for
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Events: binding, dispatch, posting and deferred calls
|
||||
|
||||
How wx 3.3.2 finds, runs, propagates, queues and drops event handlers, and how OrcaSlicer code
|
||||
How wx 3.3.4 finds, runs, propagates, queues and drops event handlers, and how OrcaSlicer code
|
||||
binds, emits and defers. Read it before writing any `Bind`/`Unbind`, `Skip()`, `ProcessEvent`,
|
||||
`wxPostEvent`/`wxQueueEvent` or `CallAfter`, before defining a custom event, and when debugging a
|
||||
handler that never runs, runs twice, runs on a dead object, or swallows a widget's own behaviour.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Mouse, keyboard and focus
|
||||
|
||||
How input reaches wx windows in the wxWidgets 3.3.2 build Orca ships, and the Orca conventions on
|
||||
How input reaches wx windows in the wxWidgets 3.3.4 build Orca ships, and the Orca conventions on
|
||||
top: mouse capture, mouse and key events, accelerators and Orca's shortcut registry, focus,
|
||||
tooltips and cursors. Read it when a widget captures the mouse or tracks hover, when adding or
|
||||
changing a keyboard shortcut, when touching focus, tooltip or cursor code, and when debugging an
|
||||
@@ -297,7 +297,7 @@ Per port [source]:
|
||||
non-enter event while the cached position is invalid is treated as the enter.
|
||||
- **GTK:** crossing events with a grab/ungrab mode are ignored; outside capture wx re-derives the
|
||||
window under the pointer on each motion (`src/gtk/window.cpp:2073-2117, 2384-2456`; fixes #24339
|
||||
and #24931–#24933 are in this release, `docs/changes.txt:537, 547`).
|
||||
and #24931–#24933 are in this release, `docs/changes.txt:730, 740`).
|
||||
- **macOS:** each view's `NSTrackingArea` uses `NSTrackingInVisibleRect`
|
||||
(`src/osx/cocoa/window.mm:3924`) and covers its children, so do not rely on the parent getting
|
||||
LEAVE when the pointer moves onto a child. `NSMouseMoved` is delivered only to the deepest view
|
||||
@@ -334,7 +334,7 @@ A composite's hover state must therefore track its children. Orca's `StateHandle
|
||||
`CS_DBLCLKS`, `src/msw/app.cpp:584`). GTK drops the surplus press before `GDK_2BUTTON_PRESS`
|
||||
(`src/gtk/window.cpp:1798-1817`), and GTK2 also suppresses triple clicks (`:1818-1829`). On wxOSX the
|
||||
third press of a triple click is a DOWN again, as on MSW (`src/osx/cocoa/window.mm:4105-4140`;
|
||||
#25886, `docs/changes.txt:316`). `GetClickCount()` is "implemented only in wxMac and returns -1
|
||||
#25886, `docs/changes.txt:509`). `GetClickCount()` is "implemented only in wxMac and returns -1
|
||||
for the other platforms" (`interface/wx/event.h:2965-2974`).
|
||||
- **Context menu:** "under MSW the context menu event is generated after EVT_RIGHT_UP … but under
|
||||
GTK … after EVT_RIGHT_DOWN", so a window handling `wxEVT_CONTEXT_MENU` must not handle (or must
|
||||
@@ -398,7 +398,7 @@ A diagonal trackpad scroll on macOS sends two events, vertical first, then one w
|
||||
| `ClientToScreen()`, `ScreenToClient()`, `GetScreenRect()` | — | add the top-level window's `gdk_window_get_origin()` (`src/gtk/window.cpp:4630-4698`). Without a global origin the result is only meaningful relative to the same top-level window: fine for deltas and hit tests inside one window, wrong across windows or for absolute placement |
|
||||
| `wxFindWindowAtPoint(pt)` | deepest window at a screen point; disabled children count, hidden ones are skipped (`interface/wx/utils.h:385-394`) | built on screen rectangles, so unreliable. On GTK it is `wxGenericFindWindowAtPoint`, a walk over every top-level window and child (`src/gtk/utilsgtk.cpp:98-101`, `src/common/utilscmn.cpp:1294-1345`) |
|
||||
| `wxGetKeyState(key)` | "In wxGTK, this function can be only used with modifier keys … when not using X11 backend" (`interface/wx/utils.h:352-358`) | Ctrl/Alt/Shift and Caps/Num/Scroll Lock only; any other key returns false (`src/unix/utilsx11.cpp:2596-2662`) |
|
||||
| `WarpPointer()` | Apple's HIG forbids it; on Wayland it works only with a compositor implementing the pointer-warp protocol, and mutter also needs a pressed button (`interface/wx/window.h:3895-3914`; `docs/changes.txt:294`) | — |
|
||||
| `WarpPointer()` | Apple's HIG forbids it; on Wayland it works only with a compositor implementing the pointer-warp protocol, and mutter also needs a pressed button (`interface/wx/window.h:3895-3914`; `docs/changes.txt:487`) | — |
|
||||
| `wxUIActionSimulator` | "doesn't work when using Wayland" (`interface/wx/uiaction.h:20`) | — |
|
||||
| `PopupMenu(x, y)` | — | GTK ≥ 3.22 positions it relative to the window (`gtk_menu_popup_at_rect`, `src/gtk/window.cpp:6520-6565`), so it is safe |
|
||||
|
||||
@@ -540,7 +540,7 @@ The full Esc/close path is in `references/windows-dialogs.md`.
|
||||
layout"; specials are their `WXK_*` (`:1371-1394`). A Cyrillic `ц` gives `'W'`, so Ctrl+letter
|
||||
shortcuts work across layouts, but an AZERTY key reports its own label (`$` where US has `]`), so
|
||||
`Ctrl-;`-style punctuation accelerators may be untypeable on some layouts (`:1396-1407`). wxGTK
|
||||
got the non-Latin mapping in 3.3.0 (#23379, `docs/changes.txt:540`).
|
||||
got the non-Latin mapping in 3.3.0 (#23379, `docs/changes.txt:733`).
|
||||
- `wxEVT_CHAR` reflects Shift and the layout. Ctrl+letter gives 1..26 (`WXK_CONTROL_A` …,
|
||||
`:1409-1421`). Exception: on macOS Cmd+letter's CHAR is the letter itself (`'a'`/`'A'`); only the
|
||||
physical Control key yields 1..26 (`src/osx/cocoa/window.mm:304-307`).
|
||||
@@ -629,8 +629,14 @@ Space/Return holds the mouse capture until its KEY_UP reaches the button. On MSW
|
||||
|
||||
### Contract
|
||||
|
||||
- "An accelerator takes precedence over normal processing" (`interface/wx/accel.h:178`), but it
|
||||
runs after `wxEVT_CHAR_HOOK` on every port (table above).
|
||||
- "An accelerator takes precedence over normal processing" (`interface/wx/accel.h:178`). Since 3.3.4 this
|
||||
holds on every port (wxGTK used to let the focused window handle the key first), unless the focused
|
||||
window claims the key. The accelerator walk still runs after `wxEVT_CHAR_HOOK` (table above). The new
|
||||
`wxEVT_ACCELERATOR_KEY` event (`interface/wx/event.h:1740-1801`, `@since 3.3.4`) is sent to the focus
|
||||
window — and propagated to its parents — before an accelerator is used; it is sent after
|
||||
`wxEVT_CHAR_HOOK` on most ports and before it on macOS. Its handler can call `UseAccelerator()`, and a
|
||||
window that must keep the key overrides `wxWindow::ClaimsKeyBeforeAccelerator()`
|
||||
(`interface/wx/window.h:4554-4583`).
|
||||
- [source] On GTK and macOS a hit is sent as `wxEVT_MENU` with the entry's id and, if unprocessed,
|
||||
retried as `wxEVT_BUTTON`; macOS treats the key as consumed either way
|
||||
(`src/gtk/window.cpp:1340-1366`, `src/osx/window_osx.cpp:2563-2590`). On MSW the `WM_COMMAND` goes to
|
||||
@@ -654,11 +660,16 @@ Space/Return holds the mouse capture until its KEY_UP reaches the button. On MSW
|
||||
them in `wxMenuBar::RebuildAccelTable` (`src/msw/menu.cpp:1264-1292`); GTK adds the menu's accel
|
||||
group to the top-level window in `AttachToFrame` (`src/gtk/menu.cpp:239-247`). A menu shown with
|
||||
`PopupMenu` treats `"\tCtrl+X"` as display text.
|
||||
- **MSW:** accelerators are not translated while a `wxTextCtrl`/`wxComboBox`/`wxSpinCtrl` has focus and
|
||||
the key is a text-editing key: Ctrl+A/C/V/X/Ins/Del/Home/End/Left/Right, Shift+those navigation
|
||||
keys, bare Del/Home/End, Alt+Backspace (`src/msw/textentry.cpp:1073-1150`). Multi-line controls also
|
||||
keep Enter (`src/msw/textctrl.cpp:2110-2135`).
|
||||
- **GTK:** the accelerator walk has no such exemption (`src/gtk/window.cpp:1340-1366`). As menu
|
||||
- **Text-entry controls claim their editing keys on every port since 3.3.4.** A `wxTextCtrl`, a
|
||||
non-read-only `wxComboBox` or a `wxSpinCtrl` overrides `ClaimsKeyBeforeAccelerator()` to return
|
||||
`wxTextEntryBase::IsUsedForEditing()` (`src/common/textcmn.cpp:136-140`;
|
||||
`src/common/spinctrlcmn.cpp:160-167`; `src/msw/combobox.cpp:389-395`, `src/gtk/combobox.cpp:205-211`):
|
||||
Alt+Backspace; any printable key with no modifier or Shift (except Delete, so Esc/Enter/Tab stay
|
||||
usable); Backspace/Delete/Home/End with no modifier or Shift; Ctrl+A/C/V/X; and Insert/Delete/Home/
|
||||
End/Left/Right with Ctrl or Shift. A matching menu accelerator does not fire while such a control has
|
||||
focus. The set lives in `IsUsedForEditing` (`src/common/textentrycmn.cpp:441-509`).
|
||||
- **GTK:** the accelerator walk now consults `ClaimsKeyBeforeAccelerator()` too
|
||||
(`src/gtk/window.cpp:1524-1539`), so the text-control exemption above applies here since 3.3.4. As menu
|
||||
accelerators, Shift with non-alphabetic keys does not work, bare arrow keys do not work, and the
|
||||
listed keys (Tab, the modifiers, locks …) are unsupported (`interface/wx/menuitem.h:562-575`).
|
||||
- **macOS:** menu-bar items become `NSMenuItem` key equivalents
|
||||
|
||||
@@ -69,9 +69,12 @@ Contents: [The stack](#the-stack-orcas-gui-is-built-on) ·
|
||||
|
||||
## The stack Orca's GUI is built on
|
||||
|
||||
- **wxWidgets 3.3.2, SoftFever fork.** `deps/wxWidgets/wxWidgets.cmake` fetches
|
||||
`https://github.com/SoftFever/Orca-deps-wxWidgets` at tag `v3.3.2` and builds it static
|
||||
(`-DwxBUILD_SHARED=OFF`); Flatpak builds build it shared. Linux builds against **GTK3** by default
|
||||
- **wxWidgets 3.3.4, upstream.** `deps/wxWidgets/wxWidgets.cmake` fetches
|
||||
`https://github.com/wxWidgets/wxWidgets` at tag `v3.3.4` and builds it static
|
||||
(`-DwxBUILD_SHARED=OFF`); Flatpak builds build it shared. Two in-tree platform patches apply on
|
||||
Apple and Windows only (`0001-macos-use-srgb-colour-components.patch`,
|
||||
`0002-clang-cl-sibling-compiler-prefix.patch`) — `references/platforms.md`. Linux builds against
|
||||
**GTK3** by default
|
||||
(`option(DEP_WX_GTK3 "Build wxWidgets against GTK3" ON)` in `deps/CMakeLists.txt`, `SLIC3R_GTK`
|
||||
default `"3"`, Flatpak uses gtk3). GTK2 exists only as an opt-out (`-DDEP_WX_GTK3=OFF`) and loses
|
||||
EGL, WebKit2 and DIP pixels. Code guarded for GTK should still compile on GTK2, but GTK3 under X11
|
||||
@@ -85,11 +88,12 @@ Contents: [The stack](#the-stack-orcas-gui-is-built-on) ·
|
||||
- **Orca's own widget library.** New UI code largely does not use raw wx controls: the owner-drawn
|
||||
widgets in `src/slic3r/GUI/Widgets/` (`Button`, `CheckBox`, `ComboBox`, `TextInput`, `SpinInput`,
|
||||
`SwitchButton`, `RadioGroup`, `Label`, `DialogButtons`, …) replace them. Reasons: native controls
|
||||
cannot follow Orca's look or its app-level dark-mode toggle; on Windows wx's native dark mode does
|
||||
not reach anything built on `TaskDialog()` (`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`,
|
||||
`wxProgressDialog`) nor the wrapped common dialogs (`wxColourDialog`, `wxFontDialog`, …)
|
||||
(`interface/wx/app.h:1434-1443`), so Orca shows the `MsgDialog` family and its own generic
|
||||
`Widgets/ProgressDialog` instead; and on GTK the theme's borders bleed through wrapped native
|
||||
cannot follow Orca's look or its app-level dark-mode toggle; on Windows wx's native dark mode reaches
|
||||
the `TaskDialog()`-based boxes (`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`,
|
||||
`wxProgressDialog`) since 3.3.3 and the wrapped common dialogs (`wxColourDialog`, `wxFontDialog`, …)
|
||||
since 3.3.4, but the date/time/calendar controls, `wxPrintDialog` on Windows 10 and MDI applications
|
||||
stay light (`interface/wx/app.h:1442-1448`), so Orca shows the `MsgDialog` family and its own generic
|
||||
`Widgets/ProgressDialog` for a consistent look; and on GTK the theme's borders bleed through wrapped native
|
||||
controls (the widgets call `RemoveButtonBorder` / `RemoveInputBorder` under `__WXGTK__`).
|
||||
Plain containers stay raw (`wxPanel`, `wxBoxSizer`, `wxScrolledWindow`).
|
||||
- **Namespaces.** Most widgets are in the global namespace; a few (`DialogButtons`, `HyperLink`,
|
||||
|
||||
@@ -67,9 +67,10 @@ Contents: [Rules](#rules) · [Why the library exists](#why-the-library-exists)
|
||||
Native controls cannot carry Orca's flat, rounded, palette-coloured look, and they cannot follow all of Orca's
|
||||
theming:
|
||||
- On Windows the theme is an app-level setting (Preferences "Enable dark Mode", Windows-only) layered on
|
||||
`MSWEnableDarkMode`, and wx's MSW dark mode does not reach `TaskDialog()`-based dialogs (`wxMessageBox`,
|
||||
`wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`), the common dialogs or the date/time pickers
|
||||
(`interface/wx/app.h:1436-1445`). Hence the `MsgDialog` family (`references/windows-dialogs.md`) and Orca's own
|
||||
`MSWEnableDarkMode`; wx's MSW dark mode now reaches the `TaskDialog()`-based dialogs (`wxMessageBox`,
|
||||
`wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`) since 3.3.3 and the common dialogs since 3.3.4,
|
||||
but the date/time pickers, `wxPrintDialog` on Windows 10 and MDI applications stay light
|
||||
(`interface/wx/app.h:1442-1448`). Hence the `MsgDialog` family (`references/windows-dialogs.md`) and Orca's own
|
||||
`ProgressDialog`.
|
||||
- On macOS and Linux Orca follows the system appearance; native controls are themed by the toolkit, but any
|
||||
light palette colour set on them still needs the `UpdateDarkUI` pass (`references/colours-dark-mode.md`).
|
||||
|
||||
@@ -6,7 +6,7 @@ to write a custom control on the wx side and how to author an Orca widget on the
|
||||
`StaticBox`/`StateHandler` foundation. Read it before writing or reviewing any `wxEVT_PAINT`
|
||||
handler, `render`/`doRender` method, `messureSize`, or a new class under `src/slic3r/GUI/Widgets/`.
|
||||
|
||||
wx cites are relative to the pinned wx 3.3.2 tree (located as in `SKILL.md` §Ground truth).
|
||||
wx cites are relative to the pinned wx 3.3.4 tree (located as in `SKILL.md` §Ground truth).
|
||||
Orca builds wx with `wxBUILD_DEBUG_LEVEL=0` and `libslic3r_gui` with `wxDEBUG_LEVEL=0`: every
|
||||
wx assert below is compiled out and `wxCHECK*` returns silently, so paint misuse shows up only as
|
||||
wrong, missing or stale pixels, never as an assert dialog.
|
||||
@@ -116,7 +116,7 @@ Bind(wxEVT_PAINT, [this](wxPaintEvent&) {
|
||||
|
||||
| Situation | MSW | macOS | GTK3 (X11 and Wayland) | GTK2 (opt-out build) |
|
||||
|---|---|---|---|---|
|
||||
| Handler creates no `wxPaintDC` | `wxWindowMSW::HandlePaint` sees no DC and lets `DefWindowProc` validate the region: no `WM_PAINT` storm in 3.3.2, but drawing is unclipped and the contract is broken (`src/msw/window.cpp` `HandlePaint`) | no error; the window shows only what the background step left (undetermined under `wxBG_STYLE_PAINT`) | same | same |
|
||||
| Handler creates no `wxPaintDC` | `wxWindowMSW::HandlePaint` sees no DC and lets `DefWindowProc` validate the region: no `WM_PAINT` storm in 3.3.4, but drawing is unclipped and the contract is broken (`src/msw/window.cpp` `HandlePaint`) | no error; the window shows only what the background step left (undetermined under `wxBG_STYLE_PAINT`) | same | same |
|
||||
| Handler creates a DC, then `Skip()`s | default `OnPaint` (native painting) runs as well | — | — | — |
|
||||
| `wxPaintDC` outside a paint event | `wxCHECK_RET(!paintStack.empty(), "wxPaintDC can't be created outside wxEVT_PAINT handler")` (also for a window other than the one being repainted): the DC gets no HDC and every draw call is a silent no-op (`src/msw/dcclient.cpp` `wxPaintDCImpl::wxPaintDCImpl`) | no visible effect | `wxCHECK_RET(cr, "using wxPaintDC without being in a native paint event")`, every draw call is a silent no-op (`src/gtk/dc.cpp:518`) | works (GDK) |
|
||||
| `wxClientDC` drawing | works on non-composited windows; the doc lists "wxMSW when using double buffering" (`WS_EX_COMPOSITED`, see below) as non-working (`interface/wx/dcclient.h:82-84`), yet `CanBeUsedForDrawing` returns `true` unconditionally (`include/wx/msw/dcclient.h:60`), so it cannot detect that case | never; `CanBeUsedForDrawing` is `false` (`include/wx/osx/dcclient.h:58`) | X11 works; Wayland has no effect, `CanBeUsedForDrawing` is `false` on `wxDisplayWayland` (`src/gtk/dc.cpp` `wxClientDCImpl::CanBeUsedForDrawing`) | works |
|
||||
@@ -283,8 +283,8 @@ void MyCard::OnPaint(wxPaintEvent&) {
|
||||
ancestor up to the TLW (`src/msw/window.cpp` `wxWindowMSW::IsDoubleBuffered`);
|
||||
`SetDoubleBuffered(on)` toggles that style; `MSWDisableComposited()` removes it up the chain.
|
||||
`WS_EX_COMPOSITED` makes the whole subtree paint bottom-up into one buffer.
|
||||
- wx 3.3.0 enabled double buffering for all MSW windows (#22851, `docs/changes.txt:557`) and 3.3.2
|
||||
reverted it (#25808, `docs/changes.txt:308`). In 3.3.2 nothing in wx sets `WS_EX_COMPOSITED`
|
||||
- wx 3.3.0 enabled double buffering for all MSW windows (#22851, `docs/changes.txt:750`) and 3.3.2
|
||||
reverted it (#25808, `docs/changes.txt:501`). In 3.3.4 nothing in wx sets `WS_EX_COMPOSITED`
|
||||
unless the app calls `SetDoubleBuffered(true)`: MSW windows are not double-buffered by default,
|
||||
exactly as in 3.2.
|
||||
- macOS: always double-buffered, `IsDoubleBuffered()` returns `true` (`include/wx/osx/window.h:161`);
|
||||
@@ -439,7 +439,7 @@ Two variants exist:
|
||||
(`src/msw/gdiimage.cpp` `wxGDIImage::GetScaleFactor`, `src/msw/dcmemory.cpp`; details in
|
||||
`references/dpi-bitmaps-fonts.md §wxBitmap`), while `GetLogicalSize()` stays the physical size there.
|
||||
- MSW `wxBitmap::Create(size, dc)` no longer multiplies by the DC content scale; the size is
|
||||
physical (`docs/changes.txt:94-96`).
|
||||
physical (`docs/changes.txt:100-102`).
|
||||
|
||||
**Usage — portable back buffer.**
|
||||
```cpp
|
||||
@@ -556,7 +556,7 @@ already prepared ([Buffered painting](#buffered-painting-and-double-buffering)).
|
||||
must set the appropriate fonts and colours" (`interface/wx/dc.h:775-780`). `GetFont()` returns `wxNullFont` until
|
||||
`SetFont()` is called (`interface/wx/dc.h:715-720`).
|
||||
- wx 3.3 moved the non-drawing members to `wxReadOnlyDC` and several overridable measuring virtuals
|
||||
now take it (`docs/changes.txt:228-231`); see `references/wx-33-changes.md`.
|
||||
now take it (`docs/changes.txt:260-263`); see `references/wx-33-changes.md`.
|
||||
|
||||
**OrcaSlicer.** Orca widgets measure in `messureSize()`. A `messureSize()` that builds a
|
||||
`wxClientDC dc(this)` (`Button::messureSize`, `TextInput::messureSize`) measures correctly on every
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Platforms, the wx build, and platform-specific code
|
||||
|
||||
Read this when code has to differ per platform, when a bug shows up on only one OS, toolkit or display
|
||||
server, or when you need to know how Orca's wxWidgets is built. It covers the wx fork and its build
|
||||
server, or when you need to know how Orca's wxWidgets is built. It covers the wx source pin and its build
|
||||
options, platform macros, per-platform summaries that point into the topic files, and where
|
||||
platform-specific code lives. It also owns runtime X11/Wayland detection, the Wayland gap list, custom
|
||||
title bars and window decoration, GTK native-chrome removal, and the cross-platform test checklist.
|
||||
@@ -58,37 +58,46 @@ Contents: [Rules](#rules) · [The wx build Orca uses](#the-wx-build-orca-uses)
|
||||
|
||||
## The wx build Orca uses
|
||||
|
||||
### Source, pin and local patch
|
||||
### Source, pin and local patches
|
||||
|
||||
- `deps/wxWidgets/wxWidgets.cmake` builds `https://github.com/SoftFever/Orca-deps-wxWidgets` at tag
|
||||
**`v3.3.2`** (`GIT_SHALLOW ON`, submodules `3rdparty/catch`, `3rdparty/pcre` and `3rdparty/libwebp`
|
||||
only). The fork carries Orca's build fixes, the clang-cl fix among them; do not duplicate
|
||||
a fork fix as a local patch under `deps/wxWidgets/` (cc390f11ee removed the local
|
||||
`0001-Clang-CL-fix.patch` once the fork carried the fix). The fork's clang-cl fix is the MSVC lib-dir
|
||||
selection in the installed `wxWidgetsConfig.cmake`: it looks for `<prefix>_<arch>_lib` (or `_dll`)
|
||||
under the consuming compiler's prefix first and then the sibling one (`clang` ↔ `vc`), because cl
|
||||
and clang-cl share an ABI and either can consume either build
|
||||
(`build/cmake/wxWidgetsConfig.cmake.in:53-73`).
|
||||
- **The one local patch** is `deps/wxWidgets/0001-macos-use-srgb-colour-components.patch`, applied
|
||||
- `deps/wxWidgets/wxWidgets.cmake` builds upstream `https://github.com/wxWidgets/wxWidgets` at tag
|
||||
**`v3.3.4`** (`GIT_SHALLOW ON`, submodules `3rdparty/catch`, `3rdparty/pcre` and `3rdparty/libwebp`
|
||||
only). Two in-tree patches under `deps/wxWidgets/` are applied, one per platform, so neither applies
|
||||
on Linux: `0001-macos-use-srgb-colour-components.patch` on Apple and
|
||||
`0002-clang-cl-sibling-compiler-prefix.patch` on Windows. The clang-cl patch is the old fork's
|
||||
clang-cl fix ported back to a local patch: it changes the MSVC lib-dir selection in the installed
|
||||
`wxWidgetsConfig.cmake` so it looks for `<prefix>_<arch>_lib` (or `_dll`) under the consuming
|
||||
compiler's prefix first and then the sibling one (`clang` ↔ `vc`), because cl and clang-cl share an
|
||||
ABI and either can consume either build (`build/cmake/wxWidgetsConfig.cmake.in:53-73`). Because the
|
||||
pin is upstream, every other build fix must live as a local patch under `deps/wxWidgets/`.
|
||||
- **The Apple patch** is `deps/wxWidgets/0001-macos-use-srgb-colour-components.patch`, applied
|
||||
only `if (APPLE)`. The `PATCH_COMMAND` first runs `git checkout -f -- src/osx/cocoa/colour.mm` and
|
||||
then `git apply`, so the step can run again safely (a7775296b0). The patch makes the wxOSX
|
||||
`wxColour` component getters (`wxNSColorRefData::Red/Green/Blue/Alpha` and `IsSolid`) convert the
|
||||
`NSColor` with `[NSColorSpace sRGBColorSpace]` instead of `NSCalibratedRGBColorSpace`, so colours
|
||||
read back on macOS match their sRGB values (custom-colour accuracy). Colour usage:
|
||||
`references/colours-dark-mode.md`.
|
||||
- **The Windows patch** is `deps/wxWidgets/0002-clang-cl-sibling-compiler-prefix.patch`, applied only
|
||||
`if (WIN32)`. Its `PATCH_COMMAND` first runs
|
||||
`git checkout -f -- build/cmake/wxWidgetsConfig.cmake.in` and then `git apply`, so the step can run
|
||||
again safely. It rewrites the `WIN32_MSVC_NAMING` branch of `build/cmake/wxWidgetsConfig.cmake.in`
|
||||
to try the consuming compiler's prefix first and then the sibling one (`clang` ↔ `vc`) when locating
|
||||
the installed `<prefix>_<arch>_lib`/`_dll` directory.
|
||||
- The checked-out source is the tree that every wx citation in this skill refers to:
|
||||
`deps/build/<arch>/dep_wxWidgets-prefix/src/dep_wxWidgets` on macOS and
|
||||
`deps/<tree>/dep_wxWidgets-prefix/src/dep_wxWidgets` on Linux and Windows (`deps/build` for a
|
||||
release build; `build_win.bat` names the others). Locate it with the bash or PowerShell lookup in
|
||||
`SKILL.md` §Ground truth. On macOS its
|
||||
`src/osx/cocoa/colour.mm` already has the patch applied.
|
||||
`src/osx/cocoa/colour.mm` already has the Apple patch applied; on Windows its
|
||||
`build/cmake/wxWidgetsConfig.cmake.in` already has the clang-cl patch applied.
|
||||
- **Flatpak builds wx separately.** `deps/CMakeLists.txt` leaves `dep_wxWidgets` out of the deps
|
||||
target when `FLATPAK` is set. Instead, `scripts/flatpak/com.orcaslicer.OrcaSlicer.yml` has its own
|
||||
`wxWidgets` module whose config-opts "mirror deps/wxWidgets/wxWidgets.cmake with FLATPAK=ON,
|
||||
DEP_WX_GTK3=ON": `-DwxBUILD_TOOLKIT=gtk3`, a shared build (`wxBUILD_SHARED=ON`,
|
||||
`BUILD_SHARED_LIBS=ON`, `d` debug postfix), and `wxUSE_LIBWEBP=sys`, because the builtin webp
|
||||
libraries are installed only by static builds. It links with lld and pins the fork's tag
|
||||
`orca-3.3.2` at a fixed commit. Option and version changes must be made in both files.
|
||||
libraries are installed only by static builds. It links with lld and pins upstream `v3.3.4` at
|
||||
commit `6a42a4b999b127cf28a8b5fe686da6b8ca93a9b8`. Option and version changes must be made in both
|
||||
files; it applies neither patch (GTK3, no MSVC).
|
||||
|
||||
### Toolkit per platform
|
||||
|
||||
@@ -188,7 +197,7 @@ Its `wx/gtk/private*` includes are commented out. The per-port headers outside t
|
||||
`wx/msw/private.h` (`BitmapComboBox.cpp`, `PresetComboBoxes.cpp`, Windows-guarded) and
|
||||
`wx/osx/private.h` (`Utils/MacDarkMode.mm`), come with the regular wx install. Private headers are
|
||||
port-specific and unversioned. Include one only under the same macro wx uses for that port or
|
||||
feature, and re-check it whenever the fork is bumped.
|
||||
feature, and re-check it whenever the wx pin is bumped.
|
||||
|
||||
### wxInspector
|
||||
|
||||
@@ -268,8 +277,8 @@ Each bullet names the mechanism and the file that owns it.
|
||||
popups with it are dismissed on deactivation, deferred through `CallAfter`. No key dismisses a
|
||||
popup, and `ProcessLeftDown` is never called. `PopupWindow::BindUnfocusEvent` is MSW-only →
|
||||
`references/popups-menus.md` §5.
|
||||
- **Painting:** in 3.3.2 windows are not double-buffered by default (the 3.3.0 global
|
||||
`WS_EX_COMPOSITED` was reverted, `docs/changes.txt:308`). Custom widgets buffer by hand →
|
||||
- **Painting:** in 3.3.4 windows are not double-buffered by default (the 3.3.0 global
|
||||
`WS_EX_COMPOSITED` was reverted, `docs/changes.txt:501`). Custom widgets buffer by hand →
|
||||
`references/painting-custom-widgets.md`.
|
||||
- **Building large panels:** every control is a native child window, and outside a sizer pass a move
|
||||
or resize is immediate, repainting when the window is shown [source: `src/msw/window.cpp:2036`
|
||||
@@ -284,8 +293,9 @@ Each bullet names the mechanism and the file that owns it.
|
||||
- **Mouse capture:** `wxEVT_MOUSE_CAPTURE_LOST` and `wxEVT_MOUSE_CAPTURE_CHANGED` are delivered →
|
||||
`references/mouse-keyboard-focus.md`.
|
||||
- **Controls:** `wxDataViewCtrl` is the generic implementation (`references/controls-dataview.md`).
|
||||
TaskDialog-based dialogs and common dialogs stay light in wx dark mode
|
||||
(`interface/wx/app.h:1434-1448`); Orca's `MsgDialog` family is owner-drawn →
|
||||
TaskDialog-based dialogs (since 3.3.3) and common dialogs (since 3.3.4) follow wx dark mode; the
|
||||
date/time/calendar controls, `wxPrintDialog` on Windows 10 and MDI applications stay light
|
||||
(`interface/wx/app.h:1442-1448`); Orca's `MsgDialog` family is owner-drawn →
|
||||
`references/windows-dialogs.md`.
|
||||
- **WebView:** Edge (WebView2). It needs the runtime (checked by `GUI_App::init_webview_runtime`),
|
||||
creates asynchronously, serves custom schemes as `https://<scheme>.wxsite`, and allows one script
|
||||
@@ -616,16 +626,16 @@ headers. Rows marked [source] or "protocol" come from the implementation or from
|
||||
| Area | What happens on Wayland | Cite | Orca handling / owner |
|
||||
|---|---|---|---|
|
||||
| Global pointer position | `wxGetMousePosition()` / `wxGetMouseState()` call `gdk_device_get_position` [source], but Wayland gives clients no global pointer position, so the result is not a screen position | `src/gtk/window.cpp` `wxGetMousePosition` | use event coordinates + `ClientToScreen` (`BBLTopbar`); dismiss popups by focus tracking (`SearchDialog::Dismiss`) → `references/mouse-keyboard-focus.md` |
|
||||
| Top-level position | the compositor places windows, and `SetPosition()` / `Move()` on a TLW have no effect (protocol) | — | `GUI_App::window_pos_restore` restores only size and maximised state; moves go through `gtk_window_begin_move_drag` |
|
||||
| Top-level position | the compositor places windows, and `SetPosition()` / `Move()` on a TLW have no effect (protocol). 3.3.4 added geometry restore through the Wayland XDG session-management protocol (`SaveGeometry`/`RestoreToGeometry` with the new `SaveString`/`RestoreString` fields) | `interface/wx/toplevel.h:439-455, 474-490` | `GUI_App::window_pos_restore` restores only size and maximised state; moves go through `gtk_window_begin_move_drag` |
|
||||
| Window icon | `SetIcon()` / `SetIcons()` "doesn't do anything when using Wayland … create a `.desktop` file" | `interface/wx/toplevel.h:517-521, 538-542` | `src/dev-utils/platform/unix/com.orcaslicer.OrcaSlicer.desktop` (`Icon=OrcaSlicer`, `StartupWMClass=orca-slicer`) |
|
||||
| App id | `wxAppConsole::SetClassName()` is the xdg `app_id` with GTK ≥ 3.24.22 (and the AUMID on Windows); it must be set before any TLW. wx applies it when a TLW is mapped, and only if it is non-empty [source: `wxTopLevelWindowGTK::GTKHandleMapped`] | `interface/wx/app.h:765-812` | Orca calls only `SetAppName(SLIC3R_APP_KEY)`, so GTK's default applies. On Windows, `SetClassName` would also change shell behaviour (MRU, Shift+middle-click) |
|
||||
| `wxClientDC` | deprecated in 3.3 ("please use wxInfoDC instead for obtaining information", `interface/wx/dcclient.h:43-46`). Drawing through it "simply doesn't have any effect" on GTK3/Wayland or wxOSX. `CanBeUsedForDrawing()` [source]: false on Wayland only for wxGTK (`src/gtk/dc.cpp`), always false on wxOSX, always true on wxMSW (`include/wx/{osx,msw}/dcclient.h`), although its doc also lists "wxMSW when using double buffering" | `interface/wx/dcclient.h:48-53, 80-88` | draw only in `wxPaintDC` after `Refresh()`/`RefreshRect()` → `references/painting-custom-widgets.md` |
|
||||
| `wxWindow::Update()` | "doesn't do anything in wxGTK port when using Wayland". [source] wx skips the GDK update calls there because they broke later updates (#25036) | `interface/wx/window.h:2405-2407` | never rely on `Update()` to paint synchronously |
|
||||
| `WarpPointer()` | works only if the compositor implements the pointer-warp protocol; mutter also needs a mouse button held | `interface/wx/window.h:3902-3907`; `docs/changes.txt:294` | Orca never warps the pointer |
|
||||
| `WarpPointer()` | works only if the compositor implements the pointer-warp protocol; mutter also needs a mouse button held | `interface/wx/window.h:3902-3907`; `docs/changes.txt:487` | Orca never warps the pointer |
|
||||
| `wxUIActionSimulator` | "currently doesn't work when using Wayland with wxGTK" | `interface/wx/uiaction.h:20` | not used; Orca also builds `wxUSE_XTEST=OFF` |
|
||||
| `wxBitmap(const wxCursor&)` | creates an invalid bitmap | `interface/wx/bitmap.h:393-395` | — |
|
||||
| OpenGL | only EGL; `PreferGLX()` has no effect. Without EGL in the build, wxGTK's `wxGLCanvas` shows a fatal message and refuses to work [source: `src/gtk/glcanvas.cpp` `IsAvailable`]. The EGL surface is a subsurface over the canvas, ready only after map and a frame callback [source: `src/unix/glegl.cpp`] | `interface/wx/glcanvas.h:1094-1095` | `CLI::run` forces X11 when wx lacks EGL; overlays are drawn in GL/ImGui, never as wx children over the canvas → `references/webview-gl-aui-media.md` |
|
||||
| AUI | the doc note "live resize is always used … for wxOSX and wxGTK3 when using Wayland" is obsolete: "As of wxWidgets 3.3.0 this function always returns false", and `wxAUI_MGR_LIVE_RESIZE` is in the default flags. Floating panes need global positions | `interface/wx/aui/framemanager.h:336-345` | `Plater::priv::priv` clears `wxAUI_MGR_ALLOW_FLOATING`; `sanitize_window_layout_for_wayland` strips floating state from the saved layout → `references/webview-gl-aui-media.md` §wxAuiManager |
|
||||
| AUI | the doc note "live resize is always used … for wxOSX and wxGTK3 when using Wayland" is obsolete: "As of wxWidgets 3.3.0 this function always returns false", and `wxAUI_MGR_LIVE_RESIZE` is in the default flags. AUI's docking-hint logic still needs global positions; 3.3.4 added system drag sessions (`StartDragSession`) so wx can move a pane's floating frame under Wayland anyway | `interface/wx/aui/framemanager.h:336-345`; `src/aui/framemanager.cpp:4574-4599` | `Plater::priv::priv` clears `wxAUI_MGR_ALLOW_FLOATING`; `sanitize_window_layout_for_wayland` strips floating state from the saved layout → `references/webview-gl-aui-media.md` §wxAuiManager |
|
||||
| Popups | a GTK popup is an `xdg_popup` only for COMBO/DROPDOWN/POPUP_MENU hints, so wx creates popups with `GDK_WINDOW_TYPE_HINT_COMBO` [source]. A chained popup's parent must be the mapped popup, and mapping it with a grab deactivates the toplevel (Orca's comments in `DropDown::mouseMove`, `DropDown::ShouldDismissOnTopWindowDeactivate`) | `src/gtk/popupwin.cpp:110-114` | `DropDown` transient-for chain, `ShouldDismissOnTopWindowDeactivate` → `references/popups-menus.md` |
|
||||
| Fractional scale | arrives as an integer GDK scale | `docs/doxygen/overviews/high_dpi.md:348-351` | → `references/dpi-bitmaps-fonts.md` |
|
||||
| Window decorations | some desktop environments draw a title bar on undecorated windows anyway | — | [Undecorated windows](#wayland-undecorated-top-level-windows-splash) |
|
||||
@@ -636,7 +646,9 @@ were two-finger scrolling (703, 3.1.3), the EGL-based `wxGLCanvas` for Wayland (
|
||||
support (498, both 3.1.5). New with the upgrade: "Many bug fixes for Wayland-specific problem" (397)
|
||||
and a `wxMediaCtrl` fix (402) in 3.1.6, GDK errors from `PopupMenu()` avoided (317, 3.1.7),
|
||||
`wxCURSOR_SIZING` fixed (261, 3.2.0). In 3.3, `WarpPointer()` on supported compositors
|
||||
(`docs/changes.txt:294`) and the EGL/Wayland high-DPI scale fix (`changes.txt:538`).
|
||||
(`docs/changes.txt:487`) and the EGL/Wayland high-DPI scale fix (`changes.txt:731`); in 3.3.4, a fix for
|
||||
the crash on pointer/seat disconnect (`changes.txt:371`), AUI pane dragging via system drag sessions
|
||||
(`:372`) and window-geometry restore via XDG session management (`:373`).
|
||||
|
||||
## Window decoration and custom title bars
|
||||
|
||||
@@ -658,7 +670,7 @@ There is no `wxCAPTION` on any platform; each port then needs its own handling.
|
||||
**Contract** [source + documented]. Since wx **3.3.0**, `wxTopLevelWindowMSW::MSWGetStyle` adds
|
||||
`WS_CAPTION` whenever any of `wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX` is set
|
||||
(`src/msw/toplevel.cpp:133-135`). The 3.3.0 wxMSW change list says "Turn wxCAPTION on automatically if
|
||||
required by other styles (#23575)" (`docs/changes.txt:581`). Commit eefdabcd98 attributes this to
|
||||
required by other styles (#23575)" (`docs/changes.txt:774`). Commit eefdabcd98 attributes this to
|
||||
3.3.2, but it is a 3.3.0 change. `SetWindowStyleFlag()` recomputes the native style through
|
||||
`MSWGetStyle` and turns the bits back on (`src/msw/window.cpp` `wxWindowMSW::MSWUpdateStyle`).
|
||||
|
||||
@@ -868,10 +880,11 @@ do both). Cite: 6148ba16b3, 988b500f33.
|
||||
|
||||
## wx 3.3 migration notes
|
||||
|
||||
Orca moved from **3.1.5** to 3.3.2 in 8248b06337 ("Updated wxWidgets to 3.3.2", #12941; build system
|
||||
in 2d7e26292b), so the 3.1.6–3.2.0 incompatible changes (`docs/changes_32.txt`) apply as well as
|
||||
`docs/changes.txt`. The version digest, every migration commit as a rule for new code, and the
|
||||
post-upgrade regressions to watch are owned by `references/wx-33-changes.md` (§8). The
|
||||
Orca moved from **3.1.5** to **3.3.2** in 8248b06337 ("Updated wxWidgets to 3.3.2", #12941; build system
|
||||
in 2d7e26292b); the pin is now upstream **3.3.4** (`deps/wxWidgets/wxWidgets.cmake`, tag `v3.3.4`), so
|
||||
the 3.1.6–3.2.0 incompatible changes (`docs/changes_32.txt`) apply as well as `docs/changes.txt`. The
|
||||
version digest, every migration commit as a rule for new code, and the post-upgrade regressions to
|
||||
watch are owned by `references/wx-33-changes.md` (§10); the 3.3.3 and 3.3.4 changes are its §8–§9. The
|
||||
platform-specific ones are described in this file: the `MainFrame` `WS_CAPTION` handling
|
||||
([MSW title bar](#msw-the-mainframe-custom-title-bar)), the macOS `kAEGetURL` re-registration and the
|
||||
`SidePopup` anchoring ([ifdef landscape](#the-ifdef-landscape)), and the GTK criticals filter
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Popups, transient windows and menus
|
||||
|
||||
How wx 3.3.2 popups and menus behave on each port, and the Orca wrappers built on them: `PopupWindow`,
|
||||
How wx 3.3.4 popups and menus behave on each port, and the Orca wrappers built on them: `PopupWindow`,
|
||||
`DropDown`/`ComboBox`, `SidePopup`, the search popups, frameless dialogs used as popups, `MenuFactory`,
|
||||
`append_menu_item`, `Plater::PopupMenu` and the macOS menubar versus `BBLTopbar`. Read it before you add
|
||||
or change anything that opens over other UI and must close by itself, or any context menu or menubar item.
|
||||
@@ -791,7 +791,7 @@ created with `wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT | wxF
|
||||
`wxWindow`. "The window automatically destroys itself when the user clicks on it or it loses the focus"
|
||||
(`interface/wx/tipwin.h:13-14`). Since 3.3.2 use `static Ref New(parent, text, maxLength, rectBound)`. The
|
||||
returned `wxTipWindow::Ref` is "guaranteed to become invalid when the tip window is closed", and the raw
|
||||
constructor is deprecated (`tipwin.h:27-132`; `docs/changes.txt:286`). `Create` positions the tip at the mouse
|
||||
constructor is deprecated (`tipwin.h:27-132`; `docs/changes.txt:479`). `Create` positions the tip at the mouse
|
||||
and pops it up immediately (`src/generic/tipwin.cpp:171-240`); on GTK it also captures the mouse.
|
||||
`SetBoundingRect` closes the tip when the mouse leaves that rectangle (`tipwin.h:160-172`). Orca:
|
||||
`Button::OnParentMotion` (MSW-only tooltips for disabled buttons) keeps a `wxTipWindow::Ref`.
|
||||
@@ -800,11 +800,11 @@ created with `wxBORDER_NONE | wxFRAME_NO_TASKBAR | wxFRAME_FLOAT_ON_PARENT | wxF
|
||||
`wxRichToolTipPopup` (`src/generic/richtooltipg.cpp`). Re-check it on every wx update.
|
||||
- **`wxInfoBar`** "calls its parent wxWindow::Layout() method and assumes that it will change the parent
|
||||
layout": add it to the parent's sizer (`interface/wx/infobar.h:38-44`). It is generic on all ports and native
|
||||
in wxGTK. Use `ShowMessage(msg, flags)`/`Dismiss()`. 3.3 adds `ShowCheckBox` (`docs/changes.txt:460`).
|
||||
in wxGTK. Use `ShowMessage(msg, flags)`/`Dismiss()`. 3.3 adds `ShowCheckBox` (`docs/changes.txt:653`).
|
||||
- **`wxNotificationMessage`** is "not a window", native on MSW, macOS and GTK (`interface/wx/notifmsg.h:12-18`).
|
||||
MSW recommends `MSWUseToasts()` before the first notification, macOS needs the alert notification style for
|
||||
actions, and GTK ignores the timeout for warnings and errors (`notifmsg.h:23-38`, 179-182). 3.3 reports the
|
||||
dismissal reason (`docs/changes.txt:488`). Orca does not use it. Its in-app notifications are the GL-canvas
|
||||
dismissal reason (`docs/changes.txt:681`). Orca does not use it. Its in-app notifications are the GL-canvas
|
||||
`NotificationManager`.
|
||||
|
||||
## 13. wxMenu and wxMenuItem
|
||||
@@ -862,7 +862,7 @@ submenu (it leaks), `Destroy(id)` deletes it, and `Remove()` returns ownership (
|
||||
an item switch it to owner-drawn (`MSWMustUseOwnerDrawn`, `src/msw/menuitem.cpp:1371-1377`). "Owner drawn items
|
||||
are also incompatible with dark mode support and using them makes the entire menu containing them to use
|
||||
standard light mode colours even in dark mode." 3.3.2 reworked MSW dark-mode menu rendering
|
||||
(`docs/changes.txt:305-306`); owner-drawn items still opt out of it.
|
||||
(`docs/changes.txt:498-499`); owner-drawn items still opt out of it.
|
||||
|
||||
**Labels and accelerators** (`menuitem.h:460-490`, 555-570).
|
||||
- The syntax is `"&Label\tCtrl+X"`; `&&` is a literal ampersand. `CTRL` means Cmd on macOS, and `RAWCTRL` gives
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sizers and layout
|
||||
|
||||
How wx 3.3.2 computes window sizes and lays out children, and how OrcaSlicer builds layouts on top of
|
||||
How wx 3.3.4 computes window sizes and lays out children, and how OrcaSlicer builds layouts on top of
|
||||
that: sizers and flags, best/min size, the fitting functions (`SetSizerAndFit`, `SetSizeHints`, `Fit`,
|
||||
`Layout`, `FitInside`) per platform, show/hide relayout, Freeze/Thaw, scrolled windows, `wxStaticText`
|
||||
wrapping, layout on DPI change, and Orca's layout idioms. Read it when building or reviewing any dialog
|
||||
@@ -604,7 +604,7 @@ Ordinary dialogs and the sidebar use plain `wxScrolledWindow`.
|
||||
without spaces never wraps with `wxStaticText::Wrap`.
|
||||
- `wxST_WRAP` (new in 3.3.2): "Wrap label text on multiple lines if necessary, using the available
|
||||
horizontal space. This style only works when the control is used inside a sizer"
|
||||
(`interface/wx/stattext.h:46-49`; `docs/changes.txt:280`). It is opt-in; labels without it are
|
||||
(`interface/wx/stattext.h:46-49`; `docs/changes.txt:473`). It is opt-in; labels without it are
|
||||
unaffected. It is implemented with `GetMinSizeFromKnownDirection` (`stattextcmn.cpp:285-312`).
|
||||
**[source]** The initial `CalcMin` still uses the unwrapped best size, so a fitted dialog grows to the
|
||||
full one-line width and nothing wraps; constrain the width another way (a fixed or min width on the
|
||||
|
||||
@@ -44,7 +44,8 @@ Contents: [Rules](#rules) · [Build facts](#build-facts-that-decide-string-behav
|
||||
12. One complete sentence per msgid, placeholders instead of concatenated fragments, the number
|
||||
placeholder in both plural forms, `// TRN` for ambiguous strings, a context for homonyms.
|
||||
→ §Plurals and contexts
|
||||
13. A wrapper around `wxGetTranslation` returns `wxString` by value. → §Translation
|
||||
13. A wrapper that converts a translation (`wxString::FromUTF8`, `ToUTF8()`, `format_wxstr`) returns
|
||||
by value; `wxGetTranslation()` itself returns `const wxString&`. → §Translation
|
||||
14. User-supplied text (preset, filament, file, printer names) in a mnemonic-interpreting label
|
||||
goes through `SetLabelText` or `wxControl::EscapeMnemonics`. → §Labels
|
||||
15. File dialogs: filters from `file_wildcards(FT_*)`, default dir `from_u8(app_config->get_last_dir())`,
|
||||
@@ -186,11 +187,11 @@ was the splash screen's event filter, fixed in 4088a36095; see `references/threa
|
||||
**modifies the string**. Use `s[n].GetValue()` or an explicit `int`/`wchar_t` type
|
||||
(`interface/wx/string.h:171-226`).
|
||||
- Since 3.3 `wxstr = {"Hello", 2}` is ambiguous (the `string_view` constructor); write
|
||||
`wxString{"Hello", 2}` (`docs/changes.txt:191-194`).
|
||||
`wxString{"Hello", 2}` (`docs/changes.txt:223-226`).
|
||||
- Never pass a `wxString`, `c_str()` or `mb_str()` to a real C vararg function (`printf`); use
|
||||
`wxString::Format`/`wxPrintf` or convert explicitly (`interface/wx/string.h:262-300`).
|
||||
- `wxUSE_STL` no longer exists; wx 3.3 re-enables implicit `wxString` → `std::string` only through
|
||||
`wxUSE_STD_STRING_CONV_IN_WXSTRING=1` (`docs/changes.txt:163-166`). Orca keeps it 0 and adds
|
||||
`wxUSE_STD_STRING_CONV_IN_WXSTRING=1` (`docs/changes.txt:195-198`). Orca keeps it 0 and adds
|
||||
`wxNO_UNSAFE_WXSTRING_CONV`; do not enable either conversion, the compile error is the guard.
|
||||
|
||||
### Pitfalls
|
||||
@@ -322,10 +323,13 @@ language's decimal separator; `wxString::ToCDouble`/`FromCDouble` do not.
|
||||
**wx contract** (`interface/wx/translation.h:577-640`): `wxGetTranslation(string, domain = "",
|
||||
context = "")` returns the original string when no catalog has it; a non-empty context needs a
|
||||
matching `msgctxt` in the catalog; the plural overload returns `string` for `n == 1` and `plural`
|
||||
otherwise when no catalog is found; "This function is thread-safe". Since 3.3 it returns
|
||||
**`wxString` by value**, not a const reference: "please change the return type of the function to
|
||||
wxString" (`docs/changes.txt:139-142`). Orca's `I18N::translate` overloads already return by value;
|
||||
keep any new wrapper that way, a `const wxString&` return now dangles.
|
||||
otherwise when no catalog is found; "This function is thread-safe". It returns **`const wxString&`**
|
||||
(`interface/wx/translation.h:615`; `include/wx/translation.h:277-309`). 3.3.2 changed this to a
|
||||
by-value `wxString` and **3.3.3 reverted it** to the 3.2.x reference, so the reference points at the
|
||||
catalog's own string or at `wxTranslations::GetUntranslatedString()`, both of which outlive the call.
|
||||
Forwarding that reference is therefore safe; what must return by value is a wrapper that constructs a
|
||||
temporary — `wxString::FromUTF8`, `ToUTF8()`, `format_wxstr`. Orca's `I18N::translate` overloads
|
||||
return `wxString` by value and `translate_utf8`/`_u8L` return `std::string`.
|
||||
|
||||
**OrcaSlicer macros** (`src/slic3r/GUI/I18N.hpp`):
|
||||
|
||||
@@ -429,7 +433,7 @@ using this class doesn't affect the native controls and dialogs", and on macOS 1
|
||||
C locale can break the menus (`interface/wx/intl.h:282-292`): native file dialogs, the app menu and
|
||||
standard buttons follow the system language. `wxLocale::IsAvailable` builds a region tag and asks
|
||||
`wxUILocale(...).IsSupported()` (`src/common/intl.cpp` `wxLocale::IsAvailable`), which on Unix no
|
||||
longer falls back to another region of the same language (`docs/changes.txt:75-79`); keep the
|
||||
longer falls back to another region of the same language (`docs/changes.txt:81-85`); keep the
|
||||
fallbacks in `load_language`.
|
||||
|
||||
- **Rule:** translate at use; never store a translated string in a namespace-scope or function-local
|
||||
@@ -457,7 +461,7 @@ call `SetLabel(label)`) [source]. `SetLabelMarkup` also treats an
|
||||
unescaped `&` as a mnemonic, needs `&`/`<` for literal characters, strips the markup where it
|
||||
is unsupported, and leaves the label unchanged (returns false) when the string is not well-formed
|
||||
(`interface/wx/control.h:200-360`); user text inside markup must be XML-escaped.
|
||||
Since 3.3 wxListbook/wxChoicebook also interpret mnemonics in page titles (`docs/changes.txt:128-130`);
|
||||
Since 3.3 wxListbook/wxChoicebook also interpret mnemonics in page titles (`docs/changes.txt:134-136`);
|
||||
Orca uses neither, but the rule is the same for every book control.
|
||||
|
||||
**OrcaSlicer.** `Label` (`Widgets/Label.cpp`) derives from `wxStaticText`; `Label::SetLabel` stores
|
||||
@@ -495,7 +499,7 @@ so build it from the wide form (`into_path(w).wstring()`) or stay with boost. At
|
||||
expands `$VAR`/`%VAR%` inside file names (`interface/wx/filename.h:90-103`); use `MakeAbsolute()` or
|
||||
explicit `wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE`. 3.3 adds `IsMSWExtendedLengthPath()` for `\\?\`
|
||||
paths "avoiding the 260 character path length restriction" (`interface/wx/filename.h:1040-1051`,
|
||||
`docs/changes.txt:551`). `wxFileSystem::FileNameToURL`/`URLToFileName` convert to and from `file:`
|
||||
`docs/changes.txt:744`). `wxFileSystem::FileNameToURL`/`URLToFileName` convert to and from `file:`
|
||||
URLs (`interface/wx/filesys.h:96-103, 175-180`).
|
||||
|
||||
**`wxStandardPaths`** (`interface/wx/stdpaths.h`): the directories "may or may not exist"
|
||||
@@ -552,9 +556,9 @@ for (const wxString& p : paths)
|
||||
|
||||
| | Behaviour |
|
||||
|---|---|
|
||||
| MSW | New-style `IFileDialog`: wx calls `SetDefaultExtension` with the selected filter's first extension and no longer calls `AppendExtension` itself (`src/msw/filedlg.cpp:1644-1656, 1738-1740`; `docs/changes.txt:556`). `SetExtraControlCreator` → XP-style dialog. |
|
||||
| MSW | New-style `IFileDialog`: wx calls `SetDefaultExtension` with the selected filter's first extension and no longer calls `AppendExtension` itself (`src/msw/filedlg.cpp:1644-1656, 1738-1740`; `docs/changes.txt:749`). `SetExtraControlCreator` → XP-style dialog. |
|
||||
| macOS | Open dialogs show **no filter choice** and apply all wildcards at once unless `wxSystemOptions::SetOption(wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1)`, and even then non-matching files are only greyed (`interface/wx/filedlg.h:117-128`). Matching compares the lower-cased last path extension (`wxOpenSavePanelDelegate panel:shouldEnableURL:`, `src/osx/cocoa/filedlg.mm:58-88`) [source]: case-insensitive, and a multi-dot pattern such as `*.gcode.3mf` or `*.zip.amf` never matches by itself. `wxFD_OVERWRITE_PROMPT` is always on (`:172-175`); `wxFD_OPEN` always behaves as `wxFD_FILE_MUST_EXIST` (`:184-189`). The save panel replaces the initial file name's extension with the first one in the wildcard (Orca's comment on `file_wildcards`). The native panel runs `runModal` and does not re-raise the parent dialog afterwards (`src/osx/cocoa/filedlg.mm` `ShowModal`); see `references/windows-dialogs.md` for the deferred re-raise. |
|
||||
| GTK3 | `GtkFileChooserNative` (portal-capable, e.g. Flatpak) when GTK ≥ 3.20 at runtime and neither `wxFD_PREVIEW` nor an extra control/customize hook is used (`src/gtk/filedlg.cpp:265-274, 437-443`; `src/gtk/dirdlg.cpp:122-130`; `docs/changes.txt:393`). It runs through `gtk_native_dialog_run`: there is no wx window, so size/position calls do nothing (`wxFileDialog::DoSetSize` is empty). Patterns go to `gtk_file_filter_add_pattern` per token and are **case-sensitive** (`src/gtk/filectrl.cpp:169`). The chooser is transient for the parent left after `GetParentForModalDialog`, which replaces a null (or hidden, dying or `wxWS_EX_TRANSIENT`) parent with the active top-level window, else the app's main top window (`src/gtk/filedlg.cpp:206, 223-225`; `src/common/dlgcmn.cpp:180-203` `DoGetParentForDialog`) [source]. `wxFD_PREVIEW` is GTK-only (`interface/wx/filedlg.h:195-197`). |
|
||||
| GTK3 | `GtkFileChooserNative` (portal-capable, e.g. Flatpak) when GTK ≥ 3.20 at runtime and neither `wxFD_PREVIEW` nor an extra control/customize hook is used (`src/gtk/filedlg.cpp:265-274, 437-443`; `src/gtk/dirdlg.cpp:122-130`; `docs/changes.txt:586`). It runs through `gtk_native_dialog_run`: there is no wx window, so size/position calls do nothing (`wxFileDialog::DoSetSize` is empty). Patterns go to `gtk_file_filter_add_pattern` per token and are **case-sensitive** (`src/gtk/filectrl.cpp:169`). The chooser is transient for the parent left after `GetParentForModalDialog`, which replaces a null (or hidden, dying or `wxWS_EX_TRANSIENT`) parent with the active top-level window, else the app's main top window (`src/gtk/filedlg.cpp:206, 223-225`; `src/common/dlgcmn.cpp:180-203` `DoGetParentForDialog`) [source]. `wxFD_PREVIEW` is GTK-only (`interface/wx/filedlg.h:195-197`). |
|
||||
| GTK2 (opt-out build) | never uses the native chooser; patterns case-sensitive. |
|
||||
|
||||
**OrcaSlicer:**
|
||||
@@ -650,7 +654,7 @@ dtor, and `!lock` tests `IsOpened()`.
|
||||
|
||||
| | Behaviour |
|
||||
|---|---|
|
||||
| MSW | `SetData`/`GetData` do not check `Open()` (`src/msw/clipbrd.cpp` `wxClipboard::SetData`), so code that forgets it works here only. `wxTextDataObject::SetData()` size must now include the 2-byte NUL (`docs/changes.txt:62-66`); use `SetText()` or the ctor. |
|
||||
| MSW | `SetData`/`GetData` do not check `Open()` (`src/msw/clipbrd.cpp` `wxClipboard::SetData`), so code that forgets it works here only. `wxTextDataObject::SetData()` size must now include the 2-byte NUL (`docs/changes.txt:68-72`); use `SetText()` or the ctor. |
|
||||
| macOS | without `Open()`, `SetData`/`AddData`/`GetData` return false through `wxCHECK_MSG(m_open, …)` without taking the object (`src/osx/carbon/clipbrd.cpp:84-105, 140-147`); a successful write is flushed to the pasteboard immediately (`:110-114`). |
|
||||
| GTK | same `wxCHECK_MSG(m_open, …)` early return (`src/gtk/clipbrd.cpp:643-647, 775`). `GetData`/`IsSupported` are asynchronous underneath: `wxClipboardSync` spins `YieldFor(wxEVT_CATEGORY_CLIPBOARD)` until GTK answers and forbids re-entrancy (`src/gtk/clipbrd.cpp:68-92`). PRIMARY selection exists. Under Wayland, Wayland MIME types are advertised next to the X11 atoms (`src/gtk/clipbrd.cpp:655-700`). |
|
||||
|
||||
@@ -793,8 +797,8 @@ from a non-main thread on wxOSX (`:39-40`); `wxCANCEL_DEFAULT` is ignored on wxO
|
||||
`wxID_OK/wxID_CANCEL/wxID_YES/wxID_NO/wxID_HELP` (`:269-275`), but **`wxMessageBox()` returns
|
||||
`wxYES/wxNO/wxCANCEL/wxOK/wxHELP`** (`:308-312`). `wxRichMessageDialog` is native only on MSW and
|
||||
generic elsewhere (`interface/wx/richmsgdlg.h:18-23`). On MSW every `TaskDialog`-based dialog
|
||||
(`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`) ignores dark mode
|
||||
(`interface/wx/app.h:1436-1440`).
|
||||
(`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`) has followed dark mode
|
||||
since 3.3.3 (`interface/wx/app.h:1442-1448`).
|
||||
|
||||
**OrcaSlicer.** UI code uses the MsgDialog family (`MessageDialog`, `RichMessageDialog`,
|
||||
`WarningDialog`, `ErrorDialog`, `InfoDialog`; `references/windows-dialogs.md` §MsgDialog family) for
|
||||
@@ -848,7 +852,7 @@ Orca does not use `wxConfig`/`wxFileConfig` (so the 3.3 change of the Unix defau
|
||||
|
||||
**Contract** (`interface/wx/secretstore.h`): on Unix it needs libsecret and a running secret service, so
|
||||
always check `IsOk(&errmsg)` (`:193-210, 257`); libsecret is no longer required at run time
|
||||
(`docs/changes.txt:533`), so a missing library or service shows up only as `IsOk()` false.
|
||||
(`docs/changes.txt:726`), so a missing library or service shows up only as `IsOk()` false.
|
||||
`GetDefault()` "may show a dialog to the user under some platforms, so it can take an arbitrarily long
|
||||
time to return" (`:243-246`). One username per service (`:260-268`).
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ yields and nested event loops, progress dialogs, startup, shutdown and exception
|
||||
screen, and the access rules for `wxGetApp()` and `app_config`. Read it whenever code runs off the
|
||||
main thread, defers work, starts a timer, yields, shows progress, or runs during startup or shutdown.
|
||||
|
||||
wx cites are relative to the pinned wx 3.3.2 tree (located as in `SKILL.md` §Ground truth).
|
||||
wx cites are relative to the pinned wx 3.3.4 tree (located as in `SKILL.md` §Ground truth).
|
||||
Orca builds wx with `wxBUILD_DEBUG_LEVEL=0` and `libslic3r_gui` with `wxDEBUG_LEVEL=0`, so `wxASSERT`
|
||||
is compiled out and `wxCHECK*` returns silently: a timer started off the main thread never fires on macOS,
|
||||
`Exit()` on a loop that is not the active one is ignored, `Start(0)` on macOS fails — all without
|
||||
@@ -454,12 +454,12 @@ and aborts the whole app. Wrap the entire body; log and convert to a status the
|
||||
`wxMessageQueue::Post(T&&)` accepts move-only types (`interface/wx/msgqueue.h:90-97`).
|
||||
- `wxTHREAD_WAIT_DEFAULT` is now `wxTHREAD_WAIT_BLOCK`; `wxTHREAD_WAIT_YIELD` "is dangerous" and "is
|
||||
only implemented in wxMSW and simply ignored under the other platforms" (`interface/wx/thread.h:648-675`),
|
||||
so the 3.3 default change (`docs/changes.txt:39-41`) only affects MSW code calling
|
||||
so the 3.3 default change (`docs/changes.txt:45-47`) only affects MSW code calling
|
||||
`Wait()`/`Delete()` from the GUI thread.
|
||||
- `wxCRITICAL_SECTION(name)` declares a function-static critical section, which is initialised
|
||||
safely only if the function is first called from the main thread before other threads call it;
|
||||
otherwise make it a global (`interface/wx/thread.h:1762-1779`). Prefer `std::mutex`.
|
||||
- `wxSecretStore` documents no thread-affinity notes in 3.3.2 (`interface/wx/secretstore.h`).
|
||||
- `wxSecretStore` documents no thread-affinity notes in 3.3.4 (`interface/wx/secretstore.h`).
|
||||
|
||||
## The Jobs framework
|
||||
|
||||
@@ -829,8 +829,8 @@ nothing) (`interface/wx/utils.h:1203-1212, 1243-1248`; see `references/strings-i
|
||||
|
||||
**Platforms.** On MSW `wxProgressDialog` is native: a TaskDialog run by a
|
||||
`wxProgressDialogTaskRunner` **wxThread**, yielding `ALL & ~USER_INPUT` (TIMER and THREAD included)
|
||||
(`src/msw/progdlg.cpp` `DispatchEvents`) **[source]**; anything based on `TaskDialog()` has no dark
|
||||
mode (`interface/wx/app.h:1436-1440`). On macOS and GTK it is `wxGenericProgressDialog`, which creates
|
||||
(`src/msw/progdlg.cpp` `DispatchEvents`) **[source]**; the native `TaskDialog` follows wx dark mode
|
||||
since 3.3.3 (`interface/wx/app.h:1442-1448`). On macOS and GTK it is `wxGenericProgressDialog`, which creates
|
||||
a temporary event loop if none is active (`src/generic/progdlgg.cpp:360-366`). On MSW (native
|
||||
dialog or Orca's generic one) and macOS, `CallAfter` bodies run inside `Update()`/`Pulse()`; on GTK
|
||||
the masked yield runs no queued event, so they wait until control returns to an event loop
|
||||
@@ -839,7 +839,7 @@ the masked yield runs no queued event, so they wait until control returns to an
|
||||
**OrcaSlicer.**
|
||||
- `Slic3r::GUI::ProgressDialog` (`Widgets/ProgressDialog.hpp`) is a themed fork of
|
||||
`wxGenericProgressDialog`: same `YieldFor(UI | USER_INPUT)` semantics, temporary event loop when
|
||||
none is active, generic on every platform (so no TaskDialog dark-mode gap).
|
||||
none is active, generic on every platform (so it is themed by Orca, not the native TaskDialog).
|
||||
- `detail::run_off_thread_with_progress` (`PluginsDialog.hpp`, wrapped by
|
||||
`PluginsDialog::run_with_dialog`/`run_with_dialog_wait`): a heap wx `wxProgressDialog` (the native
|
||||
TaskDialog on MSW, the generic dialog on macOS and GTK) pulsed by a
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# WebView, OpenGL canvas, AUI docking and media
|
||||
|
||||
How wxWebView, wxGLCanvas/wxGLContext, wxAuiManager/wxAuiToolBar and the camera view behave in the
|
||||
wx 3.3.2 tree Orca builds, and the Orca wrappers built on them: `WebView`, `WebViewHostDialog` and
|
||||
wx 3.3.4 tree Orca builds, and the Orca wrappers built on them: `WebView`, `WebViewHostDialog` and
|
||||
the web dialogs/panels, `OpenGLManager`, `GLCanvas3D` and its ImGui layer, the Plater docking
|
||||
manager, `BBLTopbar`, `wxMediaCtrl3`. Read it before touching any browser view, GL canvas, docked
|
||||
pane, the top bar or the camera view, or when debugging a blank web page, a black or garbled 3D
|
||||
@@ -242,7 +242,7 @@ a single message handler and the Chromium and IE backends do not support script
|
||||
| `Add…` return | `false` if *any* handler already exists, whatever its name (`src/msw/webview_edge.cpp:1635-1645`) | always `true` (`src/osx/webview_webkit.mm:620-629`); a duplicate name makes WebKit raise an NSException that cannot be caught and kills the app ([external]: Apple behaviour, recorded in the `WebView::CreateWebView` comment) | `false` on a duplicate or with no view, **but** `g_signal_connect` runs before registration, so a duplicate add leaves a second connection (`src/gtk/webview_webkit2.cpp:1638-1657`) |
|
||||
| `Remove…` | clears the single name (`1647-1652`) | removes the native handler (`632-636`) | unregisters but **does not disconnect** the signal (`1659-1664`): Remove + Add delivers every later message **twice** |
|
||||
| `window.<name>` alias | user script `window.<name> = window.chrome.webview` + `ExecuteScript` (`1030-1046`) | `AddUserScript` + **synchronous** `RunScript` (`626-628`) | `AddUserScript` + **synchronous** `RunScript` (`1650-1654`) |
|
||||
| Delivery | queued with `AddPendingEvent` (`785-813`); [documented] "Queue Edge wxWebView events" (`docs/changes.txt:525`) | `ProcessWindowEvent` **inside** the `WKScriptMessageHandler` delegate (`1324-1361`) | `HandleWindowEvent` **inside** the GTK signal (`397-409`) |
|
||||
| Delivery | queued with `AddPendingEvent` (`785-813`); [documented] "Queue Edge wxWebView events" (`docs/changes.txt:718`) | `ProcessWindowEvent` **inside** the `WKScriptMessageHandler` delegate (`1324-1361`) | `HandleWindowEvent` **inside** the GTK signal (`397-409`) |
|
||||
| Event fields | handler name and event object set | name set, **no event object** | **empty `GetMessageHandler()`, no event object** |
|
||||
| Body | `get_WebMessageAsJson`, JSON-decoded when it is a string (`798-809`) | NSString as is; dict/array → JSON; NSNumber → `stringValue` (booleans arrive as `1`/`0`); NSNull → `"null"` | object → JSON string, otherwise `ToString` (`64-94`) |
|
||||
|
||||
@@ -710,8 +710,8 @@ the environment variable `wx_opengl_egl=0` does the same; it exists only when `w
|
||||
returns true only when EGL is in use (false when `wxHAS_EGL` is undefined); `GetGLXVersion()` returns 0
|
||||
when GLX is not in use; both exist only when `wxHAS_GLX` is defined (`interface/wx/glcanvas.h:999-1030`).
|
||||
`wxGLCanvas::CreateSurface()` was removed "as exposing it doesn't make sense when wxGLCanvas may use
|
||||
either EGL or GLX" (`docs/changes.txt:250-252`); "Allow using GLX and EGL in same program (#26023)" is
|
||||
an upstream 3.3.2 wxGTK change (`docs/changes.txt:290-292`).
|
||||
either EGL or GLX" (`docs/changes.txt:282-284`); "Allow using GLX and EGL in same program (#26023)" is
|
||||
an upstream 3.3.2 wxGTK change (`docs/changes.txt:485`).
|
||||
|
||||
**Source** [source]:
|
||||
- When both backends are built, **EGL is the default even on X11** unless `PreferGLX()` or the
|
||||
@@ -727,7 +727,7 @@ an upstream 3.3.2 wxGTK change (`docs/changes.txt:290-292`).
|
||||
(`src/unix/glegl.cpp:801-860`).
|
||||
- The EGL-based `wxGLCanvas` for Wayland dates from 3.1.5 (`docs/changes_32.txt:497`), so it predates
|
||||
Orca's upgrade; its
|
||||
high-DPI scale under EGL/Wayland was fixed in 3.3.0 (`docs/changes.txt:538`).
|
||||
high-DPI scale under EGL/Wayland was fixed in 3.3.0 (`docs/changes.txt:731`).
|
||||
|
||||
**OrcaSlicer.**
|
||||
- `deps/wxWidgets/wxWidgets.cmake` passes `-DwxUSE_GLCANVAS_EGL=ON` (also in the Flatpak manifest).
|
||||
@@ -956,13 +956,13 @@ widgets beside the canvas (a sibling, not a child over it), or in a popup.
|
||||
`src/aui/framemanager.cpp:910-920`; `OnPaneButton`); `DestroyOnClose` panes are detached and `Destroy()`ed
|
||||
(`ClosePane`, `1431-1467`). With several handlers bound, each must `Skip()`.
|
||||
- **3.3 changes.** `wxAUI_MGR_HINT_FADE` left the default flags (`interface/wx/aui/framemanager.h:43-50`;
|
||||
`docs/changes.txt:132`); `wxAUI_MGR_LIVE_RESIZE` joined them (`interface/wx/aui/framemanager.h:59-62`); `AlwaysUsesLiveResize()` "always
|
||||
`docs/changes.txt:138`); `wxAUI_MGR_LIVE_RESIZE` joined them (`interface/wx/aui/framemanager.h:59-62`); `AlwaysUsesLiveResize()` "always
|
||||
returns false" as of 3.3.0 (`interface/wx/aui/framemanager.h:345`; `src/aui/framemanager.cpp:711-714`), non-live resize being
|
||||
restored (`docs/changes.txt:490`) — the older "live resize is always used on wxOSX and GTK3/Wayland"
|
||||
restored (`docs/changes.txt:683`) — the older "live resize is always used on wxOSX and GTK3/Wayland"
|
||||
statement (`interface/wx/aui/framemanager.h:336-340`) is obsolete. Docking hints for floating frames use
|
||||
`::wxGetMousePosition()` (`src/aui/framemanager.cpp:4139-4148`, `4242-4251`), which Wayland cannot supply.
|
||||
- `wxAuiNotebook` (not used by Orca): page indices are logical; use `GetPagePosition()` for on-screen
|
||||
order (`docs/changes.txt:121-126`); the default tab art changed (`35-37`).
|
||||
order (`docs/changes.txt:128-132`); the default tab art changed (`41-43`).
|
||||
|
||||
**OrcaSlicer.** Orca's docks use `AuiMgr` (`AuiMgr.hpp`), a `wxAuiManager` whose `CreateFloatingFrame`
|
||||
returns a `wxAuiFloatingFrame` that applies `UpdateFrameDarkUI`. `init(window)` calls
|
||||
@@ -1034,8 +1034,10 @@ Plater (Prepare and Preview); `DesignPanel::m_aui` manages the Design tab's body
|
||||
```
|
||||
- **Rule:** Disable floating on Wayland (clear `wxAUI_MGR_ALLOW_FLOATING`, `Floatable(false)`, strip
|
||||
floating state from saved layouts).
|
||||
**Why:** AUI's floating and docking-hint logic needs global pointer positions and top-level window
|
||||
moves (`wxGetMousePosition`, `wxEVT_MOVE`), which Wayland does not provide.
|
||||
**Why:** AUI's docking-hint logic needs global pointer positions and top-level window moves
|
||||
(`wxGetMousePosition`, `wxEVT_MOVE`), which Wayland does not provide. 3.3.4 added system drag sessions
|
||||
so wx can move a pane's floating frame there anyway (`src/aui/framemanager.cpp` `StartDragSession`),
|
||||
but the drop/docking hints still cannot work, so Orca keeps floating disabled.
|
||||
|
||||
## wxAuiToolBar and BBLTopbar
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ port; what Orca's `DPIDialog`/`DPIFrame` add; the Orca dialog recipe; and the `M
|
||||
Read it before writing or reviewing any dialog, frame, close handler, `Destroy()`/`delete`, or code
|
||||
that keeps a pointer to a window across an event, a `CallAfter` or a modal loop.
|
||||
|
||||
wx cites are relative to the pinned wx 3.3.2 tree (located as in `SKILL.md` §Ground truth). wx is
|
||||
wx cites are relative to the pinned wx 3.3.4 tree (located as in `SKILL.md` §Ground truth). wx is
|
||||
built with `wxBUILD_DEBUG_LEVEL=0` and `libslic3r_gui` with `wxDEBUG_LEVEL=0`: every wx assert
|
||||
quoted below is compiled out, so misuse fails silently (dropped call, stuck loop, freed memory), never with an assert dialog. "GTK" below
|
||||
means wxGTK as Orca builds it on Linux: GTK3 by default (X11 or Wayland); GTK2 is only an opt-out.
|
||||
@@ -424,7 +424,7 @@ mapped (`src/gtk/toplevel.cpp:1141-1243`).
|
||||
|
||||
**Raise.** "only requests the window manager to raise this window… If the window is currently hidden,
|
||||
this function does *not* show it", top-level windows only (`interface/wx/window.h:3013-3033`); true on all ports
|
||||
since 3.3 (`docs/changes.txt:144-146`). **[source]** MSW = `::SetForegroundWindow`, subject to the
|
||||
since 3.3 (`docs/changes.txt:145-147`). **[source]** MSW = `::SetForegroundWindow`, subject to the
|
||||
foreground lock — Windows may only flash the taskbar button (`src/msw/toplevel.cpp:650-655`); GTK =
|
||||
`gtk_window_present` only if shown (`src/gtk/toplevel.cpp:1301-1310`; during a deferred X11 first show it
|
||||
already counts as shown); macOS = `makeKeyAndOrderFront` only if shown (`src/osx/nonownedwnd_osx.cpp:289-295`, `src/osx/cocoa/nonownedwnd.mm:897-899`),
|
||||
@@ -910,8 +910,9 @@ buttons are chosen — in numeric id order, so `{"Save", "OK"}` makes Save prima
|
||||
**Rule.** Never `wxMessageBox`/`wxMessageDialog`/`wxRichMessageDialog` once the GUI exists; use the themed
|
||||
replacements in `src/slic3r/GUI/MsgDialog.hpp` (`Slic3r::GUI`), rooted in `MsgDialog : DPIDialog` (logo on the
|
||||
left, content on the right, `Button` row underneath, dark-mode and DPI aware). Why: on MSW the TaskDialog-based
|
||||
native boxes (`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`) ignore dark mode
|
||||
(`interface/wx/app.h:1436-1446`), and native boxes cannot match Orca's look. `wxMessageBox` remains only for
|
||||
native boxes (`wxMessageBox`, `wxMessageDialog`, `wxRichMessageDialog`, `wxProgressDialog`) now follow dark mode
|
||||
since 3.3.3, so only the date/time/calendar controls, `wxPrintDialog` on Windows 10 and MDI applications stay
|
||||
light (`interface/wx/app.h:1442-1448`); native boxes cannot match Orca's look. `wxMessageBox` remains only for
|
||||
failures before the GUI exists (e.g. `GUI_App::load_language`). Native message-box style limits:
|
||||
`references/strings-i18n-files.md`. Return-value trap when reading old code: `wxMessageBox()` returns
|
||||
`wxYES/wxNO/wxCANCEL/wxOK/wxHELP`, while `ShowModal()` returns `wxID_YES/…` (`interface/wx/msgdlg.h:269-276` vs `309-311`).
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
# wx 3.1.5 → 3.3.2: changes Orca code can trip on
|
||||
# wx 3.1.5 → 3.3.4: changes Orca code can trip on
|
||||
|
||||
OrcaSlicer moved from wxWidgets **3.1.5** to **3.3.2** (8248b06337, #12941). This file digests the
|
||||
OrcaSlicer moved from wxWidgets **3.1.5** to **3.3.2** (8248b06337, #12941) and the pin is now upstream
|
||||
**3.3.4** (`deps/wxWidgets/wxWidgets.cmake`, tag `v3.3.4`). This file digests the
|
||||
changes between those versions that matter to GUI code — the 3.1.6–3.2.0 incompatible changes, the
|
||||
3.3 incompatible changes, and the notable 3.3.0/3.3.1/3.3.2 changes — each with what it means for
|
||||
Orca, plus the migration already done in Orca as rules for new code. Read it when code written
|
||||
from older wx knowledge behaves oddly, when a wx doc says "since 3.3", or when reviewing code near
|
||||
the workarounds in §8. Where this file and prior wx knowledge disagree, this file wins.
|
||||
3.3 incompatible changes, and the notable 3.3.0/3.3.1/3.3.2/3.3.3/3.3.4 changes — each with what it
|
||||
means for Orca, plus the migration already done in Orca as rules for new code. Read it when code
|
||||
written from older wx knowledge behaves oddly, when a wx doc says "since 3.3", or when reviewing code
|
||||
near the workarounds in §10. Where this file and prior wx knowledge disagree, this file wins.
|
||||
|
||||
Contents: [Rules](#rules) · [1 Reading the change logs](#1-reading-the-change-logs) ·
|
||||
[2 3.1.6 → 3.2.0](#2-changes-from-316-to-320) · [3 3.3 behaviour changes](#3-33-behaviour-changes-that-compile) ·
|
||||
[4 3.3 build changes](#4-33-changes-that-break-the-build) · [5 3.3.0](#5-330-notable-changes) ·
|
||||
[6 3.3.1](#6-331-notable-fixes) · [7 3.3.2](#7-332-notable-changes) ·
|
||||
[8 Migration done in Orca](#8-migration-already-done-in-orca)
|
||||
[8 3.3.3](#8-333-notable-changes) · [9 3.3.4](#9-334-notable-changes) ·
|
||||
[10 Migration done in Orca](#10-migration-already-done-in-orca)
|
||||
|
||||
All `docs/`, `interface/`, `include/`, `src/`, `build/` cites are relative to the pinned wx tree
|
||||
(located as in `SKILL.md` §Ground truth), except paths
|
||||
@@ -21,8 +23,8 @@ explicitly called Orca's (`deps/…`, Orca's `src/CMakeLists.txt`) and bare Orca
|
||||
|
||||
1. Read every "now asserts" in the change logs as "now silently returns or does nothing" in Orca:
|
||||
wx asserts are compiled out. Validate arguments yourself. → [§1](#1-reading-the-change-logs)
|
||||
2. Target 3.3.2 only. Do not add `wxCHECK_VERSION` / `wxVERSION_NUMBER` /
|
||||
`wxVERSION_EQUAL_OR_GREATER_THAN` branches for older wx. → [§8](#8-migration-already-done-in-orca)
|
||||
2. Target 3.3.4 only. Do not add `wxCHECK_VERSION` / `wxVERSION_NUMBER` /
|
||||
`wxVERSION_EQUAL_OR_GREATER_THAN` branches for older wx. → [§10](#10-migration-already-done-in-orca)
|
||||
3. Mark every override of a wx virtual `override`. 3.2/3.3 changed parameter types (`wxBitmapBundle`,
|
||||
`wxReadOnlyDC`, `wxWindowBase*`, `wxVersionContext`); a stale signature must fail to compile, not
|
||||
become a silent overload. → [§4](#4-33-changes-that-break-the-build)
|
||||
@@ -39,33 +41,36 @@ explicitly called Orca's (`deps/…`, Orca's `src/CMakeLists.txt`) and bare Orca
|
||||
`WX_GL_SAMPLES`); `wxGLAttributes::Defaults()` no longer includes it. → [§3](#3-33-behaviour-changes-that-compile)
|
||||
9. Size a `wxImageList` in physical pixels (the bitmaps' `GetSize()`), or use the `wxBitmapBundle`
|
||||
image APIs. → [§3](#3-33-behaviour-changes-that-compile)
|
||||
10. Return translated strings as `wxString` by value. → [§3](#3-33-behaviour-changes-that-compile)
|
||||
10. `wxGetTranslation()` returns `const wxString&` (3.3.2 made it by-value; 3.3.3 reverted that); a
|
||||
wrapper that converts a translation returns by value. → [§3](#3-33-behaviour-changes-that-compile)
|
||||
11. Escape `&` in user text used as a control label or book page title. → [§3](#3-33-behaviour-changes-that-compile)
|
||||
12. `wxDynamicCast` only on a pointer whose static type derives from `wxObject`; use `dynamic_cast`
|
||||
for mixin interfaces (`wxComboPopup`, `wxItemContainer`, `wxTextEntry`). → [§4](#4-33-changes-that-break-the-build)
|
||||
13. Build a `wxArrayString` with `Add()` or an initializer list, walk wx lists with
|
||||
`compatibility_iterator` or range-for, and make a `wxString` the first operand of a mixed
|
||||
`+` chain. → [§4](#4-33-changes-that-break-the-build)
|
||||
14. MSW windows are not double-buffered by default in 3.3.2; a custom-painted control buffers itself.
|
||||
14. MSW windows are not double-buffered by default in 3.3.4; a custom-painted control buffers itself.
|
||||
→ [§5](#5-330-notable-changes)
|
||||
15. `wxEVT_DPI_CHANGED` now fires on GTK3 too; such handlers must be correct on GTK, and every handler
|
||||
you bind calls `Skip()` (`DPIAware`'s own is the one exception). → [§5](#5-330-notable-changes)
|
||||
16. wx MSW dark mode cannot be switched at runtime; do not replace Orca's NppDarkMode with it without
|
||||
keeping live theme switching. → [§5](#5-330-notable-changes)
|
||||
16. wx MSW dark mode became runtime-switchable in 3.3.3/3.3.4 (`SetAppearance`/`MSWEnableDarkMode`
|
||||
restyle existing windows); Orca still keeps NppDarkMode for its own chrome.
|
||||
→ [§5](#5-330-notable-changes), [§9](#9-334-notable-changes)
|
||||
17. After `wxStaticText::SetLabel`, re-wrap with `Wrap(-1); Wrap(w);` (or use `Label`); `wxST_WRAP`
|
||||
is opt-in and works only inside a sizer. → [§7](#7-332-notable-changes)
|
||||
18. On Linux/X11 call `wxGLCanvas::PreferGLX()` before any GL use; on Unix set a swap interval explicitly
|
||||
if frame pacing matters (wx forces 0). → [§7](#7-332-notable-changes)
|
||||
19. Compare `wxGrid::GetSelectedBlocks()` `begin()` with `end()` before dereferencing.
|
||||
→ [§8](#8-migration-already-done-in-orca)
|
||||
→ [§10](#10-migration-already-done-in-orca)
|
||||
20. Keep the post-upgrade workarounds (MainFrame `WS_CAPTION` masking, macOS deep-link handler,
|
||||
`MSWEnableDarkMode` ordering, `SidePopup` anchoring, MSW `GLCanvas3D::on_paint` render) when
|
||||
touching that code. → [§8](#8-migration-already-done-in-orca)
|
||||
touching that code. → [§10](#10-migration-already-done-in-orca)
|
||||
|
||||
## 1 Reading the change logs
|
||||
|
||||
**Sources.** `docs/changes.txt` lists changes since 3.2: incompatible behaviour changes :11-146,
|
||||
build-breaking changes :149-252, 3.3.2 :255-330, 3.3.1 :333-377, 3.3.0 :380-622.
|
||||
**Sources.** `docs/changes.txt` lists changes since 3.2: incompatible behaviour changes :11-178,
|
||||
build-breaking changes :181-292, 3.3.4 :295-385, 3.3.3 :388-445, 3.3.2 :448-523, 3.3.1 :526-570,
|
||||
3.3.0 :573-815.
|
||||
`docs/changes_32.txt` covers 3.x → 3.2.0: the cumulative "INCOMPATIBLE CHANGES SINCE 3.0.x" list
|
||||
:9-233, 3.2.0 :235-276, 3.1.7 :279-340, 3.1.6 :343-444. wxQt, wxiOS, wxUniv, wxMotif and wxGTK1
|
||||
items are left out here.
|
||||
@@ -73,11 +78,14 @@ items are left out here.
|
||||
**Coverage gaps.**
|
||||
- The "since 3.0.x" list in `changes_32.txt` is cumulative over all of 3.1.x. Most of it was already
|
||||
in force in 3.1.5; §2.1 lists only what was added after 3.1.5, §2.3 the older items worth knowing.
|
||||
- `changes_32.txt` in this tree stops at 3.2.0. The 3.2.1–3.2.10 maintenance fixes are not listed
|
||||
- `changes_32.txt` in this tree stops at 3.2.0. The 3.2.1–3.2.12 maintenance fixes are not listed
|
||||
anywhere in the tree.
|
||||
- 3.3.0's list is relative to 3.2.8 (`changes.txt:383`). 3.3.2's list is relative to 3.2.10, and the
|
||||
- 3.3.0's list is relative to 3.2.8 (`changes.txt:576`). 3.3.2's list is relative to 3.2.10, and the
|
||||
full set of changes since 3.3.1 *also includes* the 3.2.9 and 3.2.10 fixes, which are **not**
|
||||
listed in this file (`changes.txt:258-259`).
|
||||
listed in this file (`changes.txt:451-452`). 3.3.3's list is relative to 3.2.11, and its changes
|
||||
since 3.3.2 *also include* the 3.2.10–3.2.11 fixes (`changes.txt:391-392`); 3.3.4's list is
|
||||
relative to 3.2.11 too, and its changes since 3.3.3 *also include* the 3.2.11–3.2.12 fixes
|
||||
(`changes.txt:298-299`).
|
||||
|
||||
**"Asserts" mean silence in Orca.** wx is built with `-DwxBUILD_DEBUG_LEVEL=0`
|
||||
(`deps/wxWidgets/wxWidgets.cmake` → `build/cmake/init.cmake:245-246`), and `libslic3r_gui` gets
|
||||
@@ -117,7 +125,7 @@ the 3.1.7-specific section.
|
||||
| `wxSpinCtrl::SetValue(wxString)` sends no events on MSW (as documented) | :129-130 | do not rely on setter events (`controls-dataview.md`) |
|
||||
| `wxButton::GetBitmap{Current,Disabled,Focus,Pressed}()` return a valid bitmap on MSW only if set | :132-134 | check `IsOk()` |
|
||||
| `wxFileName::GetVolume()` returns `\\share` for UNC paths and `\\?\Volume{GUID}` for GUID paths | :136-140 | path code comparing volumes |
|
||||
| `wxBitmapComboBoxBase::SetItemBitmap()` takes `wxBitmapBundle` | :152-153 | the bundle change also retyped `OnAddBitmap` (5f365b5c6b, §8) |
|
||||
| `wxBitmapComboBoxBase::SetItemBitmap()` takes `wxBitmapBundle` | :152-153 | the bundle change also retyped `OnAddBitmap` (5f365b5c6b, §10) |
|
||||
| MSW also links `oleacc` (3.1.5 already needed `shlwapi`, `uxtheme`, `version`) | :158-163 | automatic with MSVC |
|
||||
| Xcode projects drop i386, add arm64 | :205-207 | none (CMake build) |
|
||||
| `wxImage` ctor from XPM data is `explicit` | :225-226 | write `wxImage(xpm)` |
|
||||
@@ -136,7 +144,7 @@ the 3.1.7-specific section.
|
||||
| MSW: TLW resizing on DPI change improved and overridable — a handler that sizes the TLW itself does not `Skip()` (3.2.0) | `changes_32.txt:269`; `interface/wx/event.h` (`wxDPIChangedEvent`) | Orca's `DPIAware` handler does not `Skip()` (`dpi-bitmaps-fonts.md`) |
|
||||
| `wxUILocale` (3.1.6); `wxLocale::IsAvailable` is now implemented through it | `changes_32.txt:348`; `src/common/intl.cpp:740-781` | see `wxUILocale::IsSupported` in §3 |
|
||||
| `wxWebView::RunScriptAsync()` (3.1.6) | `changes_32.txt:382` | `webview-gl-aui-media.md` |
|
||||
| wxOSX: "Allow user input in `wxPopupTransientWindow`" (3.1.7) — the popup's child holds mouse capture while the cursor is outside it and releases it inside, toggled from `OnIdle` [source] | `changes_32.txt:334`; `src/common/popupcmn.cpp:438-471` | how wxOSX transient popups track the mouse; the macOS gap-dismissal worked around in `SidePopup::Popup` is not traced to a specific wx change (§8; `popups-menus.md`) |
|
||||
| wxOSX: "Allow user input in `wxPopupTransientWindow`" (3.1.7) — the popup's child holds mouse capture while the cursor is outside it and releases it inside, toggled from `OnIdle` [source] | `changes_32.txt:334`; `src/common/popupcmn.cpp:438-471` | how wxOSX transient popups track the mouse; the macOS gap-dismissal worked around in `SidePopup::Popup` is not traced to a specific wx change (§10; `popups-menus.md`) |
|
||||
| wxGTK: Wayland fixes (3.1.6), no GDK errors from `PopupMenu()` on Wayland (3.1.7), `wxCURSOR_SIZING` on Wayland (3.2.0) | `changes_32.txt:397, 317, 261` | `platforms.md` |
|
||||
| MSW: all native modal dialogs are app-modal (3.1.6) | `changes_32.txt:409` | `windows-dialogs.md` |
|
||||
| Also new: `wxKeyEvent::IsAutoRepeat()`, `wxSpinCtrl::GetTextValue()/SetIncrement()`, `wxTopLevelWindow::SetContentProtection()`, `wxEVT_SPLITTER_SASH_POS_RESIZE`, OSX full-screen view options, OSX `wxEVT_CHAR` from `wxDataViewCtrl` | `changes_32.txt:364-436` | available API |
|
||||
@@ -167,7 +175,7 @@ These were already in force in 3.1.5, so the upgrade did not change them, but co
|
||||
|
||||
## 3 3.3 behaviour changes that compile
|
||||
|
||||
`changes.txt` "Changes in behaviour not resulting in compilation errors" (:11-146). Each row: the
|
||||
`changes.txt` "Changes in behaviour not resulting in compilation errors" (:11-178). Each row: the
|
||||
change, its line, and what it means for Orca.
|
||||
|
||||
| Change | Line | Orca relevance |
|
||||
@@ -177,31 +185,30 @@ change, its line, and what it means for Orca.
|
||||
| `wxGLCanvas` no longer multisamples by default | :21-23 | pitfall below |
|
||||
| `wxFileConfig` on Unix defaults to XDG `~/.config/appname.conf` (old file still used; `wxCONFIG_USE_XDG`/`wxCONFIG_USE_HOME`, `MigrateLocalFile()`) | :25-29 | none: Orca uses `AppConfig`, no `wxConfig` (`strings-i18n-files.md`) |
|
||||
| `wxColourDatabase` uses CSS values; `UseScheme()` restores the old ones (`interface/wx/gdicmn.h:845, 973-996`) | :31-33 | none: stock colours (`*wxGREEN`, …) are fixed RGB (`src/common/gdicmn.cpp:789-830`) and Orca builds colours from hex/RGB. Do not build colours from names |
|
||||
| `wxAuiNotebook` default art is the new flat art; `wxAuiNativeTabArt` (or `"native"` in XRC) keeps the old look | :35-37 | none: no `wxAuiNotebook` in Orca |
|
||||
| `wxTHREAD_WAIT_DEFAULT` is `wxTHREAD_WAIT_BLOCK`: `wxThread::Delete()/Wait()` no longer pump events | :39-41 | Orca uses std/boost threads (`wxThread` only for `IsMain()`); a new `wxThread` whose exit needs the main loop would deadlock |
|
||||
| `wxDocument::OnCloseDocument()` runs once, after the views are destroyed (it used to run twice when the document was closed from the menu); an override must not rely on any view existing | :43-46 | none: no doc/view |
|
||||
| `wxGrid::FreezeTo()` asserts on out-of-range counts, and freezes even when the grid is too small | :48-51 | silent `false` in Orca; it also refuses reordered or drag-movable rows/columns [source] (`src/generic/grid.cpp:5742-5750`). Clamp arguments (`controls-dataview.md`) |
|
||||
| Invalid `wxImageList` calls assert | :53-56 | silent in Orca; `wxCHECK` returns (generic `Add` → -1). Create the list with a valid size before use |
|
||||
| `wxTRANSPARENT_WINDOW` does nothing (`#define wxTRANSPARENT_WINDOW 0`, `include/wx/defs.h:1449`); MSW code that needs it can set `WS_EX_TRANSPARENT` | :58-60 | pitfall below; 026b105dcb |
|
||||
| MSW `wxTextDataObject::SetData()` size includes the 2-byte NUL (consistent with `GetDataSize()`); an old-style size chops the last character | :62-66 | none: Orca uses the `wxTextDataObject(text)` ctor; use `SetText()`, never `SetData()` |
|
||||
| `wxListCtrl::EditLabel()` asserts without `wxLC_EDIT_LABELS` | :68-69 | silent no-op in Orca; add the style where editing is intended |
|
||||
| MSW `wxSystemAppearance::IsDark()` reports the app's own mode; `AreAppsDark()`/`IsSystemDark()` report the OS | :71-73 | pitfall below |
|
||||
| Unix `wxUILocale::IsSupported()` no longer falls back to another region of the same language; pass just `"fr"` to accept any `fr_XX` | :75-79 | `wxLocale::IsAvailable` builds the region-qualified tag (`GetCanonicalWithRegion()`) and calls `IsSupported()` [source] (`src/common/intl.cpp:740-781`); `GUI_App::load_language` relies on it, so on Linux a language whose canonical locale (e.g. `fr_FR`) is not installed reports unavailable. Keep the fallbacks in `load_language` |
|
||||
| Deprecated `wxPGCellRenderer::DrawCaptionSelectionRect()` overload not called; override the overload taking `wxWindow*`, or enable 3.0 compatibility | :81-83 | none: no propgrid in Orca's own code |
|
||||
| `wxImageList` size is in physical pixels | :85-88 | pitfall below |
|
||||
| Mac `wxWebRequest` no longer uses persistent storage. The entry names `wxWebRequest::EnablePersistentStorage()`; the real API is `wxWebSession::EnablePersistentStorage(bool)` (`interface/wx/webrequest.h:1612-1629`; also `wxWebSessionSync`, :1835), macOS-only, before the first request | :90-92 | none: Orca uses `wxWebRequest` only for image downloads (`wxWebSession::GetDefault().CreateRequest` in `StatusPanel`, `SliceInfoPanel`, `ReleaseNote`, `DeviceErrorDialog`); network and login agents use libcurl (`Slic3r::Http`) |
|
||||
| MSW `wxBitmap::Create(size, dc)` no longer multiplies by the DC's content scale; the size is physical | :94-96 | remove compensating scaling; use `CreateWithLogicalSize` for logical sizes |
|
||||
| `wxIMAGE_QUALITY_NEAREST` has a new value and is no longer `wxIMAGE_QUALITY_NORMAL`; `NORMAL` (the `Scale`/`Rescale` default) is bilinear + box average (`interface/wx/image.h:31-67`) | :98-99 | never store or compare the enum numerically; default-quality thumbnails and icons look smoother than under 3.1.5; pass `wxIMAGE_QUALITY_NEAREST` for pixel-exact scaling |
|
||||
| `wxTextCtrl::{Save,Load}File()` treat `.rtf` as RTF | :101-104 | pass `wxTEXT_TYPE_PLAIN` to keep plain text |
|
||||
| `wxClientDC`/`wxPaintDC` offset their origin by a `wxFrame` toolbar on every port | :106-109 | none: Orca frames have no native toolbar (`BBLTopbar` is a child `wxAuiToolBar`) |
|
||||
| `wxTextCtrl::SetLabel()` does nothing and asserts on every port (MSW used to act as `SetValue`) | :111-113 | pitfall below |
|
||||
| `wxAuiGenericTabArt` subclasses (also via `wxAuiMSWTabArt`) override `DrawPageTab()`/`GetPageTabSize()` instead of `DrawTab()`/`GetTabSize()`; direct `wxAuiTabArt` subclasses still work | :115-120 | none: no Orca tab art |
|
||||
| `wxAuiNotebook` page index is logical (reorder-independent); `GetPagePosition()` gives the screen position | :122-126 | none; index math under `wxAUI_NB_TAB_MOVE` is what breaks |
|
||||
| `wxListbook`/`wxChoicebook` interpret mnemonics in page titles "just as the other wx*book classes already did" | :128-130 | Orca uses neither (`BedShapeDialog` uses `wxSimplebook` + a combo); every book interprets `&` (`interface/wx/bookctrl.h:141-147`) → rule 11 |
|
||||
| `wxAUI_MGR_HINT_FADE` is not in the default `wxAuiManager` style | :132-133 | Orca's `AuiMgr` keeps the default flags (minus `wxAUI_MGR_ALLOW_FLOATING` on Wayland, `AuiMgr::init`), so the docking hint no longer fades; add the flag if wanted |
|
||||
| `wxPrintDialogData::SetAllPages(false)`/`SetSelection(false)` changed meaning | :135-137 | none |
|
||||
| `wxGetTranslation()` returns `wxString` by value | :139-142 | pitfall below |
|
||||
| `wxWindow::Raise()` no longer shows a hidden window on any port | :144-146 | pitfall below; ba867cc534 |
|
||||
| `wxAuiNotebook` default art is the new flat art; `wxAuiNativeTabArt` (or `"native"` in XRC) keeps the old look | :41-43 | none: no `wxAuiNotebook` in Orca |
|
||||
| `wxTHREAD_WAIT_DEFAULT` is `wxTHREAD_WAIT_BLOCK`: `wxThread::Delete()/Wait()` no longer pump events | :45-47 | Orca uses std/boost threads (`wxThread` only for `IsMain()`); a new `wxThread` whose exit needs the main loop would deadlock |
|
||||
| `wxDocument::OnCloseDocument()` runs once, after the views are destroyed (it used to run twice when the document was closed from the menu); an override must not rely on any view existing | :49-52 | none: no doc/view |
|
||||
| `wxGrid::FreezeTo()` asserts on out-of-range counts, and freezes even when the grid is too small | :54-57 | silent `false` in Orca; it also refuses reordered or drag-movable rows/columns [source] (`src/generic/grid.cpp:5742-5750`). Clamp arguments (`controls-dataview.md`) |
|
||||
| Invalid `wxImageList` calls assert | :59-62 | silent in Orca; `wxCHECK` returns (generic `Add` → -1). Create the list with a valid size before use |
|
||||
| `wxTRANSPARENT_WINDOW` does nothing (`#define wxTRANSPARENT_WINDOW 0`, `include/wx/defs.h:1449`); MSW code that needs it can set `WS_EX_TRANSPARENT` | :64-66 | pitfall below; 026b105dcb |
|
||||
| MSW `wxTextDataObject::SetData()` size includes the 2-byte NUL (consistent with `GetDataSize()`); an old-style size chops the last character | :68-72 | none: Orca uses the `wxTextDataObject(text)` ctor; use `SetText()`, never `SetData()` |
|
||||
| `wxListCtrl::EditLabel()` asserts without `wxLC_EDIT_LABELS` | :74-75 | silent no-op in Orca; add the style where editing is intended |
|
||||
| MSW `wxSystemAppearance::IsDark()` reports the app's own mode; `AreAppsDark()`/`IsSystemDark()` report the OS | :77-79 | pitfall below |
|
||||
| Unix `wxUILocale::IsSupported()` no longer falls back to another region of the same language; pass just `"fr"` to accept any `fr_XX` | :81-85 | `wxLocale::IsAvailable` builds the region-qualified tag (`GetCanonicalWithRegion()`) and calls `IsSupported()` [source] (`src/common/intl.cpp:740-781`); `GUI_App::load_language` relies on it, so on Linux a language whose canonical locale (e.g. `fr_FR`) is not installed reports unavailable. Keep the fallbacks in `load_language` |
|
||||
| Deprecated `wxPGCellRenderer::DrawCaptionSelectionRect()` overload not called; override the overload taking `wxWindow*`, or enable 3.0 compatibility | :87-89 | none: no propgrid in Orca's own code |
|
||||
| `wxImageList` size is in physical pixels | :91-94 | pitfall below |
|
||||
| Mac `wxWebRequest` no longer uses persistent storage. The entry names `wxWebRequest::EnablePersistentStorage()`; the real API is `wxWebSession::EnablePersistentStorage(bool)` (`interface/wx/webrequest.h:1612-1629`; also `wxWebSessionSync`, :1835), macOS-only, before the first request | :96-98 | none: Orca uses `wxWebRequest` only for image downloads (`wxWebSession::GetDefault().CreateRequest` in `StatusPanel`, `SliceInfoPanel`, `ReleaseNote`, `DeviceErrorDialog`); network and login agents use libcurl (`Slic3r::Http`) |
|
||||
| MSW `wxBitmap::Create(size, dc)` no longer multiplies by the DC's content scale; the size is physical | :100-102 | remove compensating scaling; use `CreateWithLogicalSize` for logical sizes |
|
||||
| `wxIMAGE_QUALITY_NEAREST` has a new value and is no longer `wxIMAGE_QUALITY_NORMAL`; `NORMAL` (the `Scale`/`Rescale` default) is bilinear + box average (`interface/wx/image.h:31-67`) | :104-105 | never store or compare the enum numerically; default-quality thumbnails and icons look smoother than under 3.1.5; pass `wxIMAGE_QUALITY_NEAREST` for pixel-exact scaling |
|
||||
| `wxTextCtrl::{Save,Load}File()` treat `.rtf` as RTF | :107-110 | pass `wxTEXT_TYPE_PLAIN` to keep plain text |
|
||||
| `wxClientDC`/`wxPaintDC` offset their origin by a `wxFrame` toolbar on every port | :112-115 | none: Orca frames have no native toolbar (`BBLTopbar` is a child `wxAuiToolBar`) |
|
||||
| `wxTextCtrl::SetLabel()` does nothing and asserts on every port (MSW used to act as `SetValue`) | :117-119 | pitfall below |
|
||||
| `wxAuiGenericTabArt` subclasses (also via `wxAuiMSWTabArt`) override `DrawPageTab()`/`GetPageTabSize()` instead of `DrawTab()`/`GetTabSize()`; direct `wxAuiTabArt` subclasses still work | :121-126 | none: no Orca tab art |
|
||||
| `wxAuiNotebook` page index is logical (reorder-independent); `GetPagePosition()` gives the screen position | :128-132 | none; index math under `wxAUI_NB_TAB_MOVE` is what breaks |
|
||||
| `wxListbook`/`wxChoicebook` interpret mnemonics in page titles "just as the other wx*book classes already did" | :134-136 | Orca uses neither (`BedShapeDialog` uses `wxSimplebook` + a combo); every book interprets `&` (`interface/wx/bookctrl.h:141-147`) → rule 11 |
|
||||
| `wxAUI_MGR_HINT_FADE` is not in the default `wxAuiManager` style | :138-139 | Orca's `AuiMgr` keeps the default flags (minus `wxAUI_MGR_ALLOW_FLOATING` on Wayland, `AuiMgr::init`), so the docking hint no longer fades; add the flag if wanted |
|
||||
| `wxPrintDialogData::SetAllPages(false)`/`SetSelection(false)` changed meaning | :141-143 | none |
|
||||
| `wxWindow::Raise()` no longer shows a hidden window on any port | :145-147 | pitfall below; ba867cc534 |
|
||||
|
||||
**Pitfalls**
|
||||
|
||||
@@ -277,7 +284,7 @@ change, its line, and what it means for Orca.
|
||||
// Wrong: m_input_ip->GetTextCtrl()->SetLabelText(m_obj->get_dev_ip());
|
||||
// Right: m_input_ip->GetTextCtrl()->ChangeValue(m_obj->get_dev_ip()); // no wxEVT_TEXT
|
||||
```
|
||||
Cite: `docs/changes.txt:111-113`; `controls-dataview.md`.
|
||||
Cite: `docs/changes.txt:117-119`; `controls-dataview.md`.
|
||||
|
||||
- **Rule:** Size a `wxImageList` from the bitmaps' physical size, or use
|
||||
`SetImages(std::vector<wxBitmapBundle>)`.
|
||||
@@ -293,18 +300,23 @@ change, its line, and what it means for Orca.
|
||||
// Right: wxBitmap bmp = create_scaled_bitmap("icon", this, 16);
|
||||
// m_images = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), false);
|
||||
```
|
||||
Cite: `docs/changes.txt:85-88`; `Tab` builds its list from `bmp().GetWidth()/GetHeight()`;
|
||||
Cite: `docs/changes.txt:91-94`; `Tab` builds its list from `bmp().GetWidth()/GetHeight()`;
|
||||
`dpi-bitmaps-fonts.md`.
|
||||
|
||||
- **Rule:** A function that returns a translation returns `wxString` by value.
|
||||
**Why:** `wxGetTranslation()` returns by value now (`include/wx/translation.h:278-321`); returning
|
||||
it as `const wxString&` dangles. Orca's `I18N::translate` overloads and `_L` already return by
|
||||
value.
|
||||
- **Rule:** A wrapper that converts a translation returns by value; `wxGetTranslation()` itself
|
||||
returns `const wxString&`.
|
||||
**Why:** 3.3.2 changed `wxGetTranslation()` to return `wxString` by value, and **3.3.3 reverted it**
|
||||
(`interface/wx/translation.h:615`, `include/wx/translation.h:277-309`), so the return type is the
|
||||
3.2.x `const wxString&` again. That reference points at the catalog's own string or at
|
||||
`wxTranslations::GetUntranslatedString()`, both of which outlive the call, so forwarding it as a
|
||||
reference is safe. What still dangles is a temporary you construct: `wxString::FromUTF8`,
|
||||
`ToUTF8()`, `format_wxstr`. Orca's `I18N::translate` overloads return `wxString` by value and
|
||||
`translate_utf8`/`_u8L` return `std::string`.
|
||||
```cpp
|
||||
// Wrong: const wxString& title() { return _L("Printer"); }
|
||||
// Right: wxString title() { return _L("Printer"); }
|
||||
// Wrong: const wxString& path() { return wxString::FromUTF8(raw); } // temporary
|
||||
// Right: wxString path() { return wxString::FromUTF8(raw); }
|
||||
```
|
||||
Cite: `docs/changes.txt:139-142`; `I18N.hpp`.
|
||||
Cite: §8 (the 3.3.3 revert); `I18N.hpp`.
|
||||
|
||||
- **Rule:** Escape `&` in user data (preset, filament, printer, file names) shown as a control label or
|
||||
book page title.
|
||||
@@ -314,37 +326,37 @@ change, its line, and what it means for Orca.
|
||||
// Wrong: book->AddPage(page, preset_name);
|
||||
// Right: book->AddPage(page, wxControl::EscapeMnemonics(preset_name)); // or label->SetLabelText(name)
|
||||
```
|
||||
Cite: `docs/changes.txt:128-130`; `interface/wx/bookctrl.h:141-147`; `controls-dataview.md`.
|
||||
Cite: `docs/changes.txt:134-136`; `interface/wx/bookctrl.h:141-147`; `controls-dataview.md`.
|
||||
|
||||
## 4 3.3 changes that break the build
|
||||
|
||||
`changes.txt` "Changes in behaviour which may result in build errors" (:149-252).
|
||||
`changes.txt` "Changes in behaviour which may result in build errors" (:181-292).
|
||||
|
||||
| Change | Line | Orca relevance |
|
||||
|---|---|---|
|
||||
| 3.0-deprecated symbols disabled by default (`WXWIN_COMPATIBILITY_3_0=1` at wx build time re-enables them), 2.8-deprecated removed | :152-154 | Orca builds `WXWIN_COMPATIBILITY_3_0 0`, `_3_2 1`: port off 3.0-deprecated API |
|
||||
| `wxUSE_UNICODE=0` unsupported | :156 | none |
|
||||
| `wxUSE_STD_CONTAINERS=1` by default ("Container Classes" overview); building wx with 0 keeps the old containers | :158-161 | Orca builds with 1 → pitfall below |
|
||||
| `wxUSE_STL` gone; implicit `wxString` → `std::[w]string` only with `wxUSE_STD_STRING_CONV_IN_WXSTRING=1` at wx build time | :163-166 | Orca builds 0: convert explicitly (`into_u8`, `ToStdString`, `ToUTF8()`) |
|
||||
| MSW links `gdiplus.lib`, `msimg32.lib` | :168-172 | automatic with MSVC/wx-config; only static non-MSVC builds add them |
|
||||
| wxMotif, wxGTK1 removed | :174-175 | none |
|
||||
| Private containers (e.g. `wxSimpleDataObjectList`) removed; object arrays (`wxImageArray`) compare values in `Index()` | :177-183 | use `std::vector`/`std::list` |
|
||||
| Operators on wx types are hidden (not global) | :185-189 | pitfall below |
|
||||
| `wxString` from `std::string_view` makes `wxstr = {"Hello", 2}` ambiguous | :191-194 | write `wxString{"Hello", 2}` |
|
||||
| Generic `wxSearchCtrl` lost multi-line-only methods | :196-197 | none |
|
||||
| Wide-filename `wxOnAssert()` overload removed | :199-200 | none |
|
||||
| 64-bit DLLs carry an `x64` suffix in all build systems | :202-204 | packaging scripts matching DLL names; Orca links wx statically (Flatpak builds it shared in its own manifest) |
|
||||
| CMake config installs to `lib/cmake/wxWidgets-3.3`; plain `find_package(wxWidgets)` is unaffected, hard-coded paths break | :206-211 | Orca: `find_package(wxWidgets 3.3 CONFIG …)` on Windows/macOS, `wx-config --toolkit=gtk${SLIC3R_GTK}` on Linux (Orca's `src/CMakeLists.txt`) |
|
||||
| Memory-tracing options removed | :213-216 | use ASan |
|
||||
| `wxTEST_DIALOG()` needs a trailing `;` | :218-219 | none |
|
||||
| `wxWindow::GetDefaultBorderForControl()` not virtual | :221-223 | do not override; use `wxBORDER_THEME` |
|
||||
| GTK `wxDirButton::Create()` lost `wildcard` | :225-226 | none |
|
||||
| Several virtuals take `wxReadOnlyDC` | :228-231 | pitfall below |
|
||||
| `wxSizer::Detach()` takes `wxWindowBase*` | :233-236 | only custom sizer subclasses |
|
||||
| `wx/cursor.h` no longer includes `wx/utils.h` | :238-240 | include `<wx/utils.h>` explicitly (8248b06337 added it to `GLCanvas3D.cpp`) |
|
||||
| `wxStyledTextCtrl::AddSelection()` returns void | :242-244 | none: `wxUSE_STC=OFF` |
|
||||
| `wxColour` from `bool` no longer compiles | :246-248 | use the RGB or string ctor explicitly |
|
||||
| `wxGLCanvas::CreateSurface()` removed from EGL builds | :250-252 | none: wx chooses EGL or GLX itself (§7) |
|
||||
| 3.0-deprecated symbols disabled by default (`WXWIN_COMPATIBILITY_3_0=1` at wx build time re-enables them), 2.8-deprecated removed | :184-186 | Orca builds `WXWIN_COMPATIBILITY_3_0 0`, `_3_2 1`: port off 3.0-deprecated API |
|
||||
| `wxUSE_UNICODE=0` unsupported | :188 | none |
|
||||
| `wxUSE_STD_CONTAINERS=1` by default ("Container Classes" overview); building wx with 0 keeps the old containers | :190-193 | Orca builds with 1 → pitfall below |
|
||||
| `wxUSE_STL` gone; implicit `wxString` → `std::[w]string` only with `wxUSE_STD_STRING_CONV_IN_WXSTRING=1` at wx build time | :195-198 | Orca builds 0: convert explicitly (`into_u8`, `ToStdString`, `ToUTF8()`) |
|
||||
| MSW links `gdiplus.lib`, `msimg32.lib` | :200-204 | automatic with MSVC/wx-config; only static non-MSVC builds add them |
|
||||
| wxMotif, wxGTK1 removed | :206-207 | none |
|
||||
| Private containers (e.g. `wxSimpleDataObjectList`) removed; object arrays (`wxImageArray`) compare values in `Index()` | :209-215 | use `std::vector`/`std::list` |
|
||||
| Operators on wx types are hidden (not global) | :217-221 | pitfall below |
|
||||
| `wxString` from `std::string_view` makes `wxstr = {"Hello", 2}` ambiguous | :223-226 | write `wxString{"Hello", 2}` |
|
||||
| Generic `wxSearchCtrl` lost multi-line-only methods | :228-229 | none |
|
||||
| Wide-filename `wxOnAssert()` overload removed | :231-232 | none |
|
||||
| 64-bit DLLs carry an `x64` suffix in all build systems | :234-236 | packaging scripts matching DLL names; Orca links wx statically (Flatpak builds it shared in its own manifest) |
|
||||
| CMake config installs to `lib/cmake/wxWidgets-3.3`; plain `find_package(wxWidgets)` is unaffected, hard-coded paths break | :238-243 | Orca: `find_package(wxWidgets 3.3 CONFIG …)` on Windows/macOS, `wx-config --toolkit=gtk${SLIC3R_GTK}` on Linux (Orca's `src/CMakeLists.txt`) |
|
||||
| Memory-tracing options removed | :245-248 | use ASan |
|
||||
| `wxTEST_DIALOG()` needs a trailing `;` | :250-251 | none |
|
||||
| `wxWindow::GetDefaultBorderForControl()` not virtual | :253-255 | do not override; use `wxBORDER_THEME` |
|
||||
| GTK `wxDirButton::Create()` lost `wildcard` | :257-258 | none |
|
||||
| Several virtuals take `wxReadOnlyDC` | :260-263 | pitfall below |
|
||||
| `wxSizer::Detach()` takes `wxWindowBase*` | :265-268 | only custom sizer subclasses |
|
||||
| `wx/cursor.h` no longer includes `wx/utils.h` | :270-272 | include `<wx/utils.h>` explicitly (8248b06337 added it to `GLCanvas3D.cpp`) |
|
||||
| `wxStyledTextCtrl::AddSelection()` returns void | :274-276 | none: `wxUSE_STC=OFF` |
|
||||
| `wxColour` from `bool` no longer compiles | :278-280 | use the RGB or string ctor explicitly |
|
||||
| `wxGLCanvas::CreateSurface()` removed from EGL builds | :282-284 | none: wx chooses EGL or GLX itself (§7) |
|
||||
|
||||
**Pitfalls**
|
||||
|
||||
@@ -366,7 +378,7 @@ change, its line, and what it means for Orca.
|
||||
// Wrong: wxSize GetToolSize(wxDC& dc, wxWindow* w, const wxAuiToolBarItem& it); // never called
|
||||
// Right: wxSize GetToolSize(wxReadOnlyDC& dc, wxWindow* w, const wxAuiToolBarItem& it) override;
|
||||
```
|
||||
Cite: `docs/changes.txt:228-231`; `painting-custom-widgets.md`.
|
||||
Cite: `docs/changes.txt:260-263`; `painting-custom-widgets.md`.
|
||||
|
||||
- **Rule:** With `wxUSE_STD_CONTAINERS=1`, build a `wxArrayString` with `Add()` or an initializer
|
||||
list, and walk `WX_DECLARE_LIST` lists with `compatibility_iterator` or range-for.
|
||||
@@ -386,7 +398,7 @@ change, its line, and what it means for Orca.
|
||||
`wchar_t`, `std::string` or `std::wstring`.
|
||||
**Why:** wx operators are hidden friends now, found only by argument-dependent lookup on a wx type;
|
||||
"preventing them from implicitly being used with types convertible to wx types"
|
||||
(`changes.txt:185-189`). `char + std::wstring + …` compiled under 3.1.5 through the global
|
||||
(`changes.txt:217-221`). `char + std::wstring + …` compiled under 3.1.5 through the global
|
||||
`operator+(char, const wxString&)`, converting the `std::wstring` implicitly; under 3.3 that
|
||||
operator is a hidden friend (`include/wx/string.h:2150`) and no operand is a `wxString`, so it
|
||||
does not.
|
||||
@@ -413,9 +425,9 @@ change, its line, and what it means for Orca.
|
||||
|
||||
## 5 3.3.0 notable changes
|
||||
|
||||
`changes.txt:380-592` (relative to 3.2.8).
|
||||
`changes.txt:573-785` (relative to 3.2.8).
|
||||
|
||||
**Major changes** (:385-394)
|
||||
**Major changes** (:578-587)
|
||||
|
||||
| Change | Orca relevance |
|
||||
|---|---|
|
||||
@@ -429,7 +441,7 @@ change, its line, and what it means for Orca.
|
||||
| Native GTK file dialogs when possible (#24486, #25104) | the portal dialog is used only with GTK ≥ 3.20 at runtime, without `wxFD_PREVIEW` and without an extra control [source] (`src/gtk/filedlg.cpp:265-273, 438-443`); Orca's `CheckboxFileDialog` (`SetExtraControlCreator`, `GUI_Utils.hpp`) therefore gets the non-native GTK dialog |
|
||||
| Native `wxTextCtrl` contents / RTF (#24626, #24912) | available (`GetRTFValue`, `SearchText`) |
|
||||
|
||||
**All** (:398-442)
|
||||
**All** (:591-635)
|
||||
|
||||
| Change | Orca relevance |
|
||||
|---|---|
|
||||
@@ -439,7 +451,7 @@ change, its line, and what it means for Orca.
|
||||
| Environment variables use UTF-8 (#25101) | check round-tripping of non-ASCII paths through `wxGetEnv`/`wxSetEnv` |
|
||||
| Improved locale matching (#24855); thread-safe `wxPlatformInfo::Get()` (#25459); `wxXmlParseError` from `wxXmlDocument::Load()` (#24215); customisable error exit code (#24770) | available |
|
||||
|
||||
**All (GUI)** (:444-500)
|
||||
**All (GUI)** (:637-693)
|
||||
|
||||
| Change | Orca relevance |
|
||||
|---|---|
|
||||
@@ -452,17 +464,17 @@ change, its line, and what it means for Orca.
|
||||
| Non-live resize restored in wxAUI and `wxSplitterWindow` (#24193) | `wxAUI_MGR_LIVE_RESIZE` is in `wxAUI_MGR_DEFAULT` since 3.3.0 (`interface/wx/aui/framemanager.h:59-66`). The style table's "always enabled in wxGTK3 and wxOSX ports as non-live resizing is not implemented in them" (:199-206) is as stale as the `AlwaysUsesLiveResize()` note: that function "always returns false" as of 3.3.0 (:345; `src/aui/framemanager.cpp:711-714`), and the flag decides on every port [source] (`HasLiveResize`, :716-719). See `webview-gl-aui-media.md` §AUI docking |
|
||||
| `wxInfoBar::ShowCheckBox()` (#25394); printing multiple page ranges (#25030); `wxGrid::CopySelection()` (#24124); new default flat AUI tab art (#25316); `wxApp::SetAppearance()` (#24461) | available |
|
||||
|
||||
**All (WebView)** (:510-525) — `wxWebViewConfiguration` + `GetNativeConfiguration()`, `SetProxy()`,
|
||||
**All (WebView)** (:703-718) — `wxWebViewConfiguration` + `GetNativeConfiguration()`, `SetProxy()`,
|
||||
`ShowDevTools()`, `EnablePersistentStorage()`, `EnableBrowserAcceleratorKeys()`, clearing browsing
|
||||
data, advanced requests, child-window handling, `IsTargetMainFrame()`, Edge user agent settable after
|
||||
creation, and **Edge events queued** (#22744, #19075): Edge handlers run later than on the other
|
||||
backends. Edge posts its events with `AddPendingEvent` (script messages: `src/msw/webview_edge.cpp:811`)
|
||||
except the vetoable ones, `wxEVT_WEBVIEW_NAVIGATING` (:599) and `wxEVT_WEBVIEW_NEWWINDOW` with its
|
||||
`NEWWINDOW_FEATURES` follow-up (:723, :737), which stay synchronous; WebKit and
|
||||
backends. Edge posts its events with `AddPendingEvent` (script messages: `src/msw/webview_edge.cpp:872`)
|
||||
except the vetoable ones, `wxEVT_WEBVIEW_NAVIGATING` (:655-662) and `wxEVT_WEBVIEW_NEWWINDOW` with its
|
||||
`NEWWINDOW_FEATURES` follow-up (:783-785, :796-798), which stay synchronous; WebKit and
|
||||
WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:1360`,
|
||||
`src/gtk/webview_webkit2.cpp:408`) [source]. `webview-gl-aui-media.md` owns the details.
|
||||
|
||||
**wxGTK** (:527-547)
|
||||
**wxGTK** (:720-740)
|
||||
|
||||
| Change | Orca relevance |
|
||||
|---|---|
|
||||
@@ -477,46 +489,53 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
| `wxDC::DrawRoundedRectangle()` radius limited to half the smaller side (#24327) | the clamp is in the GTK2 GDK DC (`src/gtk/dcclient.cpp:874-875`, built only in the GTK2 opt-out, `GTK2_LOWLEVEL_SRC` in `build/files`) and also in the common `wxGraphicsPathData::AddRoundedRectangle` (`src/common/graphcmn.cpp:439-440`, absent in 3.1.5) that `wxGraphicsContext::DrawRoundedRectangle` uses, so every `wxGCDC` clamps: GTK3 (Cairo) and macOS window DCs, and Orca's memory-DC + `wxGCDC` paint paths on all ports [source]. A radius larger than half the smaller side is now clamped instead of drawing overlapping arcs |
|
||||
| Read-only `wxBitmapComboBox` height fixed (#25468) | `Slic3r::GUI::BitmapComboBox` on GTK |
|
||||
|
||||
**wxMSW** (:549-583)
|
||||
**wxMSW** (:742-776)
|
||||
|
||||
| Change | Orca relevance |
|
||||
|---|---|
|
||||
| "Enable double buffering for all windows" (#22851) | **reverted in 3.3.2** (#25808) → pitfall below |
|
||||
| `wxOverlay` reimplemented with layered windows (#23261) | none: no `wxOverlay` |
|
||||
| `wxBG_STYLE_TRANSPARENT` implemented (#23412) | as `WS_EX_TRANSPARENT` on non-TLW children [source] (`src/msw/window.cpp:1581-1582`); set before `Create()` (`painting-custom-widgets.md`) |
|
||||
| `wxCAPTION` turned on when min/max/close boxes are set (#23575) | `WS_CAPTION` is added to the style (`src/msw/toplevel.cpp:132-135`); origin of the MainFrame workaround (§8) |
|
||||
| `wxCAPTION` turned on when min/max/close boxes are set (#23575) | `WS_CAPTION` is added to the style (`src/msw/toplevel.cpp:132-135`); origin of the MainFrame workaround (§10) |
|
||||
| `wxButton` default size larger in high DPI (#25297) | raw `wxButton` layouts may grow; Orca dialogs use `Button`/`DialogButtons` |
|
||||
| Markup in `wxStaticText` (#25000); `wxHyperlinkCtrl` colour changeable (#23549) | `SetLabelMarkup` now works on MSW (single line) |
|
||||
| Extended-length paths (#25033); `wxFileDialog` no unwanted extension (#24949); UTF-8 build fixes (#23313); non-BMP strings (#25128) | available |
|
||||
| `wxDisplay` invalidated on display change (#25396); TLW with one child resized on DPI change (#22983); Aero-snapped geometry saved | multi-monitor geometry |
|
||||
| Modern default `wxTreeCtrl` look (#23844); RTL fixes for `wxOverlay`/`wxScrolled` (#25413) and GDI+ (#25431); `wxBitmap::UseAlpha()` returns `bool` (#23919) | available |
|
||||
|
||||
**wxOSX** (:585-592) — `wxEventLoop::OnExit()` is always called (#25409); TLW cursor setting fixed
|
||||
**wxOSX** (:778-785) — `wxEventLoop::OnExit()` is always called (#25409); TLW cursor setting fixed
|
||||
(#25131); Cmd-C no longer activates a "Close" button (#25346); `wxCursor` loadable from resources
|
||||
(#24374); `wxUIActionSimulator` works (#23692), usable for GUI tests.
|
||||
|
||||
**Pitfalls**
|
||||
|
||||
- **Rule:** Do not replace Orca's MSW dark mode with wx's (`SetAppearance`/`MSWEnableDarkMode`)
|
||||
unless live theme switching is kept.
|
||||
**Why:** wx's MSW dark mode cannot change once any top-level window exists or a mode was chosen:
|
||||
`SetAppearance` returns `CannotChange` (`src/msw/darkmode.cpp:263-270`;
|
||||
`interface/wx/app.h:1166-1173`). TaskDialog-based dialogs (`wxMessageDialog`, `wxProgressDialog`,
|
||||
simple `wxAboutBox`), the common dialogs (colour, find/replace, font, page setup, print) and the
|
||||
date/time/calendar controls stay light (`interface/wx/app.h:1434-1448`). Orca switches themes at
|
||||
runtime, which is why 8248b06337 kept NppDarkMode and only informs wx with
|
||||
`MSWEnableDarkMode(DarkMode_Auto)` (§8).
|
||||
- **Rule:** Orca keeps its own Windows theming (`NppDarkMode`) and only informs wx with
|
||||
`MSWEnableDarkMode(DarkMode_Auto)`; do not replace it with wx's dark mode without accounting for the
|
||||
chrome NppDarkMode themes itself.
|
||||
**Why:** when 8248b06337 landed (3.3.2), wx's MSW dark mode could not be changed once a top-level
|
||||
window existed — `SetAppearance` returned `CannotChange` — so a live Preferences toggle would have
|
||||
been restart-only. That blocker is gone: 3.3.3 (#26516) and 3.3.4 (#26734) made the mode switchable
|
||||
at runtime. `MSWEnableDarkMode()` re-applies the mode to an existing window (sends it
|
||||
`WM_SYSCOLORCHANGE`, `src/msw/darkmode.cpp:345-349`), controls restyle through
|
||||
`wxMSWDarkMode::HasChanged()`/`NotifySysColorChange()` (`src/msw/window.cpp:5337, 5528-5534`), and
|
||||
`SetAppearance()` returns only `Ok`/`Failure`; `AppearanceResult::CannotChange` is no longer
|
||||
returned (`src/msw/darkmode.cpp:289-375`; `interface/wx/app.h:1151, 1179-1183`). The remaining
|
||||
documented limits are the date/time/calendar controls, `wxPrintDialog` on Windows 10 and MDI
|
||||
applications (`interface/wx/app.h:1442-1448`); `wxMessageDialog` (3.3.3, #26570) and the common
|
||||
dialogs (3.3.4, #26780) now do support dark mode. Orca still keeps NppDarkMode because it themes
|
||||
Orca's own chrome (title bars, explorer theme, scrollbars, list headers) and drives the live
|
||||
theme-switch path (§10).
|
||||
Cite: 8248b06337 (PR text); `colours-dark-mode.md`.
|
||||
|
||||
- **Rule:** On MSW, a custom-painted control buffers its own drawing (`wxAutoBufferedPaintDC`/
|
||||
`wxBufferedPaintDC` with `wxBG_STYLE_PAINT`, or the Orca memory-DC + `wxGCDC` path), or calls
|
||||
`SetDoubleBuffered(true)` after creation.
|
||||
**Why:** 3.3.0's global `WS_EX_COMPOSITED` was reverted in 3.3.2 (`changes.txt:308`). In 3.3.2
|
||||
**Why:** 3.3.0's global `WS_EX_COMPOSITED` was reverted in 3.3.2 (`changes.txt:501`). In 3.3.4
|
||||
nothing sets it except an explicit `SetDoubleBuffered(true)` [source] (`src/msw/window.cpp:4704-4721`;
|
||||
the only other use is `MSWDisableComposited`, :1643-1652), so MSW windows are not double-buffered by
|
||||
default, exactly as in 3.1.5. `wxAutoBufferedPaintDC` is a `wxBufferedPaintDC` on MSW at compile
|
||||
time (`include/wx/dcbuffer.h:18-23, 215-221`). Nothing tuned against 3.3.0/3.3.1 applies.
|
||||
Cite: `docs/changes.txt:308, 557`; `painting-custom-widgets.md`.
|
||||
Cite: `docs/changes.txt:501, 750`; `painting-custom-widgets.md`.
|
||||
|
||||
- **Rule:** A `wxEVT_DPI_CHANGED` handler must be correct on GTK3, and every handler you bind — on a
|
||||
child, a control or a `DPIDialog`/`DPIFrame` — calls `Skip()`.
|
||||
@@ -529,11 +548,11 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
ctor starts at 1 because `get_dpi_for_window` returns 96 on Linux). Double scaling when a window moves between monitors of
|
||||
different scale is a risk that has not been verified at runtime; test DPI changes on GTK when
|
||||
touching `DPIAware::rescale` paths.
|
||||
Cite: `docs/changes.txt:541`; `dpi-bitmaps-fonts.md` §wxEVT_DPI_CHANGED.
|
||||
Cite: `docs/changes.txt:734`; `dpi-bitmaps-fonts.md` §wxEVT_DPI_CHANGED.
|
||||
|
||||
## 6 3.3.1 notable fixes
|
||||
|
||||
`changes.txt:333-377`.
|
||||
`changes.txt:526-570`.
|
||||
|
||||
| Port | Change | Orca relevance |
|
||||
|---|---|---|
|
||||
@@ -547,7 +566,7 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
|
||||
## 7 3.3.2 notable changes
|
||||
|
||||
`changes.txt:255-318`, relative to 3.2.10 (see §1 for the unlisted 3.2.9/3.2.10 fixes).
|
||||
`changes.txt:448-511`, relative to 3.2.10 (see §1 for the unlisted 3.2.9/3.2.10 fixes).
|
||||
|
||||
| Port | Change | Orca relevance |
|
||||
|---|---|---|
|
||||
@@ -589,7 +608,7 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
// Wrong: m_static_valid->SetLabel(info_line); m_static_valid->Wrap(FromDIP(300));
|
||||
// Right: m_static_valid->SetLabel(info_line); m_static_valid->Wrap(-1); m_static_valid->Wrap(FromDIP(300));
|
||||
```
|
||||
Cite: `docs/changes.txt:280`; `sizers-layout.md` §wxStaticText wrapping.
|
||||
Cite: `docs/changes.txt:473`; `sizers-layout.md` §wxStaticText wrapping.
|
||||
|
||||
- **Rule:** On Linux/X11, call `wxGLCanvas::PreferGLX()` before any GL use, attribute objects
|
||||
included; set a swap interval explicitly if the canvas needs VSync.
|
||||
@@ -605,7 +624,7 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
```cpp
|
||||
// Right (if frame pacing is wanted): canvas->SetSwapInterval(1); // before the first SwapBuffers
|
||||
```
|
||||
Cite: `docs/changes.txt:275-276, 292`; `webview-gl-aui-media.md` §EGL vs GLX.
|
||||
Cite: `docs/changes.txt:468-469, 485`; `webview-gl-aui-media.md` §EGL vs GLX.
|
||||
|
||||
- **Rule:** Do not count clicks from `wxEVT_LEFT_DCLICK` alone on macOS; handle `DOWN` and `DCLICK`
|
||||
as on MSW.
|
||||
@@ -613,13 +632,68 @@ WebKit2GTK deliver script messages synchronously (`src/osx/webview_webkit.mm:136
|
||||
(left and right buttons), so a triple click gives `DOWN, DCLICK, DOWN` as on MSW; previously every
|
||||
click with `clickCount > 1` was a `DCLICK` [source] (`src/osx/cocoa/window.mm:4103-4150`). Per-platform click-count ifdefs
|
||||
written for 3.1.5 need rechecking.
|
||||
Cite: `docs/changes.txt:316`; `mouse-keyboard-focus.md`.
|
||||
Cite: `docs/changes.txt:509`; `mouse-keyboard-focus.md`.
|
||||
|
||||
## 8 Migration already done in Orca
|
||||
## 8 3.3.3 notable changes
|
||||
|
||||
The upgrade landed as 8248b06337 ("Updated wxWidgets to 3.3.2", #12941; build system 2d7e26292b).
|
||||
Its PR kept Orca's own MSW dark mode to avoid broader changes and because wx's needs an app restart to
|
||||
switch. Each row is a rule for new code; the owning file has the detail.
|
||||
`changes.txt:388-445`, relative to 3.2.11 (see §1 for the unlisted 3.2.10/3.2.11 fixes).
|
||||
|
||||
| Port | Change | Orca relevance |
|
||||
|---|---|---|
|
||||
| All | `wxMoveToTrash()` (#26256); `wxSizer::DetachItem()` (#26512); truncated reads are errors in `wxDataInputStream` (#26600); `wxGetOsDescription()` (#26231); C++20 `<=>` for `wxString` (#26306) | available; Orca detaches windows and has its own file deletion |
|
||||
| All | **`wxGetTranslation()` returns `const wxString&` again**, reverting 3.3.2's by-value change | the by-value rule is retired → §3 pitfall |
|
||||
| GUI | `wxWebView::Print()` print settings (#26239) and `PrintToPDF()` (#26583); `wxWebViewConfiguration::DisableGPUAcceleration()` (#26626) | `webview-gl-aui-media.md` |
|
||||
| GUI | `wxGrid::GetFrozen{Row,Col}LabelWindow()` (#26617); `wxSVGFileDC` accessibility (#26379) and `GetSVGDocument()` (#26344) | `controls-dataview.md`; `wxSVGFileDC` available |
|
||||
| wxGTK | Fix regression when using `wxImageList` in high DPI (#26349) | the physical-pixel image-list rule is unchanged (§3) |
|
||||
| wxGTK | Fix `wxStaticText` label wrapping | the base `Wrap()` cache is unchanged (§7); only the GTK label wrapping was fixed |
|
||||
| wxGTK | Assert when the clipboard has non-ASCII targets fixed (#26263); GTK-without-Wayland build fixed (#26269); high-DPI bitmaps in `wxAboutBox` (#22192) | clipboard |
|
||||
| wxMSW | **Light/dark mode switching implemented** (#26516) | see §5: this removes the old "cannot switch at runtime" blocker |
|
||||
| wxMSW | `wxMessageDialog` dark mode (#26570); combo/listbox dark mode on Windows 11 (#26535); `wxCheckBox` label in screen readers (#26270); `wxPD_CAN_SKIP` regression (#26287); Direct2D text regression (#26259) | dark-mode and accessibility fixes |
|
||||
| wxMSW | Stylus events (#26223); colour emoji via Direct2D (#26657) | available |
|
||||
| wxOSX | Data-view icons under macOS 26 (#26374); `wxOverlay` phantoms in Mission Control (#26380); `wxEVT_DATAVIEW_ITEM_EDITING_DONE` value set (#26367); Xcode project for macOS 27 (#26578) | native look and data view |
|
||||
|
||||
## 9 3.3.4 notable changes
|
||||
|
||||
`changes.txt:295-385`, relative to 3.2.11 (see §1 for the unlisted 3.2.11/3.2.12 fixes).
|
||||
|
||||
| Port | Change | Orca relevance |
|
||||
|---|---|---|
|
||||
| All | `wxString` usable with `{fmt}`/`std::format()` (#27180); `wxPATH_RMDIR_PARENTS`; `fsync()` in `wxTempFile` (#27001); `wxDateTime::GetAsDOS()` after 2038 (#4393); TCP `wxIPC` fixes (#24858) | available |
|
||||
| GUI | **Accelerators take priority over the focused window in all ports** (#22630), with the new `wxEVT_ACCELERATOR_KEY` event and the `wxWindow::ClaimsKeyBeforeAccelerator()` override that text controls use to reserve their editing keys (`interface/wx/event.h:1799`, `interface/wx/window.h:4580`) | pitfall below; `mouse-keyboard-focus.md` |
|
||||
| GUI | wxGrid: `wxGridCellChoiceEditor` UI fixes (#12094), best size for auto-wrapped rows (#14072), `MakeCellVisible()` with variable row heights (#4371), editor-change crash (#21986) | `controls-dataview.md`; the choice-editor `Combo()` cast rule is unchanged |
|
||||
| GUI | AUI: no spurious sash jump on click (#4547); an added pane's best size is respected (#4404) | Plater docking |
|
||||
| GUI | `wxListCtrl` (#15411) and `wxStatusBar` (#24305) accessibility; `wxAuiNotebook` selection after a page removal (#9920); `wxPreviewCanvas` crash (#9822); generic `wxCalendarCtrl` background colour (#21885); LunaSVG with filters (#27176) | available; no `wxAuiNotebook` in Orca |
|
||||
| wxMSW | **Dark mode can be enabled dynamically** (#26734); dark mode for `wxFontPickerCtrl` (#26667), `wxNotebook` (#26694, #26695), `wxSpinButton` (#26682, #26683) and the common dialogs (#26780) | §5 pitfall; `colours-dark-mode.md` |
|
||||
| wxMSW | `wxRenameFile()` no longer copies file attributes (`changes.txt:345-347`, incompatible); Esc closes dialogs used by IME/auto-completion (#16059, #27145); IME handling in wxGrid improved (#24558); `wxPersistent` controls DPI-aware (#18752); non-BMP character input (#27016) | file dialogs, keyboard and IME |
|
||||
| wxGTK | Wayland: crash on pointer/seat disconnect fixed (#27069); **AUI panes draggable via system drag sessions** (#26969); **window geometry restorable** via XDG session management (#26324); overlay-scrollbar client size (#26889) | the Wayland gaps are partly narrowed; `webview-gl-aui-media.md` §AUI |
|
||||
| wxOSX | `wxEVT_CHAR` key codes fixed for events with Ctrl (#26810); context-menu accessibility (#13010); custom controls in sandboxed `wxFileDialog` (#26908) | `mouse-keyboard-focus.md`; macOS keys |
|
||||
|
||||
**Pitfalls**
|
||||
|
||||
- **Rule:** On every port an accelerator now runs before the focused window handles the key, unless
|
||||
that window claims the key; a custom control that must keep a key over an accelerator overrides
|
||||
`wxWindow::ClaimsKeyBeforeAccelerator()`, or handles `wxEVT_ACCELERATOR_KEY` and calls
|
||||
`UseAccelerator()`.
|
||||
**Why:** before 3.3.4 only wxGTK let the focused window handle the key first; the other ports
|
||||
already gave accelerators priority. 3.3.4 made every port consistent and added the
|
||||
`wxEVT_ACCELERATOR_KEY` event, sent after `wxEVT_CHAR_HOOK` (before it on macOS) to the focus
|
||||
window and propagated to its parents (`interface/wx/event.h:1740-1801`;
|
||||
`interface/wx/window.h:4554-4583`). Text controls, `wxComboBox` and `wxSpinCtrl` reserve their
|
||||
editing keys by overriding `ClaimsKeyBeforeAccelerator()` and returning
|
||||
`wxTextEntryBase::IsUsedForEditing()` (`src/common/textcmn.cpp:136-140`;
|
||||
`src/common/textentrycmn.cpp:441-509`; `src/common/spinctrlcmn.cpp:160-167`;
|
||||
`src/msw/combobox.cpp:389-395`, `src/gtk/combobox.cpp:205-211`), and the GTK accelerator walk now
|
||||
consults it (`src/gtk/window.cpp:1524-1539`). Orca's topbar menus are popups whose accelerators are
|
||||
display-only and Orca dispatches its own shortcuts, so few sites are affected; the macOS
|
||||
`ObjectList` `wxAcceleratorTable` and the wxInspector table are the live ones.
|
||||
Cite: `docs/changes.txt:321`; `mouse-keyboard-focus.md` §Accelerators.
|
||||
|
||||
## 10 Migration already done in Orca
|
||||
|
||||
The upgrade landed as 8248b06337 ("Updated wxWidgets to 3.3.2", #12941; build system 2d7e26292b) and
|
||||
the pin later advanced to upstream 3.3.4. Its PR kept Orca's own MSW dark mode to avoid broader
|
||||
changes; wx could then only switch at app start, so a live Orca toggle needed NppDarkMode. Each row is
|
||||
a rule for new code; the owning file has the detail.
|
||||
|
||||
| Commit | Rule for new code | Where | Owner |
|
||||
|---|---|---|---|
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
diff --git a/build/cmake/wxWidgetsConfig.cmake.in b/build/cmake/wxWidgetsConfig.cmake.in
|
||||
index 2f3a735d920c..2593c045b89b 100644
|
||||
--- a/build/cmake/wxWidgetsConfig.cmake.in
|
||||
+++ b/build/cmake/wxWidgetsConfig.cmake.in
|
||||
@@ -50,12 +50,28 @@ if(WIN32_MSVC_NAMING)
|
||||
set(wxARCH_SUFFIX "_${wxPLATFORM_ARCH}")
|
||||
endif()
|
||||
|
||||
- # use wxWidgets_USE_STATIC to force static libraries, otherwise shared is searched first
|
||||
- if(NOT wxWidgets_USE_STATIC AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}_dll/@PROJECT_NAME@Targets.cmake")
|
||||
- set(wxPLATFORM_LIB_DIR "/${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}_dll")
|
||||
- elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}_lib/@PROJECT_NAME@Targets.cmake")
|
||||
- set(wxPLATFORM_LIB_DIR "/${wxCOMPILER_PREFIX}${wxARCH_SUFFIX}_lib")
|
||||
+ # wxCOMPILER_PREFIX names the consuming compiler; the installed layout is named
|
||||
+ # after the compiler that built wxWidgets. cl and clang-cl share an ABI, so
|
||||
+ # either can consume either build.
|
||||
+ set(wxCOMPILER_PREFIXES "${wxCOMPILER_PREFIX}")
|
||||
+ if(wxCOMPILER_PREFIX STREQUAL "clang")
|
||||
+ list(APPEND wxCOMPILER_PREFIXES "vc")
|
||||
+ elseif(wxCOMPILER_PREFIX STREQUAL "vc")
|
||||
+ list(APPEND wxCOMPILER_PREFIXES "clang")
|
||||
endif()
|
||||
+
|
||||
+ # use wxWidgets_USE_STATIC to force static libraries, otherwise shared is searched first
|
||||
+ foreach(wxPREFIX IN LISTS wxCOMPILER_PREFIXES)
|
||||
+ if(NOT wxWidgets_USE_STATIC AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/${wxPREFIX}${wxARCH_SUFFIX}_dll/@PROJECT_NAME@Targets.cmake")
|
||||
+ set(wxPLATFORM_LIB_DIR "/${wxPREFIX}${wxARCH_SUFFIX}_dll")
|
||||
+ break()
|
||||
+ elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${wxPREFIX}${wxARCH_SUFFIX}_lib/@PROJECT_NAME@Targets.cmake")
|
||||
+ set(wxPLATFORM_LIB_DIR "/${wxPREFIX}${wxARCH_SUFFIX}_lib")
|
||||
+ break()
|
||||
+ endif()
|
||||
+ endforeach()
|
||||
+ unset(wxPREFIX)
|
||||
+ unset(wxCOMPILER_PREFIXES)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}${wxPLATFORM_LIB_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
Vendored
+8
-2
@@ -28,12 +28,18 @@ if (APPLE)
|
||||
COMMAND ${GIT_EXECUTABLE} apply --verbose
|
||||
${CMAKE_CURRENT_LIST_DIR}/0001-macos-use-srgb-colour-components.patch
|
||||
)
|
||||
elseif (WIN32)
|
||||
set(_wx_patch_command
|
||||
${GIT_EXECUTABLE} checkout -f -- build/cmake/wxWidgetsConfig.cmake.in
|
||||
COMMAND ${GIT_EXECUTABLE} apply --verbose
|
||||
${CMAKE_CURRENT_LIST_DIR}/0002-clang-cl-sibling-compiler-prefix.patch
|
||||
)
|
||||
endif ()
|
||||
|
||||
orcaslicer_add_cmake_project(
|
||||
wxWidgets
|
||||
GIT_REPOSITORY "https://github.com/SoftFever/Orca-deps-wxWidgets"
|
||||
GIT_TAG v3.3.2
|
||||
GIT_REPOSITORY "https://github.com/wxWidgets/wxWidgets"
|
||||
GIT_TAG v3.3.4
|
||||
GIT_SHALLOW ON
|
||||
GIT_SUBMODULES 3rdparty/catch 3rdparty/pcre 3rdparty/libwebp
|
||||
PATCH_COMMAND ${_wx_patch_command}
|
||||
|
||||
+674
-230
File diff suppressed because it is too large
Load Diff
+1006
-340
File diff suppressed because it is too large
Load Diff
+1003
-337
File diff suppressed because it is too large
Load Diff
+1002
-336
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1001
-335
File diff suppressed because it is too large
Load Diff
+1003
-337
File diff suppressed because it is too large
Load Diff
+1005
-339
File diff suppressed because it is too large
Load Diff
+1007
-341
File diff suppressed because it is too large
Load Diff
+1001
-332
File diff suppressed because it is too large
Load Diff
+1013
-347
File diff suppressed because it is too large
Load Diff
+1009
-343
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1012
-346
File diff suppressed because it is too large
Load Diff
+1000
-334
File diff suppressed because it is too large
Load Diff
+1006
-340
File diff suppressed because it is too large
Load Diff
+1006
-340
File diff suppressed because it is too large
Load Diff
+1009
-343
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Anker",
|
||||
"version": "02.04.00.05",
|
||||
"version": "02.04.00.06",
|
||||
"force_update": "0",
|
||||
"description": "Anker configurations",
|
||||
"machine_model_list": [
|
||||
@@ -304,6 +304,26 @@
|
||||
"name": "Generic PLA Silk @Anker 0.25 nozzle",
|
||||
"sub_path": "filament/Generic PLA Silk @Anker 0.25 nozzle.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Basic @Anker base",
|
||||
"sub_path": "filament/AnkerMake PLA+ Basic @Anker base.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Glitter @Anker base",
|
||||
"sub_path": "filament/AnkerMake PLA+ Glitter @Anker base.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Matte @Anker base",
|
||||
"sub_path": "filament/AnkerMake PLA+ Matte @Anker base.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Metallic @Anker base",
|
||||
"sub_path": "filament/AnkerMake PLA+ Metallic @Anker base.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Silk @Anker base",
|
||||
"sub_path": "filament/AnkerMake PLA+ Silk @Anker base.json"
|
||||
},
|
||||
{
|
||||
"name": "Generic PLA+ @Anker",
|
||||
"sub_path": "filament/Generic PLA+ @Anker.json"
|
||||
@@ -327,6 +347,26 @@
|
||||
{
|
||||
"name": "Generic TPU @Anker",
|
||||
"sub_path": "filament/Generic TPU @Anker.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Basic @Anker",
|
||||
"sub_path": "filament/AnkerMake PLA+ Basic @Anker.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Glitter @Anker",
|
||||
"sub_path": "filament/AnkerMake PLA+ Glitter @Anker.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Matte @Anker",
|
||||
"sub_path": "filament/AnkerMake PLA+ Matte @Anker.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Metallic @Anker",
|
||||
"sub_path": "filament/AnkerMake PLA+ Metallic @Anker.json"
|
||||
},
|
||||
{
|
||||
"name": "AnkerMake PLA+ Silk @Anker",
|
||||
"sub_path": "filament/AnkerMake PLA+ Silk @Anker.json"
|
||||
}
|
||||
],
|
||||
"machine_list": [
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Basic @Anker base",
|
||||
"inherits": "Generic PLA+ @Anker base",
|
||||
"from": "system",
|
||||
"filament_id": "OFUuZlQL",
|
||||
"instantiation": "false",
|
||||
"filament_vendor": [
|
||||
"AnkerMake"
|
||||
],
|
||||
"nozzle_temperature": [
|
||||
"200"
|
||||
],
|
||||
"nozzle_temperature_initial_layer": [
|
||||
"230"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"hot_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"filament_flow_ratio": [
|
||||
"1"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"fan_cooling_layer_time": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_layer_time": [
|
||||
"8"
|
||||
],
|
||||
"slow_down_min_speed": [
|
||||
"30"
|
||||
],
|
||||
"default_filament_colour": [
|
||||
"#FFFFFF"
|
||||
],
|
||||
"filament_max_volumetric_speed": [
|
||||
"22"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Basic @Anker",
|
||||
"inherits": "AnkerMake PLA+ Basic @Anker base",
|
||||
"from": "system",
|
||||
"setting_id": "EfM5rmn4w6pMBajC",
|
||||
"instantiation": "true",
|
||||
"compatible_printers": [
|
||||
"Anker M5 0.4 nozzle",
|
||||
"Anker M5 0.6 nozzle",
|
||||
"Anker M5 All-Metal 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.6 nozzle",
|
||||
"Anker M5C 0.4 nozzle",
|
||||
"Anker M5C 0.6 nozzle"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Glitter @Anker base",
|
||||
"inherits": "Generic PLA+ @Anker base",
|
||||
"from": "system",
|
||||
"filament_id": "OFxCURdg",
|
||||
"instantiation": "false",
|
||||
"filament_vendor": [
|
||||
"AnkerMake"
|
||||
],
|
||||
"nozzle_temperature": [
|
||||
"200"
|
||||
],
|
||||
"nozzle_temperature_initial_layer": [
|
||||
"230"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"hot_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"filament_flow_ratio": [
|
||||
"1"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"fan_cooling_layer_time": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_layer_time": [
|
||||
"6"
|
||||
],
|
||||
"slow_down_min_speed": [
|
||||
"30"
|
||||
],
|
||||
"default_filament_colour": [
|
||||
"#00AD66"
|
||||
],
|
||||
"filament_max_volumetric_speed": [
|
||||
"22"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Glitter @Anker",
|
||||
"inherits": "AnkerMake PLA+ Glitter @Anker base",
|
||||
"from": "system",
|
||||
"setting_id": "blGHp0htgHEj7khE",
|
||||
"instantiation": "true",
|
||||
"compatible_printers": [
|
||||
"Anker M5 0.4 nozzle",
|
||||
"Anker M5 0.6 nozzle",
|
||||
"Anker M5 All-Metal 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.6 nozzle",
|
||||
"Anker M5C 0.4 nozzle",
|
||||
"Anker M5C 0.6 nozzle"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Matte @Anker base",
|
||||
"inherits": "Generic PLA+ @Anker base",
|
||||
"from": "system",
|
||||
"filament_id": "OFKDOyNK",
|
||||
"instantiation": "false",
|
||||
"filament_vendor": [
|
||||
"AnkerMake"
|
||||
],
|
||||
"nozzle_temperature": [
|
||||
"210"
|
||||
],
|
||||
"nozzle_temperature_initial_layer": [
|
||||
"230"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"hot_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"filament_flow_ratio": [
|
||||
"1"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"fan_cooling_layer_time": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_layer_time": [
|
||||
"6"
|
||||
],
|
||||
"slow_down_min_speed": [
|
||||
"30"
|
||||
],
|
||||
"default_filament_colour": [
|
||||
"#FFFFFF"
|
||||
],
|
||||
"filament_max_volumetric_speed": [
|
||||
"22"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Matte @Anker",
|
||||
"inherits": "AnkerMake PLA+ Matte @Anker base",
|
||||
"from": "system",
|
||||
"setting_id": "tPgwC1eEXyWPOn9S",
|
||||
"instantiation": "true",
|
||||
"compatible_printers": [
|
||||
"Anker M5 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.4 nozzle",
|
||||
"Anker M5C 0.4 nozzle"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Metallic @Anker base",
|
||||
"inherits": "Generic PLA+ @Anker base",
|
||||
"from": "system",
|
||||
"filament_id": "OFBfbmtb",
|
||||
"instantiation": "false",
|
||||
"filament_vendor": [
|
||||
"AnkerMake"
|
||||
],
|
||||
"nozzle_temperature": [
|
||||
"200"
|
||||
],
|
||||
"textured_plate_temp": [
|
||||
"60"
|
||||
],
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"60"
|
||||
],
|
||||
"filament_flow_ratio": [
|
||||
"1"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"fan_cooling_layer_time": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_layer_time": [
|
||||
"6"
|
||||
],
|
||||
"slow_down_min_speed": [
|
||||
"30"
|
||||
],
|
||||
"overhang_fan_speed": [
|
||||
"50"
|
||||
],
|
||||
"reduce_fan_stop_start_freq": [
|
||||
"0"
|
||||
],
|
||||
"filament_retraction_length": [
|
||||
"1"
|
||||
],
|
||||
"filament_retraction_speed": [
|
||||
"50"
|
||||
],
|
||||
"filament_deretraction_speed": [
|
||||
"50"
|
||||
],
|
||||
"default_filament_colour": [
|
||||
"#ACAC8A"
|
||||
],
|
||||
"filament_max_volumetric_speed": [
|
||||
"20"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Metallic @Anker",
|
||||
"inherits": "AnkerMake PLA+ Metallic @Anker base",
|
||||
"from": "system",
|
||||
"setting_id": "jlbAMNNaEacdUASZ",
|
||||
"instantiation": "true",
|
||||
"compatible_printers": [
|
||||
"Anker M5 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.4 nozzle",
|
||||
"Anker M5C 0.4 nozzle"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Silk @Anker base",
|
||||
"inherits": "Generic PLA+ @Anker base",
|
||||
"from": "system",
|
||||
"filament_id": "OFkxTGQc",
|
||||
"instantiation": "false",
|
||||
"filament_vendor": [
|
||||
"AnkerMake"
|
||||
],
|
||||
"nozzle_temperature": [
|
||||
"210"
|
||||
],
|
||||
"nozzle_temperature_initial_layer": [
|
||||
"230"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp": [
|
||||
"65"
|
||||
],
|
||||
"hot_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"textured_plate_temp_initial_layer": [
|
||||
"65"
|
||||
],
|
||||
"filament_flow_ratio": [
|
||||
"1"
|
||||
],
|
||||
"close_fan_the_first_x_layers": [
|
||||
"3"
|
||||
],
|
||||
"fan_cooling_layer_time": [
|
||||
"60"
|
||||
],
|
||||
"slow_down_layer_time": [
|
||||
"2"
|
||||
],
|
||||
"slow_down_min_speed": [
|
||||
"20"
|
||||
],
|
||||
"filament_retraction_length": [
|
||||
"0.5"
|
||||
],
|
||||
"filament_retraction_speed": [
|
||||
"20"
|
||||
],
|
||||
"filament_wipe": [
|
||||
"0"
|
||||
],
|
||||
"default_filament_colour": [
|
||||
"#99ADA3"
|
||||
],
|
||||
"filament_deretraction_speed": [
|
||||
"20"
|
||||
],
|
||||
"filament_max_volumetric_speed": [
|
||||
"13"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "filament",
|
||||
"name": "AnkerMake PLA+ Silk @Anker",
|
||||
"inherits": "AnkerMake PLA+ Silk @Anker base",
|
||||
"from": "system",
|
||||
"setting_id": "eVM9Ckwjl5vEvEKN",
|
||||
"instantiation": "true",
|
||||
"compatible_printers": [
|
||||
"Anker M5 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.4 nozzle",
|
||||
"Anker M5 All-Metal 0.6 nozzle",
|
||||
"Anker M5C 0.4 nozzle",
|
||||
"Anker M5C 0.6 nozzle"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Anycubic",
|
||||
"version": "02.04.00.08",
|
||||
"version": "02.04.00.09",
|
||||
"force_update": "0",
|
||||
"description": "Anycubic configurations",
|
||||
"machine_model_list": [
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"default_filament_profile": [
|
||||
"Generic PLA @Anycubic"
|
||||
],
|
||||
"machine_start_gcode": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG0 Z0.2 F1800 ; move nozzle to print position\nG92 E0 ; specify current extruder position as zero\nG1 Y10 X180 E50 F1200 ; extrude a line in front of the printer\nG92 E0 ; specify current extruder position as zero\nG0 Z20 F6000 ; move head up\nG1 E-7 F2400 ; retract\nG04 S2 ; wait 2s\nG0 X0 F6000 ; wipe from oozed filament\nG1 E-1 F2400 ; undo some of the retraction to avoid oozing\nG1 F6000 ; set travel speed to move to start printing point\nM117",
|
||||
"machine_start_gcode": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 X0 Y0 ;move X/Y to min endstops\nG28 Z0 ;move Z to min endstops\nG0 Z0.2 F1800 ; move nozzle to print position\nG92 E0 ; specify current extruder position as zero\nM109 S[nozzle_temperature_initial_layer] ; wait for nozzle temp to stabilize\nG1 Y10 X180 E50 F1200 ; extrude a line in front of the printer\nG92 E0 ; specify current extruder position as zero\nG0 Z20 F6000 ; move head up\nG1 E-7 F2400 ; retract\nG04 S2 ; wait 2s\nG0 X0 F6000 ; wipe from oozed filament\nG1 E-1 F2400 ; undo some of the retraction to avoid oozing\nG1 F6000 ; set travel speed to move to start printing point\nM117",
|
||||
"machine_end_gcode": "G4 ; wait\nG92 E0\nG1{if max_layer_z < printable_height} Z{z_offset+min(max_layer_z+30, printable_height)}{endif} ; move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200 F3000 ; home X axis\nM84 ; disable motors",
|
||||
"before_layer_change_gcode": ";BEFORE_LAYER_CHANGE\n;[layer_z]",
|
||||
"layer_change_gcode": ";AFTER_LAYER_CHANGE\n;[layer_z]",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "Bambulab",
|
||||
"url": "http://www.bambulab.com/Parameters/vendor/BBL.json",
|
||||
"version": "02.08.00.13",
|
||||
"version": "02.08.00.14",
|
||||
"force_update": "0",
|
||||
"description": "the initial version of BBL configurations",
|
||||
"machine_model_list": [
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"0.4"
|
||||
],
|
||||
"printer_variant": "0.4",
|
||||
"use_3mf": "1",
|
||||
"bed_exclude_area": [
|
||||
"0x0",
|
||||
"28x0",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"0.4"
|
||||
],
|
||||
"printer_variant": "0.4",
|
||||
"use_3mf": "1",
|
||||
"best_object_pos": "0.3x0.5",
|
||||
"bed_exclude_area": [],
|
||||
"bed_temperature_formula": "by_highest_temp",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Prusa",
|
||||
"version": "02.04.00.16",
|
||||
"version": "02.04.00.17",
|
||||
"force_update": "0",
|
||||
"description": "Prusa configurations",
|
||||
"machine_model_list": [
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
"35"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"110"
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"35"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
],
|
||||
"hot_plate_temp": [
|
||||
"110"
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
"0.8"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.053{elsif nozzle_diameter[filament_extruder_id]==0.5}0.042{elsif nozzle_diameter[filament_extruder_id]==0.6}0.032{elsif nozzle_diameter[filament_extruder_id]==0.8}0.018{elsif nozzle_diameter[filament_extruder_id]==0.25}0.18{elsif nozzle_diameter[filament_extruder_id]==0.3}0.1{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.053{elsif nozzle_diameter[filament_extruder_id]==0.5}0.042{elsif nozzle_diameter[filament_extruder_id]==0.6}0.032{elsif nozzle_diameter[filament_extruder_id]==0.8}0.018{elsif nozzle_diameter[filament_extruder_id]==0.25}0.18{elsif nozzle_diameter[filament_extruder_id]==0.3}0.1{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_wipe": [
|
||||
"1"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"15"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One|CORE One L).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_z_hop": [
|
||||
"0.6"
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"7"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[0]==0.4}0.05{elsif nozzle_diameter[0]==0.25}0.14{elsif nozzle_diameter[0]==0.3}0.07{elsif nozzle_diameter[0]==0.35}0.06{elsif nozzle_diameter[0]==0.6}0.03{elsif nozzle_diameter[0]==0.5}0.035{elsif nozzle_diameter[0]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[0]==0.4}0.03{elsif nozzle_diameter[0]==0.5}0.022{elsif nozzle_diameter[0]==0.6}0.018{elsif nozzle_diameter[0]==0.8}0.012{elsif nozzle_diameter[0]==0.25}0.12{elsif nozzle_diameter[0]==0.3}0.075{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[0]==0.4}0.05{elsif nozzle_diameter[0]==0.25}0.14{elsif nozzle_diameter[0]==0.3}0.07{elsif nozzle_diameter[0]==0.35}0.06{elsif nozzle_diameter[0]==0.6}0.03{elsif nozzle_diameter[0]==0.5}0.035{elsif nozzle_diameter[0]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[0]==0.4}0.03{elsif nozzle_diameter[0]==0.5}0.022{elsif nozzle_diameter[0]==0.6}0.018{elsif nozzle_diameter[0]==0.8}0.012{elsif nozzle_diameter[0]==0.25}0.12{elsif nozzle_diameter[0]==0.3}0.075{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_z_hop": [
|
||||
"0.6",
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.04{elsif nozzle_diameter[filament_extruder_id]==0.25}0.1{elsif nozzle_diameter[filament_extruder_id]==0.3}0.06{elsif nozzle_diameter[filament_extruder_id]==0.35}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.03{elsif nozzle_diameter[filament_extruder_id]==0.6}0.02{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.02{elsif nozzle_diameter[filament_extruder_id]==0.5}0.018{elsif nozzle_diameter[filament_extruder_id]==0.6}0.012{elsif nozzle_diameter[filament_extruder_id]==0.8}0.01{elsif nozzle_diameter[filament_extruder_id]==0.25}0.09{elsif nozzle_diameter[filament_extruder_id]==0.3}0.065{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S40 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"ASA"
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PA11-CF"
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PC"
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.6}0.025{elsif nozzle_diameter[filament_extruder_id]==0.8}0.016{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S45 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PC-CF"
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.053{elsif nozzle_diameter[filament_extruder_id]==0.5}0.042{elsif nozzle_diameter[filament_extruder_id]==0.6}0.032{elsif nozzle_diameter[filament_extruder_id]==0.8}0.018{elsif nozzle_diameter[filament_extruder_id]==0.25}0.18{elsif nozzle_diameter[filament_extruder_id]==0.3}0.1{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.07{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.09{elsif nozzle_diameter[filament_extruder_id]==0.35}0.08{elsif nozzle_diameter[filament_extruder_id]==0.6}0.04{elsif nozzle_diameter[filament_extruder_id]==0.5}0.05{elsif nozzle_diameter[filament_extruder_id]==0.8}0.02{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.053{elsif nozzle_diameter[filament_extruder_id]==0.5}0.042{elsif nozzle_diameter[filament_extruder_id]==0.6}0.032{elsif nozzle_diameter[filament_extruder_id]==0.8}0.018{elsif nozzle_diameter[filament_extruder_id]==0.25}0.18{elsif nozzle_diameter[filament_extruder_id]==0.3}0.1{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PETG"
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One|CORE One L).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PLA"
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"1"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PVB"
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"0"
|
||||
],
|
||||
"filament_start_gcode": [
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|CORE One).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
"M900 K{if nozzle_diameter[filament_extruder_id]==0.4}0.05{elsif nozzle_diameter[filament_extruder_id]==0.25}0.14{elsif nozzle_diameter[filament_extruder_id]==0.3}0.07{elsif nozzle_diameter[filament_extruder_id]==0.35}0.06{elsif nozzle_diameter[filament_extruder_id]==0.6}0.03{elsif nozzle_diameter[filament_extruder_id]==0.5}0.035{elsif nozzle_diameter[filament_extruder_id]==0.8}0.015{else}0{endif} ; Filament gcode\n\n{if printer_notes=~/.*(MK4IS|XLIS|MK4S|MK3.9S|COREONE).*/}\nM572 S{if nozzle_diameter[filament_extruder_id]==0.4}0.036{elsif nozzle_diameter[filament_extruder_id]==0.5}0.025{elsif nozzle_diameter[filament_extruder_id]==0.6}0.022{elsif nozzle_diameter[filament_extruder_id]==0.8}0.014{elsif nozzle_diameter[filament_extruder_id]==0.25}0.12{elsif nozzle_diameter[filament_extruder_id]==0.3}0.08{else}0{endif} ; Filament gcode\n{endif}\n\nM142 S36 ; set heatbreak target temp"
|
||||
],
|
||||
"filament_type": [
|
||||
"PLA"
|
||||
|
||||
@@ -118,9 +118,9 @@ modules:
|
||||
# Use git instead of archive: wxWidgets 3.3 relies on multiple git
|
||||
# submodules (PCRE2, etc.) that are not included in GitHub tarballs.
|
||||
- type: git
|
||||
url: https://github.com/SoftFever/Orca-deps-wxWidgets.git
|
||||
tag: orca-3.3.2
|
||||
commit: db1005db3dea2c37a46fb455a9a02e37aa360751
|
||||
url: https://github.com/wxWidgets/wxWidgets.git
|
||||
tag: v3.3.4
|
||||
commit: 6a42a4b999b127cf28a8b5fe686da6b8ca93a9b8
|
||||
|
||||
# OrcaSlicer C++ dependencies (built offline with pre-downloaded archives)
|
||||
- name: orca_deps
|
||||
|
||||
@@ -405,6 +405,7 @@ set(lisbslic3r_sources
|
||||
Polyline.hpp
|
||||
PresetBundle.cpp
|
||||
PresetBundle.hpp
|
||||
PrinterBedAssets.hpp
|
||||
PresetCacheFormat.cpp
|
||||
PresetCacheFormat.hpp
|
||||
Preset.cpp
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <ios>
|
||||
#include <optional>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -29,6 +30,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "PresetBundle.hpp"
|
||||
#include "PrinterBedAssets.hpp"
|
||||
|
||||
#include "Config.hpp"
|
||||
#include "Exception.hpp"
|
||||
@@ -64,6 +66,7 @@
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
@@ -1678,6 +1681,258 @@ bool PresetBundle::apply_vendor_config(
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// The two bed files a printer bundle can carry. Zip names are bed/<n>/<stem><ext>, never the source basename.
|
||||
struct BedAssetSlot {
|
||||
const char *option;
|
||||
const char *stem;
|
||||
};
|
||||
|
||||
constexpr BedAssetSlot k_bed_asset_slots[] = {
|
||||
{"bed_custom_texture", "texture"},
|
||||
{"bed_custom_model", "model"},
|
||||
};
|
||||
|
||||
std::string zip_slashes(std::string name)
|
||||
{
|
||||
for (char &c : name)
|
||||
if (c == '\\')
|
||||
c = '/';
|
||||
return name;
|
||||
}
|
||||
|
||||
// The bed dialog loads only png/svg textures and stl models. Anything else is not a bed asset.
|
||||
bool bed_extension_allowed(const char *option, const std::string &ext)
|
||||
{
|
||||
if (std::string(option) == "bed_custom_texture")
|
||||
return boost::iequals(ext, ".png") || boost::iequals(ext, ".svg");
|
||||
if (std::string(option) == "bed_custom_model")
|
||||
return boost::iequals(ext, ".stl");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extension including the dot, or empty when this option may not use it.
|
||||
std::string bed_asset_extension(const std::string &path, const char *option)
|
||||
{
|
||||
const auto slash = path.find_last_of("/\\");
|
||||
const auto base = slash == std::string::npos ? 0 : slash + 1;
|
||||
const auto dot = path.find_last_of('.');
|
||||
if (dot == std::string::npos || dot < base || dot + 1 >= path.size())
|
||||
return {};
|
||||
const std::string ext = path.substr(dot);
|
||||
if (!bed_extension_allowed(option, ext))
|
||||
return {};
|
||||
return ext;
|
||||
}
|
||||
|
||||
bool utf8_is_file(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return false;
|
||||
boost::system::error_code ec;
|
||||
#ifdef _WIN32
|
||||
// A narrow path is the ANSI code page unless nowide_filesystem() has run.
|
||||
const std::wstring wide = boost::nowide::widen(path);
|
||||
if (wide.empty())
|
||||
return false;
|
||||
return boost::filesystem::is_regular_file(boost::filesystem::path(wide), ec) && !ec;
|
||||
#else
|
||||
return boost::filesystem::is_regular_file(path, ec) && !ec;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string bed_asset_dest_utf8(const fs::path &dest)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return boost::nowide::narrow(dest.wstring());
|
||||
#else
|
||||
return dest.string();
|
||||
#endif
|
||||
}
|
||||
|
||||
// True only for bed/<digits>/<stem><ext> with an extension the bed dialog accepts for this field.
|
||||
bool accepted_bed_zip_name(const std::string &raw, const BedAssetSlot &slot, const fs::path &bundle_dir,
|
||||
std::string &zip_name, std::string &folder)
|
||||
{
|
||||
const std::string name = zip_slashes(raw);
|
||||
if (name.find("..") != std::string::npos)
|
||||
return false;
|
||||
if (name.size() < 8 || name.compare(0, 4, "bed/") != 0)
|
||||
return false;
|
||||
const auto slash = name.find('/', 4);
|
||||
if (slash == std::string::npos || slash == 4 || name.find('/', slash + 1) != std::string::npos)
|
||||
return false;
|
||||
const std::string digits = name.substr(4, slash - 4);
|
||||
for (unsigned char c : digits) {
|
||||
if (!std::isdigit(c))
|
||||
return false;
|
||||
}
|
||||
const std::string filename = name.substr(slash + 1);
|
||||
const std::string ext = bed_asset_extension(filename, slot.option);
|
||||
if (ext.empty() || filename != std::string(slot.stem) + ext)
|
||||
return false;
|
||||
if (!is_path_within_root(name, bundle_dir))
|
||||
return false;
|
||||
zip_name = name;
|
||||
folder = digits;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct PendingBedAsset {
|
||||
std::string option;
|
||||
std::string zip_name;
|
||||
std::string dest;
|
||||
std::string printer_key;
|
||||
fs::path final_path;
|
||||
fs::path staged;
|
||||
};
|
||||
|
||||
// Validated asset names only. A raw manifest value that fails the check is not skipped later,
|
||||
// so a value like printer/Name.json cannot hide that preset.
|
||||
// printer_asset is keyed by printer_config zip entry. A flat (unkeyed) object is not read.
|
||||
std::vector<PendingBedAsset> pending_bed_assets(const json &bundle_json, const fs::path &bundle_dir,
|
||||
std::unordered_set<std::string> &skip_names,
|
||||
const std::unordered_set<std::string> &zip_entries)
|
||||
{
|
||||
std::vector<PendingBedAsset> pending;
|
||||
if (!bundle_json.contains("printer_asset") || !bundle_json["printer_asset"].is_object())
|
||||
return pending;
|
||||
const json &assets = bundle_json["printer_asset"];
|
||||
for (auto it = assets.begin(); it != assets.end(); ++it) {
|
||||
const std::string printer_key = it.key();
|
||||
if (zip_entries.count(printer_key) == 0) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer bundle asset entry is ignored, no matching printer in the zip: " << printer_key;
|
||||
continue;
|
||||
}
|
||||
if (!it.value().is_object())
|
||||
continue;
|
||||
const json &per_printer = it.value();
|
||||
for (const BedAssetSlot &slot : k_bed_asset_slots) {
|
||||
if (!per_printer.contains(slot.option) || !per_printer[slot.option].is_string())
|
||||
continue;
|
||||
const std::string raw = per_printer[slot.option].get<std::string>();
|
||||
std::string zip_name;
|
||||
std::string folder;
|
||||
if (!accepted_bed_zip_name(raw, slot, bundle_dir, zip_name, folder)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer bundle asset path is rejected: " << raw;
|
||||
continue;
|
||||
}
|
||||
const std::string filename = zip_name.substr(zip_name.rfind('/') + 1);
|
||||
const fs::path final_path = fs::absolute(bundle_dir / "bed" / folder / filename);
|
||||
pending.push_back({slot.option, zip_name, bed_asset_dest_utf8(final_path), printer_key, final_path, {}});
|
||||
skip_names.insert(zip_name);
|
||||
}
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
|
||||
// Stage under temp_folder. The bundle bed/ directory is not touched until a printer preset keeps the path.
|
||||
bool stage_bed_asset(mz_zip_archive &zip, PendingBedAsset &asset, const fs::path &temp_folder)
|
||||
{
|
||||
size_t size = 0;
|
||||
void *buf = mz_zip_reader_extract_file_to_heap(&zip, asset.zip_name.c_str(), &size, MZ_ZIP_FLAG_CASE_SENSITIVE);
|
||||
if (buf == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer bundle asset is missing, skipping " << asset.option << ": " << asset.zip_name;
|
||||
return false;
|
||||
}
|
||||
const std::string filename = asset.zip_name.substr(asset.zip_name.rfind('/') + 1);
|
||||
asset.staged = temp_folder / "bed" / asset.final_path.parent_path().filename() / filename;
|
||||
boost::system::error_code ec;
|
||||
fs::create_directories(asset.staged.parent_path(), ec);
|
||||
const std::string staged_utf8 = bed_asset_dest_utf8(asset.staged);
|
||||
bool wrote = false;
|
||||
if (!ec) {
|
||||
boost::nowide::ofstream out(staged_utf8, std::ios::binary | std::ios::trunc);
|
||||
wrote = static_cast<bool>(out);
|
||||
if (wrote && size > 0)
|
||||
wrote = static_cast<bool>(out.write(static_cast<const char *>(buf), static_cast<std::streamsize>(size)));
|
||||
}
|
||||
mz_free(buf);
|
||||
if (!wrote) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer bundle asset could not be written, skipping " << asset.option << ": " << staged_utf8;
|
||||
fs::remove(asset.staged, ec);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool install_bed_asset(const PendingBedAsset &asset)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
fs::create_directories(asset.final_path.parent_path(), ec);
|
||||
if (!ec)
|
||||
fs::copy_file(asset.staged, asset.final_path, fs::copy_options::overwrite_existing, ec);
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer bundle asset could not be installed: " << asset.dest;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_pending_bed_asset_entry(const std::string &entry, const std::unordered_set<std::string> &names)
|
||||
{
|
||||
return names.count(entry) != 0 || names.count(zip_slashes(entry)) != 0;
|
||||
}
|
||||
|
||||
bool printer_kept_bed_paths(const PresetCollection &printers, const std::map<std::string, std::string> &paths)
|
||||
{
|
||||
if (paths.empty())
|
||||
return false;
|
||||
for (const Preset &preset : printers.get_presets()) {
|
||||
for (const auto &entry : paths)
|
||||
if (preset.config.opt_string(entry.first) == entry.second)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool append_printer_bed_assets(mz_zip_archive &zip, const DynamicPrintConfig &config, json &bundle_structure,
|
||||
const std::string &printer_config_entry, int printer_index)
|
||||
{
|
||||
if (printer_config_entry.empty() || printer_index < 0)
|
||||
return true;
|
||||
json assets = json::object();
|
||||
for (const BedAssetSlot &slot : k_bed_asset_slots) {
|
||||
if (!config.has(slot.option))
|
||||
continue;
|
||||
const std::string stored = config.opt_string(slot.option);
|
||||
if (stored.empty())
|
||||
continue;
|
||||
if (!utf8_is_file(stored)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bed asset file is missing, skipping " << slot.option << ": " << stored;
|
||||
continue;
|
||||
}
|
||||
const std::string ext = bed_asset_extension(stored, slot.option);
|
||||
if (ext.empty()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bed asset extension is not packable, skipping " << slot.option << ": " << stored;
|
||||
continue;
|
||||
}
|
||||
boost::nowide::ifstream in(stored, std::ios::binary);
|
||||
if (!in) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bed asset file cannot be read, skipping " << slot.option << ": " << stored;
|
||||
continue;
|
||||
}
|
||||
const std::string bytes((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||||
if (in.bad()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Bed asset file cannot be read, skipping " << slot.option << ": " << stored;
|
||||
continue;
|
||||
}
|
||||
const std::string zip_name = std::string("bed/") + std::to_string(printer_index) + "/" + slot.stem + ext;
|
||||
const void *data = bytes.empty() ? static_cast<const void *>("") : static_cast<const void *>(bytes.data());
|
||||
if (mz_zip_writer_add_mem(&zip, zip_name.c_str(), data, bytes.size(), MZ_DEFAULT_COMPRESSION) == MZ_FALSE) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to add bed asset to printer bundle: " << zip_name;
|
||||
return false;
|
||||
}
|
||||
assets[slot.option] = zip_name;
|
||||
}
|
||||
if (!assets.empty())
|
||||
bundle_structure["printer_asset"][printer_config_entry] = std::move(assets);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Import presets from UI control
|
||||
PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string> & files,
|
||||
std::function<int(std::string const &)> override_confirm,
|
||||
@@ -1773,14 +2028,44 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " No bundle_structure.json found, importing presets into the user preset directory";
|
||||
}
|
||||
|
||||
json bundle_json = json::object();
|
||||
std::unordered_set<std::string> bed_asset_entries;
|
||||
std::vector<PendingBedAsset> bed_assets;
|
||||
std::map<std::string, std::map<std::string, std::string>> bed_paths_by_printer;
|
||||
bool bed_paths_loaded = false;
|
||||
if (has_bundle_structure && !bundle_base_dir.empty()) {
|
||||
try {
|
||||
boost::nowide::ifstream manifest_in(metadata_path.string());
|
||||
manifest_in >> bundle_json;
|
||||
} catch (const std::exception &err) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " failed to read bundle manifest: " << err.what();
|
||||
bundle_json = json::object();
|
||||
}
|
||||
std::unordered_set<std::string> zip_entries;
|
||||
const int zip_file_count = mz_zip_reader_get_num_files(&zip_archive);
|
||||
for (int zi = 0; zi < zip_file_count; ++zi) {
|
||||
mz_zip_archive_file_stat st;
|
||||
if (mz_zip_reader_file_stat(&zip_archive, zi, &st))
|
||||
zip_entries.insert(zip_slashes(st.m_filename));
|
||||
}
|
||||
bed_assets = pending_bed_assets(bundle_json, bundle_base_dir, bed_asset_entries, zip_entries);
|
||||
for (PendingBedAsset &asset : bed_assets)
|
||||
if (stage_bed_asset(zip_archive, asset, temp_folder))
|
||||
bed_paths_by_printer[asset.printer_key].emplace(asset.option, asset.dest);
|
||||
}
|
||||
|
||||
// Extract Files
|
||||
int num_files = mz_zip_reader_get_num_files(&zip_archive);
|
||||
const std::map<std::string, std::string> no_bed_paths;
|
||||
for (int i = 0; i < num_files; i++) {
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
status = mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
|
||||
if (status) {
|
||||
std::string file_name = file_stat.m_filename;
|
||||
const std::string zip_entry = zip_slashes(file_name);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " From zip file: " << file << ". Read file name: " << file_stat.m_filename;
|
||||
if (is_pending_bed_asset_entry(file_name, bed_asset_entries))
|
||||
continue;
|
||||
size_t index = file_name.find_last_of("/\\");
|
||||
if (std::string::npos != index) {
|
||||
file_name = file_name.substr(index + 1);
|
||||
@@ -1798,13 +2083,26 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
|
||||
if (MZ_FALSE == status) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Failed to open target file: " << target_file_path;
|
||||
} else {
|
||||
const auto paths_it = bed_paths_by_printer.find(zip_entry);
|
||||
const std::map<std::string, std::string> &this_bed_paths =
|
||||
paths_it != bed_paths_by_printer.end() ? paths_it->second : no_bed_paths;
|
||||
bool is_success = import_json_presets(substitutions, target_file_path, override_confirm, rule, overwrite, result,
|
||||
has_bundle_structure ? bundle_base_dir.string() : std::string());
|
||||
has_bundle_structure ? bundle_base_dir.string() : std::string(),
|
||||
this_bed_paths, &bed_paths_loaded);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " import target file: " << target_file_path << " import result" << is_success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy into bed/ only after this import loads a printer that still holds the staged path.
|
||||
// A preset left from an earlier import must not count: declining this import leaves its files alone.
|
||||
if (bed_paths_loaded) {
|
||||
for (const PendingBedAsset &asset : bed_assets) {
|
||||
if (printer_kept_bed_paths(printers, {{asset.option, asset.dest}}))
|
||||
install_bed_asset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
// Set imported_time to current time if not already set
|
||||
if (metadata.imported_time == 0) {
|
||||
metadata.imported_time = std::time(nullptr);
|
||||
@@ -1846,7 +2144,9 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
|
||||
ForwardCompatibilitySubstitutionRule rule,
|
||||
int & overwrite,
|
||||
std::vector<std::string> & result,
|
||||
const std::string & bundle_dir)
|
||||
const std::string & bundle_dir,
|
||||
const std::map<std::string, std::string> & bed_asset_paths,
|
||||
bool * bed_paths_loaded)
|
||||
{
|
||||
try {
|
||||
DynamicPrintConfig config;
|
||||
@@ -1910,6 +2210,10 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
|
||||
if (inherit_preset)
|
||||
inherits_value = inherit_preset->name; // keep the base_id redo below in sync
|
||||
}
|
||||
if (collection == &printers) {
|
||||
for (const auto &entry : bed_asset_paths)
|
||||
config.option<ConfigOptionString>(entry.first, true)->value = entry.second;
|
||||
}
|
||||
if (inherit_preset) {
|
||||
new_config = inherit_preset->config;
|
||||
new_config.apply(std::move(config));
|
||||
@@ -1927,6 +2231,8 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
|
||||
new_config.apply(std::move(config));
|
||||
extend_default_config_length(new_config, true, default_preset.config);
|
||||
}
|
||||
if (bed_paths_loaded != nullptr && collection == &printers && !bed_asset_paths.empty())
|
||||
*bed_paths_loaded = true;
|
||||
|
||||
Preset &preset = collection->load_preset(collection->path_from_name(name, inherit_preset == nullptr), preset_name, std::move(new_config), false);
|
||||
preset.bundle_id = load_origin.bundle_id;
|
||||
|
||||
@@ -319,7 +319,9 @@ public:
|
||||
ForwardCompatibilitySubstitutionRule rule,
|
||||
int& overwrite,
|
||||
std::vector<std::string>& result,
|
||||
const std::string& bundle_dir = "");
|
||||
const std::string& bundle_dir = "",
|
||||
const std::map<std::string, std::string> &bed_asset_paths = {},
|
||||
bool *bed_paths_loaded = nullptr);
|
||||
|
||||
void save_user_presets(AppConfig& config, std::map<std::string, std::string>& need_to_delete_list);
|
||||
void check_and_fix_user_presets_syncinfo(const std::string& user_id);
|
||||
|
||||
@@ -1148,6 +1148,8 @@ void PrintConfigDef::init_common_params()
|
||||
|
||||
def = this->add("print_host", coString);
|
||||
def->label = L("Hostname, IP or URL");
|
||||
// The URL is an example of the format to type, not a link, so it stays in the text.
|
||||
// xgettext:no-url-check
|
||||
def->tooltip = L("Orca Slicer can upload G-code files to a printer host. This field should contain "
|
||||
"the hostname, IP address or URL of the printer host instance. "
|
||||
"Print host behind HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL "
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
#include <miniz.h>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
|
||||
// Not on PresetBundle.hpp: miniz.h's zlib-compat macros rename GUI methods (GLTexture::Compressor::compress).
|
||||
// printer_config_entry is the zip name also pushed onto bundle_structure["printer_config"].
|
||||
// printer_index is that entry's 0-based index in the exported printer_config list.
|
||||
bool append_printer_bed_assets(mz_zip_archive &zip, const DynamicPrintConfig &config, nlohmann::json &bundle_structure,
|
||||
const std::string &printer_config_entry, int printer_index);
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// paper: https://people.eecs.berkeley.edu/~jrs/meshpapers/GarlandHeckbert2.pdf
|
||||
// sum up: https://users.csc.calpoly.edu/~zwood/teaching/csc570/final06/jseeba/
|
||||
// inspiration: https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <wx/valtext.h>
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/PrinterBedAssets.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
@@ -3674,9 +3675,20 @@ ExportConfigsDialog::~ExportConfigsDialog()
|
||||
}
|
||||
|
||||
void ExportConfigsDialog::on_dpi_changed(const wxRect &suggested_rect) {
|
||||
if (m_include_bed_assets)
|
||||
m_include_bed_assets->Rescale();
|
||||
Layout();
|
||||
}
|
||||
|
||||
void ExportConfigsDialog::update_include_bed_assets_enabled()
|
||||
{
|
||||
const bool on = get_curr_radio_type(m_export_type_btns) == m_exprot_type.preset_bundle;
|
||||
if (m_include_bed_assets)
|
||||
m_include_bed_assets->Enable(on);
|
||||
if (m_include_bed_assets_label)
|
||||
m_include_bed_assets_label->Enable(on);
|
||||
}
|
||||
|
||||
void ExportConfigsDialog::show_export_result(const ExportCase &export_case)
|
||||
{
|
||||
MessageDialog *msg_dlg = nullptr;
|
||||
@@ -3819,6 +3831,17 @@ wxBoxSizer *ExportConfigsDialog::create_export_config_item(wxWindow *parent)
|
||||
static_export_printer_preset_bundle_text->SetFont(Label::Body_12);
|
||||
static_export_printer_preset_bundle_text->SetForegroundColour(wxColour("#6B6B6B"));
|
||||
radioBoxSizer->Add(static_export_printer_preset_bundle_text, 0, wxEXPAND | wxLEFT, FromDIP(22));
|
||||
wxBoxSizer *include_bed_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_include_bed_assets = new ::CheckBox(parent);
|
||||
m_include_bed_assets->SetValue(true);
|
||||
include_bed_sizer->Add(m_include_bed_assets, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
m_include_bed_assets_label = new wxStaticText(parent, wxID_ANY, _L("Include custom bed texture and model"));
|
||||
m_include_bed_assets_label->SetFont(Label::Body_12);
|
||||
m_include_bed_assets_label->SetForegroundColour(wxColour("#6B6B6B"));
|
||||
include_bed_sizer->Add(m_include_bed_assets_label, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(5));
|
||||
radioBoxSizer->Add(0, 0, 0, wxTOP, FromDIP(6));
|
||||
radioBoxSizer->Add(include_bed_sizer, 0, wxEXPAND | wxLEFT, FromDIP(22));
|
||||
update_include_bed_assets_enabled();
|
||||
radioBoxSizer->Add(create_radio_item(m_exprot_type.filament_bundle, parent, wxEmptyString, m_export_type_btns), 0, wxEXPAND | wxTOP, FromDIP(10));
|
||||
wxStaticText *static_export_filament_preset_bundle_text = new wxStaticText(parent, wxID_ANY, _L("User's filament preset set.\nCan be shared with others."),
|
||||
wxDefaultPosition, wxDefaultSize);
|
||||
@@ -3988,9 +4011,10 @@ void ExportConfigsDialog::select_curr_radiobox(std::vector<std::pair<RadioBox *,
|
||||
radiobox_list[i].first->SetValue(false);
|
||||
}
|
||||
}
|
||||
update_include_bed_assets_enabled();
|
||||
}
|
||||
|
||||
ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_preset_bundle_to_file(const wxString &path)
|
||||
ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_preset_bundle_to_file(const wxString &path, bool include_bed_assets)
|
||||
{
|
||||
std::string export_path = initial_file_path(path, "");
|
||||
if (export_path.empty() || "initial_failed" == export_path) return ExportCase::EXPORT_CANCEL;
|
||||
@@ -4092,6 +4116,12 @@ ExportConfigsDialog::ExportCase ExportConfigsDialog::archive_preset_bundle_to_fi
|
||||
bundle_structure["filament_config"] = filament_configs;
|
||||
bundle_structure["process_config"] = process_configs;
|
||||
|
||||
if (include_bed_assets &&
|
||||
!append_printer_bed_assets(zip_archive, printer_preset->config, bundle_structure, printer_config_file_name, 0)) {
|
||||
mz_zip_writer_end(&zip_archive);
|
||||
return ExportCase::ADD_FILE_FAIL;
|
||||
}
|
||||
|
||||
std::string bundle_structure_str = bundle_structure.dump();
|
||||
status = mz_zip_writer_add_mem(&zip_archive, BUNDLE_STRUCTURE_JSON_NAME, bundle_structure_str.data(), bundle_structure_str.size(), MZ_DEFAULT_COMPRESSION);
|
||||
if (MZ_FALSE == status) {
|
||||
@@ -4339,7 +4369,7 @@ wxWindow *ExportConfigsDialog::create_dialog_buttons(wxWindow* parent)
|
||||
const wxString curr_radio_type = get_curr_radio_type(m_export_type_btns);
|
||||
|
||||
if (curr_radio_type == m_exprot_type.preset_bundle) {
|
||||
export_case = archive_preset_bundle_to_file(path);
|
||||
export_case = archive_preset_bundle_to_file(path, m_include_bed_assets->GetValue());
|
||||
} else if (curr_radio_type == m_exprot_type.filament_bundle) {
|
||||
export_case = archive_filament_bundle_to_file(path);
|
||||
} else if (curr_radio_type == m_exprot_type.printer_preset) {
|
||||
|
||||
@@ -271,6 +271,7 @@ protected:
|
||||
private:
|
||||
void data_init();
|
||||
void select_curr_radiobox(std::vector<std::pair<RadioBox *, wxString>> &radiobox_list, int btn_idx);
|
||||
void update_include_bed_assets_enabled();
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void show_export_result(const ExportCase &export_case);
|
||||
bool has_check_box_selected();
|
||||
@@ -284,7 +285,7 @@ private:
|
||||
int initial_zip_archive(mz_zip_archive &zip_archive, const std::string &file_path);
|
||||
ExportCase save_zip_archive_to_file(mz_zip_archive &zip_archive);
|
||||
ExportCase save_presets_to_zip(const std::string &export_file, const std::vector<std::pair<std::string, std::string>> &config_paths);
|
||||
ExportCase archive_preset_bundle_to_file(const wxString &path);
|
||||
ExportCase archive_preset_bundle_to_file(const wxString &path, bool include_bed_assets);
|
||||
ExportCase archive_filament_bundle_to_file(const wxString &path);
|
||||
ExportCase archive_printer_preset_to_file(const wxString &path);
|
||||
ExportCase archive_filament_preset_to_file(const wxString &path);
|
||||
@@ -304,6 +305,8 @@ private:
|
||||
wxGridSizer * m_preset_sizer = nullptr;
|
||||
wxPanel * m_presets_window = nullptr;
|
||||
wxStaticText * m_serial_text = nullptr;
|
||||
::CheckBox * m_include_bed_assets = nullptr;
|
||||
wxStaticText * m_include_bed_assets_label = nullptr;
|
||||
};
|
||||
|
||||
class CreatePresetForPrinterDialog : public DPIDialog
|
||||
|
||||
@@ -379,14 +379,24 @@ void FilamentGroupPopup::OnTimer(wxTimerEvent &event)
|
||||
// leaving event got triggered. So the timer is stopped first, then started
|
||||
// again, causing the popup being dismissed immediately.
|
||||
// To fix this, we check if cursor is still inside the popup window before
|
||||
// dismissing.
|
||||
// dismissing, and keep checking while it is: a leave event is not guaranteed
|
||||
// to follow, and a popup left open keeps grabbing the mouse capture.
|
||||
wxPoint pos = this->ScreenToClient(wxGetMousePosition());
|
||||
if (this->GetClientRect().Contains(pos)) return;
|
||||
if (this->GetClientRect().Contains(pos)) {
|
||||
StartTimer();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Dismiss();
|
||||
}
|
||||
|
||||
FilamentGroupPopup::~FilamentGroupPopup()
|
||||
{
|
||||
m_timer->Stop();
|
||||
delete m_timer;
|
||||
}
|
||||
|
||||
void FilamentGroupPopup::Dismiss() {
|
||||
m_active = false;
|
||||
PopupWindow::Dismiss();
|
||||
@@ -405,7 +415,10 @@ void FilamentGroupPopup::OnEnterWindow(wxMouseEvent &)
|
||||
// Ignore spurious ENTER synthesized by PopupWindow::OnMouseEvent2 on macOS.
|
||||
wxPoint pos = this->ScreenToClient(wxGetMousePosition());
|
||||
if (!this->GetClientRect().Contains(pos)) return;
|
||||
// On macOS the timer keeps running instead, and OnTimer closes the popup once the cursor has left it.
|
||||
#ifndef __APPLE__
|
||||
ResetTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FilamentGroupPopup::UpdateButtonStatus(int hover_idx)
|
||||
|
||||
@@ -27,6 +27,7 @@ class FilamentGroupPopup : public PopupWindow
|
||||
{
|
||||
public:
|
||||
FilamentGroupPopup(wxWindow *parent);
|
||||
~FilamentGroupPopup() override;
|
||||
void tryPopup(Plater* plater,PartPlate* plate, bool slice_all);
|
||||
void tryClose();
|
||||
void Dismiss() override;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/dialog.h>
|
||||
#include "slic3r/GUI/FilamentMapPanel.hpp"
|
||||
#include "slic3r/GUI/FilamentGroupPopup.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@@ -377,6 +379,13 @@ FilamentMapMode FilamentMapDialog::get_mode()
|
||||
|
||||
int FilamentMapDialog::ShowModal()
|
||||
{
|
||||
// The Slice-plate hover popup is a transient popup that keeps grabbing the mouse
|
||||
// capture while shown. Left behind this modal dialog it would starve the dialog of
|
||||
// mouse events, so close it synchronously first, whichever path opened the dialog.
|
||||
if (MainFrame* frame = wxGetApp().mainframe;
|
||||
frame && frame->m_filament_group_popup && frame->m_filament_group_popup->IsShown())
|
||||
frame->m_filament_group_popup->Dismiss();
|
||||
|
||||
update_panel_status(m_page_type);
|
||||
return wxDialog::ShowModal();
|
||||
}
|
||||
|
||||
@@ -2654,9 +2654,10 @@ void GUI_App::init_webview_runtime()
|
||||
BOOST_LOG_TRIVIAL(info) << "WebView2 runtime installed successfully.";
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "WebView2 runtime installation failed or still not detected.";
|
||||
wxMessageBox(_L("The Microsoft WebView2 Runtime could not be installed.\n"
|
||||
"Some features, including the setup wizard, may appear blank until it is installed.\n"
|
||||
"Please install it manually from https://developer.microsoft.com/microsoft-edge/webview2/ and restart Orca Slicer."),
|
||||
wxMessageBox(format_wxstr(_L("The Microsoft WebView2 Runtime could not be installed.\n"
|
||||
"Some features, including the setup wizard, may appear blank until it is installed.\n"
|
||||
"Please install it manually from %1% and restart Orca Slicer."),
|
||||
"https://developer.microsoft.com/microsoft-edge/webview2/"),
|
||||
_L("WebView2 Runtime"), wxOK | wxICON_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ void GridCellFilamentsEditor::SetSize(const wxRect& rect)
|
||||
|
||||
void GridCellFilamentsEditor::OnComboCloseUp(wxCommandEvent& evt)
|
||||
{
|
||||
wxGridCellChoiceEditor::OnComboCloseUp(evt);
|
||||
wxGridCellChoiceEditor::DismissEditor();
|
||||
}
|
||||
|
||||
void GridCellFilamentsEditor::BeginEdit(int row, int col, wxGrid* grid)
|
||||
@@ -449,7 +449,7 @@ void GridCellChoiceEditor::SetSize(const wxRect &rect)
|
||||
wxGridCellChoiceEditor::SetSize(rect);
|
||||
}
|
||||
|
||||
void GridCellChoiceEditor::OnComboCloseUp(wxCommandEvent &evt) { wxGridCellChoiceEditor::OnComboCloseUp(evt); }
|
||||
void GridCellChoiceEditor::OnComboCloseUp(wxCommandEvent &evt) { wxGridCellChoiceEditor::DismissEditor(); }
|
||||
|
||||
void GridCellChoiceEditor::BeginEdit(int row, int col, wxGrid *grid)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface OtherInstanceMessageHandlerMac : NSObject
|
||||
|
||||
@@ -2309,12 +2309,6 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||
|
||||
bool slice = true;
|
||||
|
||||
// The Slice-plate hover popup is a transient popup that keeps grabbing
|
||||
// the mouse capture while shown. Left behind the modal grouping dialog it
|
||||
// would starve that dialog of mouse events, so close it synchronously first.
|
||||
if (m_filament_group_popup)
|
||||
m_filament_group_popup->Dismiss();
|
||||
|
||||
auto curr_plate = m_plater->get_partplate_list().get_curr_plate();
|
||||
#ifdef __linux__
|
||||
PresetBundle* preset = wxGetApp().preset_bundle;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "slic3r/GUI/wxExtensions.hpp"
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -12820,8 +12820,8 @@ void Plater::priv::on_select_bed_type(wxCommandEvent &evt)
|
||||
|
||||
// update plater with new config
|
||||
q->on_config_change(wxGetApp().preset_bundle->full_config());
|
||||
if (auto *plate_tab = dynamic_cast<TabPrintPlate *>(wxGetApp().get_plate_tab()))
|
||||
plate_tab->update_model_config();
|
||||
// Rebuild the plate tab from the current selection; its cached plates may be gone after a reset.
|
||||
wxGetApp().obj_list()->update_and_show_object_settings_item();
|
||||
|
||||
// update app_config
|
||||
AppConfig* app_config = wxGetApp().app_config;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface RemovableDriveManagerMM : NSObject
|
||||
|
||||
@@ -5957,7 +5957,7 @@ if (is_marlin_flavor)
|
||||
{
|
||||
// In the configuration group rather than a group of its own: a full-width widget line
|
||||
// records no mode, so a group holding only this line would show in every mode.
|
||||
auto line = Line{ L("Modes"), L("") };
|
||||
auto line = Line{ L("Modes"), "" };
|
||||
line.full_width = 1;
|
||||
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
||||
int n_cols = 0, n_rows = 0, layout = 0;
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/webview.h>
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
WebDialog::WebDialog(wxWindow* parent,
|
||||
@@ -52,6 +56,17 @@ WebDialog::WebDialog(wxWindow* parent,
|
||||
Bind(wxEVT_CLOSE_WINDOW, &WebDialog::on_close_window, this);
|
||||
}
|
||||
|
||||
void WebDialog::use_normal_window_type()
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
// wxGTK types every wxDialog as a dialog, and Mutter offers no maximize for anything but a
|
||||
// normal window. Mutter also stops hiding a normal window from the taskbar, so keep it hidden
|
||||
// as a dialog with a parent is everywhere else.
|
||||
gtk_window_set_type_hint(GTK_WINDOW(m_widget), GDK_WINDOW_TYPE_HINT_NORMAL);
|
||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(m_widget), TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebDialog::add_user_scripts()
|
||||
{
|
||||
if (wxWebView* wv = browser()) {
|
||||
|
||||
@@ -62,6 +62,10 @@ public:
|
||||
|
||||
bool is_open() const { return m_open; }
|
||||
|
||||
// Lets a modeless window be maximized on X11; call before Show(). Modal ones stay dialogs so the
|
||||
// window manager keeps routing focus from the parent to them.
|
||||
void use_normal_window_type();
|
||||
|
||||
// The payload submitted via window.orca.submit() (modal use), if any.
|
||||
const std::optional<nlohmann::json>& result() const { return m_result; }
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
BEGIN_EVENT_TABLE(SideButton, wxWindow)
|
||||
EVT_LEFT_DOWN(SideButton::mouseDown)
|
||||
EVT_LEFT_UP(SideButton::mouseReleased)
|
||||
EVT_MOUSE_CAPTURE_LOST(SideButton::mouseCaptureLost)
|
||||
EVT_PAINT(SideButton::paintEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@@ -331,20 +332,30 @@ void SideButton::mouseDown(wxMouseEvent& event)
|
||||
event.Skip();
|
||||
pressedDown = true;
|
||||
SetFocus();
|
||||
CaptureMouse();
|
||||
// Capturing twice pushes this button onto the capture stack twice, and the
|
||||
// release would then hand the capture straight back to it.
|
||||
if (!HasCapture())
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void SideButton::mouseReleased(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
// A press whose release went elsewhere still holds the capture.
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
if (pressedDown) {
|
||||
pressedDown = false;
|
||||
ReleaseMouse();
|
||||
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
|
||||
sendButtonEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void SideButton::mouseCaptureLost(wxMouseCaptureLostEvent&)
|
||||
{
|
||||
pressedDown = false;
|
||||
}
|
||||
|
||||
void SideButton::sendButtonEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
void mouseCaptureLost(wxMouseCaptureLostEvent& event);
|
||||
|
||||
void sendButtonEvent();
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/colour.h>
|
||||
|
||||
|
||||
@@ -197,6 +197,7 @@ bool CloudPluginService::download_cloud_plugin(PluginDescriptor& entry,
|
||||
Http http = Http::get(download_url);
|
||||
http.timeout_connect(30)
|
||||
.timeout_max(300)
|
||||
.tls_verify(true)
|
||||
.on_complete([&body, &http_status](std::string response_body, unsigned status) {
|
||||
body = std::move(response_body);
|
||||
http_status = status;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user