diff --git a/include/wx/osx/window.h b/include/wx/osx/window.h index 19cd7d21d7..76ec9bdb1c 100644 --- a/include/wx/osx/window.h +++ b/include/wx/osx/window.h @@ -120,6 +120,8 @@ public: virtual bool UnregisterHotKey(int hotkeyId) wxOVERRIDE; #endif // wxUSE_HOTKEY + virtual wxSize GetDPI() const wxOVERRIDE; + #if wxUSE_DRAG_AND_DROP virtual void SetDropTarget( wxDropTarget *dropTarget ) wxOVERRIDE; @@ -149,6 +151,7 @@ public: // -------------- void OnMouseEvent( wxMouseEvent &event ); + void OnDPIChanged( wxDPIChangedEvent& event ); void MacOnScroll( wxScrollEvent&event ); @@ -291,6 +294,9 @@ public: // internal response to size events virtual void MacOnInternalSize() {} + // Return the DPI corresponding to the given scale factor. + static wxSize OSXMakeDPIFromScaleFactor(double scaleFactor); + protected: // For controls like radio buttons which are genuinely composite wxList m_subControls; diff --git a/src/osx/carbon/dcscreen.cpp b/src/osx/carbon/dcscreen.cpp index 234fd3934a..1c6a987f96 100644 --- a/src/osx/carbon/dcscreen.cpp +++ b/src/osx/carbon/dcscreen.cpp @@ -34,6 +34,7 @@ wxScreenDCImpl::wxScreenDCImpl( wxDC *owner ) : SetGraphicsContext( wxGraphicsContext::Create() ); m_ok = true ; #endif + m_contentScaleFactor = wxOSXGetMainScreenContentScaleFactor(); } wxScreenDCImpl::~wxScreenDCImpl() diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index f38eeddde4..f118433a03 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -321,6 +321,7 @@ static void *EffectiveAppearanceContext = &EffectiveAppearanceContext; - (BOOL)windowShouldClose:(id)window; - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; - (void)windowWillEnterFullScreen:(NSNotification *)notification; +- (void)windowDidChangeBackingProperties:(NSNotification *)notification; @end @@ -612,7 +613,43 @@ extern int wxOSXGetIdFromSelector(SEL action ); [view setFrameSize: expectedframerect.size]; } } - + +// from https://developer.apple.com/library/archive/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/CapturingScreenContents/CapturingScreenContents.html + +- (void)windowDidChangeBackingProperties:(NSNotification *)notification +{ + NSWindow* theWindow = (NSWindow*)[notification object]; + wxNonOwnedWindowCocoaImpl* windowimpl = [theWindow WX_implementation]; + wxNonOwnedWindow* wxpeer = windowimpl ? windowimpl->GetWXPeer() : NULL; + if (wxpeer) + { + CGFloat newBackingScaleFactor = [theWindow backingScaleFactor]; + CGFloat oldBackingScaleFactor = [[[notification userInfo] + objectForKey:@"NSBackingPropertyOldScaleFactorKey"] + doubleValue]; + if (newBackingScaleFactor != oldBackingScaleFactor) + { + const wxSize oldDPI = wxWindow::OSXMakeDPIFromScaleFactor(oldBackingScaleFactor); + const wxSize newDPI = wxWindow::OSXMakeDPIFromScaleFactor(newBackingScaleFactor); + + wxDPIChangedEvent event(oldDPI, newDPI); + event.SetEventObject(wxpeer); + wxpeer->HandleWindowEvent(event); + + } + + NSColorSpace *newColorSpace = [theWindow colorSpace]; + NSColorSpace *oldColorSpace = [[notification userInfo] + objectForKey:@"NSBackingPropertyOldColorSpaceKey"]; + if (![newColorSpace isEqual:oldColorSpace]) + { + wxSysColourChangedEvent event; + event.SetEventObject(wxpeer); + wxpeer->HandleWindowEvent(event); + } + } +} + - (void)addObservers:(NSWindow*)win { [win addObserver:self forKeyPath:@"effectiveAppearance" diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index beccd49723..4e5db615b2 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -14,6 +14,7 @@ #ifndef WX_PRECOMP #include "wx/log.h" + #include "wx/math.h" #include "wx/app.h" #include "wx/utils.h" #include "wx/panel.h" @@ -79,6 +80,7 @@ wxBEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase) EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent) + EVT_DPI_CHANGED(wxWindowMac::OnDPIChanged) wxEND_EVENT_TABLE() #define wxMAC_DEBUG_REDRAW 0 @@ -2345,6 +2347,25 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) } } +// propagate the dpi changed event to the subwindows +void wxWindowMac::OnDPIChanged(wxDPIChangedEvent& event) +{ + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + while ( node ) + { + // Only propagate to non-top-level windows + wxWindow *win = node->GetData(); + if ( !win->IsTopLevel() ) + { + wxDPIChangedEvent event2( event.GetOldDPI(), event.GetNewDPI() ); + event2.SetEventObject(win); + win->GetEventHandler()->ProcessEvent(event2); + } + + node = node->GetNext(); + } +} + void wxWindowMac::TriggerScrollEvent( wxEventType WXUNUSED(scrollEvent) ) { } @@ -2599,6 +2620,25 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) return handled ; } +/* static */ +wxSize wxWindowMac::OSXMakeDPIFromScaleFactor(double scaleFactor) +{ + const int dpi = wxRound(scaleFactor*72.0); + + return wxSize(dpi, dpi); +} + +wxSize wxWindowMac::GetDPI() const +{ + double scaleFactor; + if ( wxNonOwnedWindow* tlw = MacGetTopLevelWindow() ) + scaleFactor = tlw->GetContentScaleFactor(); + else + scaleFactor = wxOSXGetMainScreenContentScaleFactor(); + + return OSXMakeDPIFromScaleFactor(scaleFactor); +} + // // wxWidgetImpl //