diff --git a/include/wx/private/display.h b/include/wx/private/display.h index 36f5985fbb..3f74f3dc99 100644 --- a/include/wx/private/display.h +++ b/include/wx/private/display.h @@ -28,10 +28,32 @@ public: // get it from cache. wxDisplayImpl* GetDisplay(unsigned n) { - if ( m_impls.empty() ) + // Normally, m_impls should be cleared if the number of displays in the + // system changes because InvalidateCache() must be called. However in + // some ports (e.g. Mac right now, see #18318), cache invalidation never + // happens, so we can end up with m_impls size being out of sync with + // the actual number of monitors. Compensate for this here by checking + // if the index is invalid and invalidating the cache at least in this + // case. + // + // Note that this is still incorrect because we continue using outdated + // information if the first monitor is disconnected, for example. The + // only real solution is to ensure that InvalidateCache() is called, + // but for now this at least avoids crashes when a new display is + // connected. + if ( n >= m_impls.size() ) + { + // This strange two-step resize is done to clear all the existing + // elements: they may not be valid any longer if the number of + // displays has changed. + m_impls.resize(0); m_impls.resize(GetCount()); + } else if ( m_impls[n] ) + { + // Just return the existing display if we have it. return m_impls[n]; + } m_impls[n] = CreateDisplay(n); return m_impls[n];