diff --git a/aegisub/src/retina_helper.mm b/aegisub/src/retina_helper.mm index b2c7a7682..f69bd52e0 100644 --- a/aegisub/src/retina_helper.mm +++ b/aegisub/src/retina_helper.mm @@ -42,15 +42,19 @@ RetinaHelper::RetinaHelper(wxWindow *window) : window(window) , observer([RetinaObserver new]) { + NSView *view = window->GetHandle(); RetinaObserver *obs = (id)observer; - obs.window = window->GetHandle().window; + obs.window = view.window; obs.block = ^{ ScaleFactorChanged(GetScaleFactor()); }; NSNotificationCenter *nc = NSNotificationCenter.defaultCenter; [nc addObserver:(id)observer selector:@selector(backingPropertiesDidChange:) name:NSWindowDidChangeBackingPropertiesNotification - object:window->GetHandle().window]; + object:view.window]; + + if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) + view.wantsBestResolutionOpenGLSurface = YES; } RetinaHelper::~RetinaHelper() { diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp index bf9f93316..a076a1903 100644 --- a/aegisub/src/video_display.cpp +++ b/aegisub/src/video_display.cpp @@ -43,6 +43,7 @@ #include "include/aegisub/hotkey.h" #include "include/aegisub/menu.h" #include "options.h" +#include "retina_helper.h" #include "spline_curve.h" #include "subs_controller.h" #include "threaded_frame_source.h" @@ -99,6 +100,13 @@ VideoDisplay::VideoDisplay( , toolBar(visualSubToolBar) , zoomBox(zoomBox) , freeSize(freeSize) +, retina_helper(agi::util::make_unique(this)) +, scale_factor(retina_helper->GetScaleFactor()) +, scale_factor_connection(retina_helper->AddScaleFactorListener([=](int new_scale_factor) { + double new_zoom = zoomValue * new_scale_factor / scale_factor; + scale_factor = new_scale_factor; + SetZoom(new_zoom); +})) { zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.)); zoomBox->Bind(wxEVT_COMBOBOX, &VideoDisplay::SetZoomFromBox, this); @@ -199,7 +207,7 @@ void VideoDisplay::Render() try { E(glMatrixMode(GL_PROJECTION)); E(glLoadIdentity()); - E(glOrtho(0.0f, videoSize.GetWidth(), videoSize.GetHeight(), 0.0f, -1000.0f, 1000.0f)); + E(glOrtho(0.0f, videoSize.GetWidth() / scale_factor, videoSize.GetHeight() / scale_factor, 0.0f, -1000.0f, 1000.0f)); if (OPT_GET("Video/Overscan Mask")->GetBool()) { double ar = con->videoController->GetAspectRatioValue(); @@ -272,7 +280,7 @@ void VideoDisplay::PositionVideo() { if (!con->videoController->IsLoaded() || !IsShownOnScreen()) return; viewport_left = 0; - viewport_bottom = GetClientSize().GetHeight() - videoSize.GetHeight(); + viewport_bottom = GetClientSize().GetHeight() * scale_factor - videoSize.GetHeight(); viewport_top = 0; viewport_width = videoSize.GetWidth(); viewport_height = videoSize.GetHeight(); @@ -300,7 +308,8 @@ void VideoDisplay::PositionVideo() { } if (tool) - tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height); + tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, + viewport_width / scale_factor, viewport_height / scale_factor); Render(); } @@ -320,12 +329,12 @@ void VideoDisplay::UpdateSize() { wxSize cs = GetClientSize(); wxSize oldSize = top->GetSize(); - top->SetSize(top->GetSize() + videoSize - cs); + top->SetSize(top->GetSize() + videoSize / scale_factor - cs); SetClientSize(cs + top->GetSize() - oldSize); } else { - SetMinClientSize(videoSize); - SetMaxClientSize(videoSize); + SetMinClientSize(videoSize / scale_factor); + SetMaxClientSize(videoSize / scale_factor); GetGrandParent()->Layout(); } @@ -335,7 +344,7 @@ void VideoDisplay::UpdateSize() { void VideoDisplay::OnSizeEvent(wxSizeEvent &event) { if (freeSize) { - videoSize = GetClientSize(); + videoSize = GetClientSize() * scale_factor; PositionVideo(); zoomValue = double(viewport_height) / con->videoController->GetHeight(); zoomBox->ChangeValue(wxString::Format("%g%%", zoomValue * 100.)); @@ -419,7 +428,8 @@ void VideoDisplay::SetTool(std::unique_ptr new_tool) { else { // UpdateSize fits the window to the video, which we don't want to do GetGrandParent()->Layout(); - tool->SetDisplayArea(viewport_left, viewport_top, viewport_width, viewport_height); + tool->SetDisplayArea(viewport_left / scale_factor, viewport_top / scale_factor, + viewport_width / scale_factor, viewport_height / scale_factor); } } diff --git a/aegisub/src/video_display.h b/aegisub/src/video_display.h index 977c5f829..46cdd6952 100644 --- a/aegisub/src/video_display.h +++ b/aegisub/src/video_display.h @@ -42,13 +42,14 @@ #include // Prototypes -struct FrameReadyEvent; +class RetinaHelper; class VideoContext; class VideoOutGL; class VisualToolBase; class wxComboBox; class wxTextCtrl; class wxToolBar; +struct FrameReadyEvent; struct VideoFrame; namespace agi { @@ -106,6 +107,10 @@ class VideoDisplay : public wxGLCanvas { /// Frame which will replace the currently visible frame on the next render std::shared_ptr pending_frame; + std::unique_ptr retina_helper; + int scale_factor; + agi::signal::Connection scale_factor_connection; + /// @brief Draw an overscan mask /// @param horizontal_percent The percent of the video reserved horizontally /// @param vertical_percent The percent of the video reserved vertically