Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets
Commits:
c535a140 by Vadim Zeitlin at 2026-08-15T20:43:41+02:00
Rename wxGenericTreeCtrl::Next_Visible flag to Next_Opened
8ca1be38e2 (Add wxGenericTreeCtrl::DoGetNext(Next_Visible) function,
2023-11-08) added this flag with a confusing name because it doesn't
mean the same thing here as in GetNextVisible(): here "visible" meant
just "in an expanded branch" and not necessarily "visible on screen".
Rename the flag to make it more clear what it means.
No real changes yet.
- - - - -
04c70ccb by Vadim Zeitlin at 2026-08-15T20:57:00+02:00
Fix regression in wxGenericTreeCtrl::GetNextVisible()
This function could return an item which wasn't actually visible after
8ca1be38e2 (Add wxGenericTreeCtrl::DoGetNext(Next_Visible) function,
2023-11-08) due to a confusion about what "visible" meant, see the
parent commit.
Return the next item which is really visible on screen from this
function again.
See #24041.
Closes #26839.
- - - - -
6e132165 by Vadim Zeitlin at 2026-08-15T20:57:27+02:00
Remove unused code from wxGenericTreeCtrl::IsVisible()
There is no need to call GetViewStart() whose value we never use.
- - - - -
a6699873 by Lorenzo Salami at 2026-08-15T21:07:36+02:00
wxOSX: fix wxDataViewCustomRenderer cells reading as raw objects
On macOS, wxUSE_ACCESSIBILITY (the generic wxAccessible layer) is unused:
Cocoa's dataview implementation relies entirely on native NSAccessibility,
and had no code at all describing custom-rendered cells to it. Both
VoiceOver and the ordinary tooltip mechanism fell back to NSObject's
default -description on the private wxCustomRendererObject value holder,
announcing/showing literally "<wxCustomRendererObject: 0x...>" instead of
the cell's actual content.
Add wxDataViewCustomRendererBase::GetAccessibleText() which is always
available in wxOSX that stringifies the renderer's current value, with
explicit handling for wxDataViewIconText (the common case of an
icon-plus-text custom renderer) since wxVariant::MakeString() doesn't
know that type. Also improve the existing GetAccessibleText()
implementation in the generic version by adding specific support for
wxDataViewIconText to it too.
Surface it on macOS via an -description override on wxCustomRendererObject,
which both NSCell's default stringification and the accessibility bridge
already consult for non-string objectValues.
Verified against a live app (aMule) with a real accessibility inspector
(pyobjc/ApplicationServices AXUIElement queries, the same API Accessibility
Inspector uses): custom-rendered cells now report their real text instead
of the debug representation, confirmed via 5 rounds of AX-tree hammering
with zero crashes. Also verified against samples/dataview with a custom
renderer using the same wxDataViewIconText round-trip.
Closes #18723.
Closes #26808.
Closes #26809.
- - - - -
7cc9fd17 by Blake-Madden at 2026-08-15T17:25:13-04:00
Fix incorrect pointer check
- - - - -
a16ecfeb by Blake-Madden at 2026-08-15T17:41:31-04:00
Add more pointer checks
Mostly for consistency with the rest of the file, along with being more overly robust
- - - - -
eca8f513 by Blake-Madden at 2026-08-15T18:27:57-04:00
Don't insert null handler when looking up Edge WebView handlers
- - - - -
b08a0cc9 by Blake-Madden at 2026-08-16T09:13:31-04:00
Null out button pointers after clearing button collection
- - - - -
a339b9fb by Blake-Madden at 2026-08-16T09:21:44-04:00
Clamp current layout index after rebuilding buttonbar layout
- - - - -
39e2be88 by Blake-Madden at 2026-08-16T09:26:09-04:00
Use page height, not width, when scrolling vertical ribbon pages
- - - - -
08b63a47 by Blake-Madden at 2026-08-16T09:31:49-04:00
Fix stale hovered page index in buttonbar after page removal
- - - - -
e93a4906 by Blake-Madden at 2026-08-16T09:42:45-04:00
Make art provider buttons in ribbon sample toggle buttons
Will show which art provider is in use.
- - - - -
5e81e9a1 by Vadim Zeitlin at 2026-08-16T15:49:23+02:00
Merge branch 'gen-tree-next-visible'
Fix regression in wxGenericTreeCtrl::GetNextVisible() and some cleanup.
See #26840.
- - - - -
8ba29d6c by Vadim Zeitlin at 2026-08-16T15:51:49+02:00
Merge branch 'EdgeReview3' of github.com:Blake-Madden/wxWidgets
Fix/add null pointer checks in Edge WebView.
See #26843.
- - - - -
d5eccea2 by Blake-Madden at 2026-08-16T09:53:19-04:00
Add pointer checks
- - - - -
5cd9bab5 by Blake-Madden at 2026-08-16T15:53:20+02:00
Fix WebKitWebContext leaks in WebKit2-based wxGTK wxWebView code
Web context and data manager were being leaked under most circumstances.
Closes #26847.
- - - - -
b4d93a62 by Blake-Madden at 2026-08-16T09:56:06-04:00
Fix wxRibbonToolBar default CTOR to call init helper
- - - - -
486948ce by Blake-Madden at 2026-08-16T10:04:21-04:00
Fix dangling tool pointers in ribbon toolbar clear/delete
- - - - -
db57e36a by Blake-Madden at 2026-08-16T10:35:46-04:00
Smarter way to init wxRibbonToolBar
- - - - -
b37b5933 by Eduard Ereza MartÃnez at 2026-08-16T16:42:49+02:00
Update Catalan translation
Translated all missing strings, fixed some mistranslations and typos,
and updated credits to include previous translators.
Closes #26848.
- - - - -
f1b668bd by Blake-Madden at 2026-08-16T11:01:44-04:00
Add comments about m_current_hovered_page logic
- - - - -
53428018 by Vadim Zeitlin at 2026-08-16T17:06:56+02:00
Merge branch 'RibbonFixes' of github.com:Blake-Madden/wxWidgets
Various ribbon fixes and improvements, notably don't use dangling or
null pointers.
See #26849.
- - - - -
546966cf by Steve Cornett at 2026-08-16T17:10:02+02:00
Use native dark theme border for wxTextCtrl when possible in wxMSW
Using "DarkMode_DarkTheme" with wxTextCtrl results in a nicely looking
border with real native appearance, so use it when supported and only
fall back to our implementation otherwise.
Closes #26824.
- - - - -
4b282666 by Steve Cornett at 2026-08-16T17:13:43+02:00
Fix dark mode wxDataViewTreeCtrl expander size on DPI change
Do not specify a dark theme in wxRendererXP::GetExpanderSize() because
it may give incorrect result in high DPI: as we only need the size here,
using light theme (which always works) is good enough.
Fixes #26829.
Closes #26837.
- - - - -
828b5f87 by Steve Cornett at 2026-08-16T17:17:30+02:00
Fix wxDataViewTreeCtrl expander style switching to light mode
Always apply theme "Explorer" upon switching to light mode, except for
the wxGauge, for which we still need to disable themes.
Closes #26838.
- - - - -
e7703503 by Blake-Madden at 2026-08-16T17:20:55+02:00
Fix wrong margin field used for right edge of menu item rects
Use width, not height, in horizontal direction.
Closes #26842.
- - - - -
24 changed files:
- include/wx/dvrenderers.h
- include/wx/generic/treectlg.h
- include/wx/msw/textctrl.h
- include/wx/msw/window.h
- include/wx/ribbon/toolbar.h
- locale/ca.po
- samples/ribbon/ribbondemo.cpp
- src/common/datavcmn.cpp
- src/generic/datavgen.cpp
- src/generic/treectlg.cpp
- src/gtk/webview_webkit2.cpp
- src/msw/gauge.cpp
- src/msw/menuitem.cpp
- src/msw/renderer.cpp
- src/msw/textctrl.cpp
- src/msw/webview_edge.cpp
- src/msw/window.cpp
- src/osx/cocoa/
dataview.mm
- src/ribbon/bar.cpp
- src/ribbon/buttonbar.cpp
- src/ribbon/gallery.cpp
- src/ribbon/page.cpp
- src/ribbon/panel.cpp
- src/ribbon/toolbar.cpp
Changes:
=====================================
include/wx/dvrenderers.h
=====================================
@@ -29,6 +29,22 @@
class WXDLLIMPEXP_FWD_CORE wxDataViewCustomRenderer;
+// wxUSE_ACCESSIBILITY (generic wxAccessible support) is unconditionally 0 on
+// wxOSX, which has no wxAccessible-based accessibility of its own -- but a
+// custom-rendered dataview cell still needs some way to describe itself to
+// screen readers there, since it is the only port where nothing else does it
+// for the cell. wxDataViewCustomRendererBase::GetAccessibleDescription()
+// below is compiled in on wxOSX under this symbol even though
+// wxUSE_ACCESSIBILITY itself stays 0 -- it does not override
+// wxDataViewRendererBase's (still wxUSE_ACCESSIBILITY-gated) pure virtual of
+// the same name there, it is simply the only accessibility entry point
+// wxOSX's custom renderers have.
+#if wxUSE_ACCESSIBILITY || defined(__WXOSX__)
+ #define wxUSE_DATAVIEW_A11Y 1
+#else
+ #define wxUSE_DATAVIEW_A11Y 0
+#endif
+
// ----------------------------------------------------------------------------
// wxDataViewIconText: helper class used by wxDataViewIconTextRenderer
// ----------------------------------------------------------------------------
@@ -384,6 +400,36 @@ public:
virtual void SetEnabled(bool enabled) override;
bool GetEnabled() const { return m_enabled; }
+#if wxUSE_DATAVIEW_A11Y
+ // A plain text representation of the value currently rendered by this
+ // cell, e.g. for use by screen readers. Declared unconditionally on
+ // wxUSE_DATAVIEW_A11Y (see above) rather than plain wxUSE_ACCESSIBILITY,
+ // since wxOSX's native dataview implementation calls this directly on a
+ // custom renderer with no wxAccessible involved at all -- it is not
+ // reachable through wxDataViewRendererBase's own (still
+ // wxUSE_ACCESSIBILITY-only) virtual of the same name there, just a
+ // same-named method that happens to double as its override wherever
+ // wxUSE_ACCESSIBILITY is genuinely 1 too.
+ //
+ // The default implementation stringifies the value returned by
+ // GetValue(), the same as wxDataViewCustomRenderer::
+ // GetAccessibleDescription() does for the generic implementation;
+ // override it if the renderer draws something a bare
+ // wxVariant::MakeString() can't usefully describe (e.g. a progress bar).
+ //
+ // `override` is only added where wxUSE_ACCESSIBILITY is genuinely 1: on
+ // wxOSX (wxUSE_DATAVIEW_A11Y but not wxUSE_ACCESSIBILITY), the base
+ // class's own virtual of this name isn't even compiled in, so there is
+ // nothing to override yet -Winconsistent-missing-override would still
+ // flag its absence there once wxUSE_ACCESSIBILITY is 1 elsewhere in the
+ // same build (that's the whole point of the split below).
+#if wxUSE_ACCESSIBILITY
+ virtual wxString GetAccessibleDescription() const override;
+#else
+ virtual wxString GetAccessibleDescription() const;
+#endif
+#endif // wxUSE_DATAVIEW_A11Y
+
// Implementation only from now on
=====================================
include/wx/generic/treectlg.h
=====================================
@@ -373,7 +373,7 @@ private:
enum
{
Next_Any = 0,
- Next_Visible = 1
+ Next_Opened = 1
};
wxTreeItemId DoGetNext(const wxTreeItemId& item, int flags = 0) const;
=====================================
include/wx/msw/textctrl.h
=====================================
@@ -247,8 +247,10 @@ protected:
virtual wxString DoGetValue() const override;
+ virtual bool MSWShouldDrawDarkThemeBorder() const override;
virtual void MSWDrawThemeBorder(WXHDC hdc) override;
+ virtual void MSWGetDarkModeSupport(MSWDarkModeSupport& support) const override;
virtual void MSWSetDarkOrLightMode(SetMode setmode) override;
#if wxUSE_RICHEDIT
=====================================
include/wx/msw/window.h
=====================================
@@ -627,6 +627,10 @@ protected:
// The theme IDs to use. If neither this field nor the theme name is
// set, no theme is applied to the window.
const wchar_t* themeId = nullptr;
+
+ // True if we should apply theme L"Explorer" when switching to light
+ // mode. Otherwise, nullptr is used.
+ bool isLightModeThemed = true;
};
virtual void MSWGetDarkModeSupport(MSWDarkModeSupport& support) const;
@@ -650,6 +654,10 @@ protected:
// if themed border should be used, depending on CanApplyThemeBorder().
wxBorder DoTranslateBorder(wxBorder border) const;
+ // Returns true if the window does not draw a good dark mode themed
+ // border and therefore we should explicitly draw it.
+ virtual bool MSWShouldDrawDarkThemeBorder() const { return true; }
+
#if wxUSE_MENUS_NATIVE
virtual bool DoPopupMenu( wxMenu *menu, int x, int y ) override;
#endif // wxUSE_MENUS_NATIVE
=====================================
include/wx/ribbon/toolbar.h
=====================================
@@ -190,11 +190,11 @@ protected:
static wxBitmap MakeDisabledBitmap(const wxBitmap& original);
wxArrayRibbonToolBarToolGroup m_groups;
- wxRibbonToolBarToolBase* m_hover_tool;
- wxRibbonToolBarToolBase* m_active_tool;
- wxSize* m_sizes;
- int m_nrows_min;
- int m_nrows_max;
+ wxRibbonToolBarToolBase* m_hover_tool = nullptr;
+ wxRibbonToolBarToolBase* m_active_tool = nullptr;
+ wxSize* m_sizes = nullptr;
+ int m_nrows_min = 0;
+ int m_nrows_max = 0;
#ifndef SWIG
wxDECLARE_CLASS(wxRibbonToolBar);
=====================================
locale/ca.po
=====================================
The diff for this file was not included because it is too large.
=====================================
samples/ribbon/ribbondemo.cpp
=====================================
@@ -163,10 +163,11 @@ protected:
wxColour GetGalleryColour(wxRibbonGallery *gallery,
wxRibbonGalleryItem* item, wxString* name);
void ResetGalleryArtProviders();
- void SetArtProvider(wxRibbonArtProvider* prov);
+ void SetArtProvider(int button_id, wxRibbonArtProvider* prov);
void SetBarStyle(long style);
wxRibbonBar* m_ribbon;
+ wxRibbonButtonBar* m_provider_bar;
wxRibbonGallery* m_primary_gallery;
wxRibbonGallery* m_secondary_gallery;
wxTextCtrl* m_logwindow;
@@ -604,15 +605,17 @@ MyFrame::MyFrame()
wxRibbonPanel *provider_panel = new wxRibbonPanel(scheme, wxID_ANY,
"Art", wxBitmapBundle(), wxDefaultPosition, wxDefaultSize,
wxRIBBON_PANEL_NO_AUTO_MINIMISE);
- wxRibbonButtonBar *provider_bar = new wxRibbonButtonBar(provider_panel, wxID_ANY);
- provider_bar->AddButton(ID_DEFAULT_PROVIDER, "Default Provider",
+ m_provider_bar = new wxRibbonButtonBar(provider_panel, wxID_ANY);
+ m_provider_bar->AddToggleButton(ID_DEFAULT_PROVIDER, "Default Provider",
wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, wxSize(32, 32)));
- provider_bar->AddButton(ID_AUI_PROVIDER, "AUI Provider",
+ m_provider_bar->AddToggleButton(ID_AUI_PROVIDER, "AUI Provider",
MakeSvgBundle(aui_style_svg, wxSize(32, 32)));
- provider_bar->AddButton(ID_MSW_PROVIDER, "MSW Provider",
+ m_provider_bar->AddToggleButton(ID_MSW_PROVIDER, "MSW Provider",
MakeSvgBundle(msw_style_svg, wxSize(32, 32)));
- provider_bar->AddButton(ID_MSW_FLAT_PROVIDER, "MSW Flat Provider",
+ m_provider_bar->AddToggleButton(ID_MSW_FLAT_PROVIDER, "MSW Flat Provider",
MakeSvgBundle(msw_flat_style_svg, wxSize(32, 32)));
+
+ m_provider_bar->ToggleButton(ID_DEFAULT_PROVIDER, true);
wxRibbonPanel *primary_panel = new wxRibbonPanel(scheme, wxID_ANY,
"Primary Colour", MakeSvgBundle(colours_svg, wxSize(16, 16)));
m_primary_gallery = PopulateColoursPanel(primary_panel,
@@ -1275,28 +1278,28 @@ void MyFrame::OnColourGalleryButton(wxCommandEvent& evt)
void MyFrame::OnDefaultProvider(wxRibbonButtonBarEvent& WXUNUSED(evt))
{
m_ribbon->DismissExpandedPanel();
- SetArtProvider(new wxRibbonDefaultArtProvider);
+ SetArtProvider(ID_DEFAULT_PROVIDER, new wxRibbonDefaultArtProvider);
}
void MyFrame::OnAUIProvider(wxRibbonButtonBarEvent& WXUNUSED(evt))
{
m_ribbon->DismissExpandedPanel();
- SetArtProvider(new wxRibbonAUIArtProvider);
+ SetArtProvider(ID_AUI_PROVIDER, new wxRibbonAUIArtProvider);
}
void MyFrame::OnMSWProvider(wxRibbonButtonBarEvent& WXUNUSED(evt))
{
m_ribbon->DismissExpandedPanel();
- SetArtProvider(new wxRibbonMSWArtProvider);
+ SetArtProvider(ID_MSW_PROVIDER, new wxRibbonMSWArtProvider);
}
void MyFrame::OnMSWFlatProvider(wxRibbonButtonBarEvent& WXUNUSED(evt))
{
m_ribbon->DismissExpandedPanel();
- SetArtProvider(new wxRibbonMSWFlatArtProvider);
+ SetArtProvider(ID_MSW_FLAT_PROVIDER, new wxRibbonMSWFlatArtProvider);
}
-void MyFrame::SetArtProvider(wxRibbonArtProvider *prov)
+void MyFrame::SetArtProvider(int button_id, wxRibbonArtProvider *prov)
{
m_ribbon->Freeze();
m_ribbon->SetArtProvider(prov);
@@ -1308,6 +1311,15 @@ void MyFrame::SetArtProvider(wxRibbonArtProvider *prov)
PopulateColoursPanel(m_secondary_gallery->GetParent(), m_default_secondary,
ID_SECONDARY_COLOUR);
+ m_provider_bar->ToggleButton(ID_DEFAULT_PROVIDER,
+ button_id == ID_DEFAULT_PROVIDER);
+ m_provider_bar->ToggleButton(ID_AUI_PROVIDER,
+ button_id == ID_AUI_PROVIDER);
+ m_provider_bar->ToggleButton(ID_MSW_PROVIDER,
+ button_id == ID_MSW_PROVIDER);
+ m_provider_bar->ToggleButton(ID_MSW_FLAT_PROVIDER,
+ button_id == ID_MSW_FLAT_PROVIDER);
+
m_ribbon->Realize();
m_ribbon->Thaw();
GetSizer()->Layout();
=====================================
src/common/datavcmn.cpp
=====================================
@@ -1109,6 +1109,35 @@ wxDataViewCustomRendererBase::RenderText(const wxString& text,
GetEllipsizeMode());
}
+#if wxUSE_DATAVIEW_A11Y
+wxString wxDataViewCustomRendererBase::GetAccessibleDescription() const
+{
+ wxVariant value;
+ GetValue(value);
+
+ if ( value.IsType(wxS("bool")) )
+ {
+ /* TRANSLATORS: Name of Boolean true value */
+ return value.GetBool() ? _("true")
+ /* TRANSLATORS: Name of Boolean false value */
+ : _("false");
+ }
+
+ // wxVariant::MakeString() doesn't know how to stringify this one either,
+ // and it's an extremely common choice of variant type for a custom
+ // renderer that draws an icon next to some text (it's the same type
+ // wxDataViewIconTextRenderer itself uses).
+ if ( value.IsType(wxS("wxDataViewIconText")) )
+ {
+ wxDataViewIconText iconText;
+ iconText << value;
+ return iconText.GetText();
+ }
+
+ return value.MakeString();
+}
+#endif // wxUSE_DATAVIEW_A11Y
+
void wxDataViewCustomRendererBase::SetEnabled(bool enabled)
{
// The native base renderer needs to know about the enabled state as well
=====================================
src/generic/datavgen.cpp
=====================================
@@ -1179,6 +1179,15 @@ wxString wxDataViewCustomRenderer::GetAccessibleDescription() const
/* TRANSLATORS: Name of Boolean false value */
: _("false");
}
+ else if ( val.IsType(wxS("wxDataViewIconText")) )
+ {
+ // wxVariant::MakeString() doesn't know how to stringify this one:
+ // wxDataViewIconTextVariantData doesn't override Write(), so the
+ // wxVariantData base's does-nothing default leaves this empty.
+ wxDataViewIconText iconText;
+ iconText << val;
+ strVal = iconText.GetText();
+ }
else
{
strVal = val.MakeString();
=====================================
src/generic/treectlg.cpp
=====================================
@@ -1342,9 +1342,6 @@ bool wxGenericTreeCtrl::IsVisible(const wxTreeItemId& item) const
parent = parent->GetParent();
}
- int startX, startY;
- GetViewStart(& startX, & startY);
-
wxSize clientSize = GetClientSize();
wxRect rect;
@@ -1497,7 +1494,7 @@ wxGenericTreeCtrl::DoGetNext(const wxTreeItemId& item, int flags) const
wxGenericTreeItem *i = GetItemPtr(item);
// First see if there are any children.
- if ( !(flags & Next_Visible) || i->IsExpanded() )
+ if ( !(flags & Next_Opened) || i->IsExpanded() )
{
wxGenericTreeItems& children = i->GetChildren();
if (!children.empty())
@@ -1538,7 +1535,48 @@ wxTreeItemId wxGenericTreeCtrl::GetNextVisible(const wxTreeItemId& item) const
wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
wxASSERT_MSG( IsVisible(item), wxT("this item itself should be visible") );
- return DoGetNext(item, Next_Visible);
+ const wxSize clientSize = GetClientSize();
+ wxRect rect;
+
+ for ( ;; )
+ {
+ wxTreeItemId itemid = DoGetNext(item, Next_Opened);
+ if ( !itemid.IsOk() )
+ {
+ // There are no more items at all.
+ break;
+ }
+
+ // We could just use IsVisible() here and keep iterating until we find
+ // a visible item or run out of them, but this is inefficient because
+ // we would keep going (possibly long after) the visible area.
+ //
+ // Also, IsVisible() checks that the item is in an opened branch, but
+ // this is always the case for the items returned by DoGetNext() with
+ // Next_Opened flag, so here we just need to check the item rectangle.
+ GetBoundingRect(itemid, rect);
+
+ if ( rect.GetTop() > clientSize.y )
+ {
+ // This item is below the visible area, there won't be any other
+ // items beneath it.
+ break;
+ }
+
+ if ( rect.GetBottom() < 0 )
+ {
+ // This item is above the visible area, try the next one.
+ continue;
+ }
+
+ if ( rect.GetRight() > 0 && rect.GetLeft() < clientSize.x )
+ {
+ // This item is at least partially visible, return it.
+ return itemid;
+ }
+ }
+
+ return wxTreeItemId();
}
wxTreeItemId wxGenericTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const
@@ -1606,13 +1644,13 @@ wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
wxTreeItemId itemid = idParent;
if ( prefix.length() == 1 )
{
- itemid = DoGetNext(itemid, Next_Visible);
+ itemid = DoGetNext(itemid, Next_Opened);
}
// look for the item starting with the given prefix after it
while ( itemid.IsOk() && !GetItemText(itemid).Lower().StartsWith(prefix) )
{
- itemid = DoGetNext(itemid, Next_Visible);
+ itemid = DoGetNext(itemid, Next_Opened);
}
// if we haven't found anything...
@@ -1623,14 +1661,14 @@ wxTreeItemId wxGenericTreeCtrl::FindItem(const wxTreeItemId& idParent,
if ( HasFlag(wxTR_HIDE_ROOT) )
{
// can't select virtual root
- itemid = DoGetNext(itemid, Next_Visible);
+ itemid = DoGetNext(itemid, Next_Opened);
}
// and try all the items (stop when we get to the one we started from)
while ( itemid.IsOk() && itemid != idParent &&
!GetItemText(itemid).Lower().StartsWith(prefix) )
{
- itemid = DoGetNext(itemid, Next_Visible);
+ itemid = DoGetNext(itemid, Next_Opened);
}
// If we haven't found the item but wrapped back to the one we started
// from, id.IsOk() must be false
=====================================
src/gtk/webview_webkit2.cpp
=====================================
@@ -715,6 +715,15 @@ wxgtk_authorize_authenticated_peer_cb(GDBusAuthObserver *,
class wxWebViewConfigurationImplWebKit : public wxWebViewConfigurationImpl
{
public:
+ ~wxWebViewConfigurationImplWebKit()
+ {
+ // The context holds a reference to the data manager, so release it first.
+ // Also, use g_clear_object instead of g_object_unref in case they were not initialized.
+ g_clear_object(&m_webContext);
+#ifdef wxHAVE_WEBKIT_WEBSITE_DATA_MANAGER
+ g_clear_object(&m_websiteDataManager);
+#endif
+ }
#ifdef wxHAVE_WEBKIT_WEBSITE_DATA_MANAGER
wxString GetDataPath() const override
@@ -776,6 +785,7 @@ private:
#ifdef wxHAVE_WEBKIT_EPHEMERAL_CONTEXT
if (!m_persistentStorage)
{
+ // transfer full
m_webContext = webkit_web_context_new_ephemeral();
return m_webContext;
}
@@ -796,15 +806,24 @@ private:
dataPath = wxGtkString(g_strdup(configDataPath.GetPath().utf8_str()));
}
+ // transfer full
m_websiteDataManager = webkit_website_data_manager_new(
"base-cache-directory", cachePath.c_str(),
"base-data-directory", dataPath.c_str(),
nullptr);
+ // transfer full
m_webContext = webkit_web_context_new_with_website_data_manager(m_websiteDataManager);
}
else
#endif
+ {
+ // transfer none
m_webContext = webkit_web_context_get_default();
+
+ // transfer none, so add a ref count
+ g_object_ref(m_webContext);
+ }
+
return m_webContext;
}
=====================================
src/msw/gauge.cpp
=====================================
@@ -102,6 +102,7 @@ void wxGauge::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const
{
support.themeName = L"DarkMode_DarkTheme";
support.themeId = L"Progress";
+ support.isLightModeThemed = false;
}
else
wxGaugeBase::MSWGetDarkModeSupport(support);
=====================================
src/msw/menuitem.cpp
=====================================
@@ -104,7 +104,7 @@ public:
{
rect.top += cyTopHeight;
rect.left += cxLeftWidth;
- rect.right -= cyTopHeight;
+ rect.right -= cxRightWidth;
rect.bottom -= cyBottomHeight;
}
@@ -112,7 +112,7 @@ public:
{
rect.top -= cyTopHeight;
rect.left -= cxLeftWidth;
- rect.right += cyTopHeight;
+ rect.right += cxRightWidth;
rect.bottom += cyBottomHeight;
}
};
=====================================
src/msw/renderer.cpp
=====================================
@@ -851,7 +851,10 @@ wxSize wxRendererXP::GetExpanderSize(wxWindow* win)
{
wxCHECK_MSG( win, wxSize(0, 0), "Must have a valid window" );
- wxUxThemeHandle hTheme(win, L"TREEVIEW", L"DarkMode_Explorer::TreeView");
+ // Do not specify a dark theme as we do in DrawTreeItemButton() because
+ // that may give incorrect high DPI behavior, particularly on old Windows
+ // versions. The light mode theme gives the correct size.
+ wxUxThemeHandle hTheme(win, L"TREEVIEW");
if ( hTheme )
{
if ( ::IsThemePartDefined(hTheme, TVP_GLYPH, 0) )
=====================================
src/msw/textctrl.cpp
=====================================
@@ -2857,6 +2857,14 @@ void wxTextCtrl::OnSetFocus(wxFocusEvent& event)
event.Skip();
}
+bool wxTextCtrl::MSWShouldDrawDarkThemeBorder() const
+{
+ // We need to draw the border for rich edit and when we are not using
+ // DarkMode_DarkTheme. The non-rich control draws a good themed border
+ // with DarkMode_DarkTheme.
+ return IsRich() && !wxMSWDarkMode::HasDarkTheme();
+}
+
void wxTextCtrl::MSWDrawThemeBorder(WXHDC hdc)
{
if ( IsRich() )
@@ -2979,6 +2987,14 @@ void wxTextCtrl::MSWSetRichZoom()
#endif // wxUSE_RICHEDIT
+void wxTextCtrl::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const
+{
+ if ( wxMSWDarkMode::HasDarkTheme() )
+ support.themeName = L"DarkMode_DarkTheme";
+ else
+ wxTextCtrlBase::MSWGetDarkModeSupport(support);
+}
+
void wxTextCtrl::MSWSetDarkOrLightMode(SetMode setmode)
{
wxTextCtrlBase::MSWSetDarkOrLightMode(setmode);
=====================================
src/msw/webview_edge.cpp
=====================================
@@ -216,11 +216,14 @@ public:
return false;
}
// Mark event as completed
- hr = m_deferral->Complete();
- if (FAILED(hr))
+ if ( m_deferral )
{
- wxLogApiError("deferral->Complete()", hr);
- return false;
+ hr = m_deferral->Complete();
+ if (FAILED(hr))
+ {
+ wxLogApiError("deferral->Complete()", hr);
+ return false;
+ }
}
return true;
@@ -369,7 +372,8 @@ public:
{
wxPoint result(-1, -1);
BOOL hasPosition;
- if (SUCCEEDED(m_windowFeatures->get_HasPosition(&hasPosition)) && hasPosition)
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_HasPosition(&hasPosition)) && hasPosition)
{
UINT32 x, y;
if (SUCCEEDED(m_windowFeatures->get_Left(&x)) &&
@@ -383,7 +387,8 @@ public:
{
wxSize result(-1, -1);
BOOL hasSize;
- if (SUCCEEDED(m_windowFeatures->get_HasSize(&hasSize)) && hasSize)
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_HasSize(&hasSize)) && hasSize)
{
UINT32 width, height;
if (SUCCEEDED(m_windowFeatures->get_Width(&width)) &&
@@ -396,7 +401,8 @@ public:
virtual bool ShouldDisplayMenuBar() const override
{
BOOL result;
- if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayMenuBar(&result)))
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_ShouldDisplayMenuBar(&result)))
return result;
else
return true;
@@ -405,7 +411,8 @@ public:
virtual bool ShouldDisplayStatusBar() const override
{
BOOL result;
- if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayStatus(&result)))
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_ShouldDisplayStatus(&result)))
return result;
else
return true;
@@ -413,7 +420,8 @@ public:
virtual bool ShouldDisplayToolBar() const override
{
BOOL result;
- if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayToolbar(&result)))
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_ShouldDisplayToolbar(&result)))
return result;
else
return true;
@@ -422,7 +430,8 @@ public:
virtual bool ShouldDisplayScrollBars() const override
{
BOOL result;
- if (SUCCEEDED(m_windowFeatures->get_ShouldDisplayScrollBars(&result)))
+ if (m_windowFeatures &&
+ SUCCEEDED(m_windowFeatures->get_ShouldDisplayScrollBars(&result)))
return result;
else
return true;
@@ -555,7 +564,7 @@ void wxWebViewEdgeImpl::UpdateBounds()
{
RECT r;
wxCopyRectToRECT(m_ctrl->GetClientRect(), r);
- if (m_webView)
+ if ( m_webViewController )
m_webViewController->put_Bounds(r);
}
@@ -828,7 +837,11 @@ HRESULT wxWebViewEdgeImpl::OnWebResourceRequested(ICoreWebView2* WXUNUSED(sender
wxSharedPtr<wxWebViewHandler> handler;
if (uri.HasServer())
- handler = m_handlers[uri.GetServer()];
+ {
+ const auto it = m_handlers.find(uri.GetServer());
+ if ( it != m_handlers.end() )
+ handler = it->second;
+ }
if (!handler)
{
@@ -1005,7 +1018,7 @@ HRESULT wxWebViewEdgeImpl::OnWebViewCreated(HRESULT result, ICoreWebView2Control
{
if (FAILED(m_newWindowArgs->put_NewWindow(baseWebView)))
SendErrorEventForAPI("WebView2::WebViewCreated (put_NewWindow)", hr);
- if (FAILED(m_newWindowDeferral->Complete()))
+ if (m_newWindowDeferral && FAILED(m_newWindowDeferral->Complete()))
SendErrorEventForAPI("WebView2::WebViewCreated (Complete)", hr);
m_newWindowArgs.reset();
m_newWindowDeferral.reset();
@@ -1631,6 +1644,9 @@ void wxWebViewEdge::EnableAccessToDevTools(bool enable)
bool wxWebViewEdge::ShowDevTools()
{
+ if ( !m_impl->m_webView )
+ return false;
+
const HRESULT hr = m_impl->m_webView->OpenDevToolsWindow();
if ( FAILED(hr) )
{
@@ -1718,6 +1734,9 @@ bool wxWebViewEdge::SetProxy(const wxString& proxy)
bool wxWebViewEdge::ClearBrowsingData(int types, wxDateTime since)
{
+ if ( !m_impl->m_webView )
+ return false;
+
wxCOMPtr<ICoreWebView2_13> webView13;
if (FAILED(m_impl->m_webView->QueryInterface(IID_PPV_ARGS(&webView13))))
return false;
=====================================
src/msw/window.cpp
=====================================
@@ -3846,12 +3846,20 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
case wxBORDER_STATIC:
case wxBORDER_RAISED:
- case wxBORDER_SUNKEN:
// In dark mode, explicitly draw these border styles because
// the default drawing uses light mode colours.
drawBorder = wxMSWDarkMode::IsActive();
break;
+ case wxBORDER_SUNKEN:
+ // In dark mode, explicitly draw the border unless the window
+ // draws a good border itself. When the window draws a good
+ // border, DoTranslateBorder() translates wxBORDER_THEME to
+ // wxBORDER_SUNKEN.
+ drawBorder = wxMSWDarkMode::IsActive() &&
+ MSWShouldDrawDarkThemeBorder();
+ break;
+
case wxBORDER_NONE:
case wxBORDER_SIMPLE:
default:
@@ -4150,16 +4158,24 @@ void wxWindowMSW::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const
void wxWindowMSW::MSWSetDarkOrLightMode(SetMode WXUNUSED(setmode))
{
+ const wchar_t* themeName = nullptr;
+ const wchar_t* themeId = nullptr;
+
MSWDarkModeSupport support;
+ MSWGetDarkModeSupport(support);
if ( wxMSWDarkMode::IsActive() )
{
- MSWGetDarkModeSupport(support);
+ themeName = support.themeName;
+ themeId = support.themeId;
+ }
+ else if ( support.isLightModeThemed )
+ {
+ themeName = L"Explorer";
}
- // Else to restore light mode, use support.themeName == nullptr and
- // support.themeId == nullptr.
+ //else: Disable themes.
// This updates scroll bars, if there are any.
- wxMSWDarkMode::AllowForWindow(m_hWnd, support.themeName, support.themeId);
+ wxMSWDarkMode::AllowForWindow(m_hWnd, themeName, themeId);
// If the window class has a background brush, update it.
// This is the value in WNDCLASS::hbrBackground.
=====================================
src/osx/cocoa/
dataview.mm
=====================================
@@ -158,6 +158,26 @@ inline wxDataViewItem wxDataViewItemFromMaybeNilItem(id item)
return copy;
}
+
+-(NSString*) description
+{
+ // wxCustomCell's -stringValue (inherited, unmodified, from
+ // NSTextFieldCell) falls back to "-[objectValue description]" whenever
+ // the cell's objectValue -- one of these -- isn't itself a string. Both
+ // VoiceOver and the ordinary tooltip mechanism read a cell's text this
+ // way, and NSObject's default -description produces exactly the debug
+ // representation ("<wxCustomRendererObject: 0x...>") both were seen to
+ // leak. Overriding it here, on this private wx-internal value holder,
+ // gets every one of those callers a real answer for free.
+ if ( customRenderer )
+ {
+ const wxString text = customRenderer->GetAccessibleDescription();
+ if ( !text.empty() )
+ return [[wxCFStringRef(text).AsNSString() retain] autorelease];
+ }
+
+ return [super description];
+}
@end
// ----------------------------------------------------------------------------
=====================================
src/ribbon/bar.cpp
=====================================
@@ -389,6 +389,19 @@ void wxRibbonBar::DeletePage(size_t n)
{
m_current_page--;
}
+
+ // If the current hovered page is the one getting deleted, then we
+ // don't have a hovered page anymore.
+ if ( m_current_hovered_page == static_cast<int>(n) )
+ {
+ m_current_hovered_page = wxNOT_FOUND;
+ }
+ // ...otherwise, the pages after it shifted down by one,
+ // so adjust the index to keep referring to the same (still hovered) page.
+ else if ( m_current_hovered_page > static_cast<int>(n) )
+ {
+ m_current_hovered_page--;
+ }
}
}
@@ -410,6 +423,7 @@ void wxRibbonBar::ClearPages()
m_pages.Empty();
Realize();
m_current_page = wxNOT_FOUND;
+ m_current_hovered_page = wxNOT_FOUND;
Refresh();
}
@@ -789,6 +803,9 @@ wxImageList* wxRibbonBar::GetButtonImageList(wxSize size, int initialCount)
void wxRibbonBar::SetArtProvider(wxRibbonArtProvider* art)
{
+ if ( art == m_art )
+ return;
+
wxRibbonArtProvider *old = m_art;
m_art = art;
@@ -960,7 +977,8 @@ void wxRibbonBar::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonBar::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
void wxRibbonBar::RepositionPage(wxRibbonPage *page)
=====================================
src/ribbon/buttonbar.cpp
=====================================
@@ -563,6 +563,8 @@ void wxRibbonButtonBar::ClearButtons()
delete button;
}
m_buttons.Clear();
+ m_hovered_button = nullptr;
+ m_active_button = nullptr;
Realize();
}
@@ -1173,6 +1175,11 @@ void wxRibbonButtonBar::MakeLayouts()
wxRIBBON_BUTTONBAR_BUTTON_SMALL);
}
}
+
+ // Removing buttons can result in fewer layouts from before,
+ // so clamp if necessary.
+ if ( m_current_layout >= (int)m_layouts.GetCount() )
+ m_current_layout = (int)m_layouts.GetCount() - 1;
}
void wxRibbonButtonBar::TryCollapseLayout(wxRibbonButtonBarLayout* original,
@@ -1607,7 +1614,8 @@ void wxRibbonButtonBar::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonButtonBar::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
#endif // wxUSE_RIBBON
=====================================
src/ribbon/gallery.cpp
=====================================
@@ -543,7 +543,8 @@ void wxRibbonGallery::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonGallery::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
wxRibbonGalleryItem* wxRibbonGallery::Append(const wxBitmapBundle& bitmap, int id)
=====================================
src/ribbon/page.cpp
=====================================
@@ -391,7 +391,7 @@ bool wxRibbonPage::ScrollSections(int sections)
gap = m_art->GetMetric(wxRIBBON_ART_PANEL_Y_SEPARATION_SIZE);
if (scrollForward)
{
- scrollpos = width - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE);
+ scrollpos = height - m_art->GetMetric(wxRIBBON_ART_PAGE_BORDER_BOTTOM_SIZE);
}
else
{
@@ -574,7 +574,8 @@ void wxRibbonPage::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonPage::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
void wxRibbonPage::RemoveChild(wxWindowBase *child)
=====================================
src/ribbon/panel.cpp
=====================================
@@ -263,7 +263,8 @@ void wxRibbonPanel::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonPanel::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
void wxRibbonPanel::DoSetSize(int x, int y, int width, int height, int sizeFlags)
=====================================
src/ribbon/toolbar.cpp
=====================================
@@ -338,6 +338,12 @@ void wxRibbonToolBar::ClearTools()
delete group;
}
m_groups.Clear();
+
+ m_hover_tool = nullptr;
+ m_active_tool = nullptr;
+
+ // at least one group should be available
+ AppendGroup();
}
bool wxRibbonToolBar::DeleteTool(int tool_id)
@@ -354,6 +360,10 @@ bool wxRibbonToolBar::DeleteTool(int tool_id)
if(tool->id == tool_id)
{
group->tools.RemoveAt(t);
+ if ( tool == m_hover_tool )
+ m_hover_tool = nullptr;
+ if ( tool == m_active_tool )
+ m_active_tool = nullptr;
delete tool;
return true;
}
@@ -375,6 +385,10 @@ bool wxRibbonToolBar::DeleteToolByPos(size_t pos)
// Remove tool
wxRibbonToolBarToolBase* tool = group->tools.Item(pos);
group->tools.RemoveAt(pos);
+ if (tool == m_hover_tool )
+ m_hover_tool = nullptr;
+ if ( tool == m_active_tool )
+ m_active_tool = nullptr;
delete tool;
return true;
}
@@ -990,7 +1004,8 @@ void wxRibbonToolBar::OnDPIChanged(wxDPIChangedEvent& event)
void wxRibbonToolBar::OnSysColourChanged(wxSysColourChangedEvent& event)
{
event.Skip();
- m_art->UpdateColoursFromSystem();
+ if ( m_art )
+ m_art->UpdateColoursFromSystem();
}
// Finds the best width and height given the parents' width and height
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/01fdfa2b50ab6719ed4bfa5f833d5ceae127fc10...e770350305df94534baeef9c49c129cd3830fc7c
--
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/01fdfa2b50ab6719ed4bfa5f833d5ceae127fc10...e770350305df94534baeef9c49c129cd3830fc7c
You're receiving this email because of your account on
gitlab.com. Manage all notifications:
https://gitlab.com/-/profile/notifications | Help:
https://gitlab.com/help