diff --git a/apps/RawLogViewer/main_timeline.cpp b/apps/RawLogViewer/main_timeline.cpp index c592077d55..c20e121a7a 100644 --- a/apps/RawLogViewer/main_timeline.cpp +++ b/apps/RawLogViewer/main_timeline.cpp @@ -143,7 +143,7 @@ void xRawLogViewerFrame::rebuildBottomTimeLine() auto& tl = m_timeline; tl.clearStats(); - const auto clsz = m_glTimeLine->GetClientSize(); + const auto clsz = mrpt::gui::GetScaledClientSize(m_glTimeLine); auto px2x = [clsz](int u) { return -1.0 + (2.0 / clsz.GetWidth()) * u; }; auto px2y = [clsz](int v) { return +1.0 - (2.0 / clsz.GetHeight()) * v; }; @@ -365,7 +365,7 @@ void xRawLogViewerFrame::bottomTimeLineUpdateCursorFromTreeScrollPos() return; } - const auto clsz = m_glTimeLine->GetClientSize(); + const auto clsz = mrpt::gui::GetScaledClientSize(m_glTimeLine); auto px2x = [clsz](int u) { return -1.0 + (2.0 / clsz.GetWidth()) * u; }; auto px2y = [clsz](int v) { return +1.0 - (2.0 / clsz.GetHeight()) * v; }; @@ -557,7 +557,7 @@ void xRawLogViewerFrame::OnTimeLineMouseWheel(wxMouseEvent& e) mrpt::keep_max(xFocus, -1.0); mrpt::keep_min(xFocus, 1.0); - const auto clsz = m_glTimeLine->GetClientSize(); + const auto clsz = mrpt::gui::GetScaledClientSize(m_glTimeLine); auto px2x = [clsz](int u) { return -1.0 + (2.0 / clsz.GetWidth()) * u; @@ -613,7 +613,7 @@ std::optional> const std::optional& forceThisSensorLabel, const mrpt::optional_ref& outSelectedSensorLabel) const { - const auto clsz = m_glTimeLine->GetClientSize(); + const auto clsz = mrpt::gui::GetScaledClientSize(m_glTimeLine); auto& tl = m_timeline; diff --git a/apps/camera-calib/CDlgCalibWizardOnline.cpp b/apps/camera-calib/CDlgCalibWizardOnline.cpp index 751f51cf2d..bdf5700d66 100644 --- a/apps/camera-calib/CDlgCalibWizardOnline.cpp +++ b/apps/camera-calib/CDlgCalibWizardOnline.cpp @@ -439,7 +439,8 @@ void CDlgCalibWizardOnline::OntimCaptureTrigger(wxTimerEvent& event) // Resize the display area, if needed: if (std::abs( - (int)(this->m_realtimeview->GetClientSize().GetWidth()) - + (int)(mrpt::gui::GetScaledClientSize(m_realtimeview) + .GetWidth()) - int(img_to_show.getWidth())) > 30) { this->m_realtimeview->SetSize( diff --git a/apps/camera-calib/CDlgPoseEst.cpp b/apps/camera-calib/CDlgPoseEst.cpp index 9e75f2aafd..87afd58005 100644 --- a/apps/camera-calib/CDlgPoseEst.cpp +++ b/apps/camera-calib/CDlgPoseEst.cpp @@ -479,7 +479,8 @@ void CDlgPoseEst::OntimCaptureTrigger(wxTimerEvent& event) // Resize the display area, if needed: if (std::abs( - (int)(this->m_realtimeview->GetClientSize().GetWidth()) - + (int)(mrpt::gui::GetScaledClientSize(m_realtimeview) + .GetWidth()) - int(img_to_show.getWidth())) > 30) { this->m_realtimeview->SetSize( diff --git a/doc/source/doxygen-docs/changelog.md b/doc/source/doxygen-docs/changelog.md index 51b0dbc56d..e5e26efda8 100644 --- a/doc/source/doxygen-docs/changelog.md +++ b/doc/source/doxygen-docs/changelog.md @@ -1,7 +1,11 @@ \page changelog Change Log # Version 2.11.2: UNRELEASED -(none yet) +- Changes in libraries: + - \ref mrpt_gui_grp + - New function mrpt::gui::GetScaledClientSize(). +- BUG FIXES: + - Fix wrong rendering of all wxWidgets-based OpenGL windows when using Ubuntu's display settings to change UI to a size different than 100% (Fixes [issue #1114](https://github.com/MRPT/mrpt/issues/1114)). # Version 2.11.1: Released Oct 23rd, 2023 - Changes in libraries: diff --git a/libs/gui/include/mrpt/gui/WxUtils.h b/libs/gui/include/mrpt/gui/WxUtils.h index 260dd882fc..642c57b748 100644 --- a/libs/gui/include/mrpt/gui/WxUtils.h +++ b/libs/gui/include/mrpt/gui/WxUtils.h @@ -64,10 +64,14 @@ namespace gui /** \addtogroup mrpt_gui_wxutils Utilities for MRPT-wxWidgets interfacing (in #include ) * \ingroup mrpt_gui_grp - * @{ */ #if MRPT_HAS_WXWIDGETS +/** Returns the size of a window, including the optional magnification scale set + * by users in Display->Appearance. + */ +wxSize GetScaledClientSize(const wxWindow* w); + #ifndef WX_START_TRY #define WX_START_TRY \ diff --git a/libs/gui/src/CWxGLCanvasBase.cpp b/libs/gui/src/CWxGLCanvasBase.cpp index c5b648a80c..d9e0a84cd8 100644 --- a/libs/gui/src/CWxGLCanvasBase.cpp +++ b/libs/gui/src/CWxGLCanvasBase.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT @@ -223,9 +224,8 @@ void CWxGLCanvasBase::Render() lck.unlock(); - int width, height; - GetClientSize(&width, &height); - double At = renderCanvas(width, height); + const auto sz = mrpt::gui::GetScaledClientSize(this); + double At = renderCanvas(sz.GetWidth(), sz.GetHeight()); OnPostRenderSwapBuffers(At, dc); } @@ -241,8 +241,7 @@ void CWxGLCanvasBase::OnSize(wxSizeEvent& event) if (!m_parent->IsShown()) return; // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...) - int w, h; - GetClientSize(&w, &h); + const auto sz = mrpt::gui::GetScaledClientSize(this); if (this->IsShownOnScreen()) { @@ -256,7 +255,7 @@ void CWxGLCanvasBase::OnSize(wxSizeEvent& event) SetCurrent(*m_gl_context); } - resizeViewport(w, h); + resizeViewport(sz.GetWidth(), sz.GetHeight()); } } diff --git a/libs/gui/src/WxUtils.cpp b/libs/gui/src/WxUtils.cpp index fa9e664f39..f65e909e06 100644 --- a/libs/gui/src/WxUtils.cpp +++ b/libs/gui/src/WxUtils.cpp @@ -9,6 +9,7 @@ #include "gui-precomp.h" // Precompiled headers // +#include #include #include #include @@ -933,4 +934,12 @@ mrptKeyModifier mrpt::gui::keyEventToMrptKeyModifier(const wxKeyEvent& ev) return mrptKeyModifier(mod); } +wxSize mrpt::gui::GetScaledClientSize(const wxWindow* w) +{ + int width, height; + w->GetClientSize(&width, &height); + const double s = w->GetContentScaleFactor(); + return wxSize(mrpt::round(s * width), mrpt::round(s * height)); +} + #endif // MRPT_HAS_WXWIDGETS diff --git a/libs/gui/src/mathplots/mathplot.cpp b/libs/gui/src/mathplots/mathplot.cpp index f2bb686835..d4c7bbe1f6 100644 --- a/libs/gui/src/mathplots/mathplot.cpp +++ b/libs/gui/src/mathplots/mathplot.cpp @@ -90,6 +90,14 @@ double mpWindow::zoomIncrementalFactor = 1.5; IMPLEMENT_ABSTRACT_CLASS(mpLayer, wxObject) +static void MyGetScaledClientSize(const wxWindow* w, int& width, int& height) +{ + w->GetClientSize(&width, &height); + const double s = w->GetContentScaleFactor(); + width = static_cast(s * width); + height = static_cast(s * height); +} + mpLayer::mpLayer() { SetPen((wxPen&)*wxBLACK_PEN); @@ -1501,8 +1509,6 @@ void mpWindow::OnMouseWheel(wxMouseEvent& event) return; } - // GetClientSize( &m_scrX,&m_scrY); - if (event.m_controlDown) { wxPoint clickPt(event.GetX(), event.GetY()); @@ -1695,7 +1701,7 @@ void mpWindow::Fit( else { // Normal case (screen): - GetClientSize(&m_scrX, &m_scrY); + MyGetScaledClientSize(this, m_scrX, m_scrY); } double Ax, Ay; @@ -1839,7 +1845,7 @@ void mpWindow::ZoomIn(const wxPoint& centerPoint) wxPoint c(centerPoint); if (c == wxDefaultPosition) { - GetClientSize(&m_scrX, &m_scrY); + MyGetScaledClientSize(this, m_scrX, m_scrY); c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft; // c.x = m_scrX/2; c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 - @@ -1882,7 +1888,7 @@ void mpWindow::ZoomOut(const wxPoint& centerPoint) wxPoint c(centerPoint); if (c == wxDefaultPosition) { - GetClientSize(&m_scrX, &m_scrY); + MyGetScaledClientSize(this, m_scrX, m_scrY); c.x = (m_scrX - m_marginLeft - m_marginRight) / 2 + m_marginLeft; // c.x = m_scrX/2; c.y = (m_scrY - m_marginTop - m_marginBottom) / 2 - @@ -2022,7 +2028,7 @@ void mpWindow::OnPrintMenu(wxCommandEvent& WXUNUSED(event)) void mpWindow::OnFit(wxCommandEvent& WXUNUSED(event)) { Fit(); } void mpWindow::OnCenter(wxCommandEvent& WXUNUSED(event)) { - GetClientSize(&m_scrX, &m_scrY); + MyGetScaledClientSize(this, m_scrX, m_scrY); int centerX = (m_scrX - m_marginLeft - m_marginRight) / 2; // + m_marginLeft; // c.x = m_scrX/2; int centerY = (m_scrY - m_marginTop - m_marginBottom) / @@ -2131,68 +2137,6 @@ void mpWindow::OnPaint(wxPaintEvent&) if (m_enableScrollBars) {} } -// void mpWindow::OnScroll2(wxScrollWinEvent &event) -// { -// #ifdef MATHPLOT_DO_LOGGING -// wxLogMessage(_("[mpWindow::OnScroll2] Init: m_posX=%f m_posY=%f, sc_pos = -// %d"),m_posX,m_posY, event.GetPosition()); -// #endif -// // If scrollbars are not enabled, Skip operation -// if (!m_enableScrollBars) { -// event.Skip(); -// return; -// } -// // m_scrollX = (int) floor((m_posX - m_minX)*m_scaleX); -// // m_scrollY = (int) floor((m_maxY - m_posY /*- m_minY*/)*m_scaleY); -// // Scroll(m_scrollX, m_scrollY); -// -// // GetClientSize( &m_scrX, &m_scrY); -// //Scroll(x2p(m_desiredXmin), y2p(m_desiredYmin)); -// int pixelStep = 1; -// if (event.GetOrientation() == wxHORIZONTAL) { -// //m_desiredXmin -= (m_scrollX - event.GetPosition())/m_scaleX; -// //m_desiredXmax -= (m_scrollX - event.GetPosition())/m_scaleX; -// m_posX -= (m_scrollX - event.GetPosition())/m_scaleX; -// m_scrollX = event.GetPosition(); -// } -// Fit(m_desiredXmin, m_desiredXmax, m_desiredYmin, m_desiredYmax); -// // /* int pixelStep = 1; -// // if (event.GetOrientation() == wxHORIZONTAL) { -// // m_posX -= (px - -// event.GetPosition())/m_scaleX;//(pixelStep/m_scaleX); -// // m_desiredXmax -= (px - -// event.GetPosition())/m_scaleX;//(pixelStep/m_scaleX); -// // m_desiredXmin -= (px - -// event.GetPosition())/m_scaleX;//(pixelStep/m_scaleX); -// // //SetPosX( (double)px / GetScaleX() + m_minX + -// (double)(width>>1)/GetScaleX()); -// // // m_posX = p2x(px); //m_minX + (double)(px /*+ -// (m_scrX)*/)/GetScaleX(); -// // } else { -// // m_posY += (py - -// event.GetPosition())/m_scaleY;//(pixelStep/m_scaleY); -// // m_desiredYmax += (py - -// event.GetPosition())/m_scaleY;//(pixelStep/m_scaleY); -// // m_desiredYmax += (py - -// event.GetPosition())/m_scaleY;//(pixelStep/m_scaleY); -// // //SetPosY( m_maxY - (double)py / GetScaleY() - -// (double)(height>>1)/GetScaleY()); -// // //m_posY = m_maxY - (double)py / GetScaleY() - -// (double)(height>>1)/GetScaleY(); -// // // m_posY = p2y(py);//m_maxY - (double)(py /*+ -// (m_scrY)*/)/GetScaleY(); -// // }*/ -// #ifdef MATHPLOT_DO_LOGGING -// int px, py; -// GetViewStart( &px, &py); -// wxLogMessage(_("[mpWindow::OnScroll2] End: m_posX = %f, m_posY = %f, px -// = %f, py = %f"),m_posX, m_posY, px, py); -// #endif -// -// UpdateAll(); -// // event.Skip(); -// } - void mpWindow::SetMPScrollbars(bool status) { // Temporary behaviour: always disable scrollbars @@ -2204,36 +2148,6 @@ void mpWindow::SetMPScrollbars(bool status) } // else the scroll bars will be updated in UpdateAll(); UpdateAll(); - - // EnableScrolling(false, false); - // m_enableScrollBars = status; - // EnableScrolling(status, status); - /* m_scrollX = (int) floor((m_posX - m_minX)*m_scaleX); - m_scrollY = (int) floor((m_posY - m_minY)*m_scaleY);*/ - // int scrollWidth = (int) floor((m_maxX - m_minX)*m_scaleX) - m_scrX; - // int scrollHeight = (int) floor((m_minY - m_maxY)*m_scaleY) - m_scrY; - - // /* m_scrollX = (int) floor((m_posX - m_minX)*m_scaleX); - // m_scrollY = (int) floor((m_maxY - m_posY /*- m_minY*/)*m_scaleY); - // int scrollWidth = (int) floor(((m_maxX - m_minX) - (m_desiredXmax - - // m_desiredXmin))*m_scaleX); - // int scrollHeight = (int) floor(((m_maxY - m_minY) - (m_desiredYmax - - // m_desiredYmin))*m_scaleY); - // #ifdef MATHPLOT_DO_LOGGING - // wxLogMessage(_("mpWindow::SetMPScrollbars() scrollWidth = %d, - // scrollHeight = %d"), scrollWidth, scrollHeight); - // #endif - // if(status) { - // SetScrollbars(1, - // 1, - // scrollWidth, - // scrollHeight, - // m_scrollX, - // m_scrollY); - // // SetVirtualSize((int) (m_maxX - m_minX), (int) (m_maxY - - // m_minY)); - // } - // Refresh(true);*/ } bool mpWindow::UpdateBBox() @@ -2271,63 +2185,6 @@ bool mpWindow::UpdateBBox() return first == FALSE; } -// void mpWindow::UpdateAll() -// { -// GetClientSize( &m_scrX,&m_scrY); -/* if (m_enableScrollBars) { - // The "virtual size" of the scrolled window: - const int sx = (int)((m_maxX - m_minX) * GetScaleX()); - const int sy = (int)((m_maxY - m_minY) * GetScaleY()); - SetVirtualSize(sx, sy); - SetScrollRate(1, 1);*/ -// const int px = (int)((GetPosX() - m_minX) * GetScaleX());// - -// m_scrX); //(cx>>1)); - -// J.L.Blanco, Aug 2007: Formula fixed: -// const int py = (int)((m_maxY - GetPosY()) * GetScaleY());// - -// m_scrY); //(cy>>1)); -// int px, py; -// GetViewStart(&px0, &py0); -// px = (int)((m_posX - m_minX)*m_scaleX); -// py = (int)((m_maxY - m_posY)*m_scaleY); - -// SetScrollbars( 1, 1, sx - m_scrX, sy - m_scrY, px, py, TRUE); -// } - -// Working code -// UpdateBBox(); -// Refresh( FALSE ); -// end working code - -// Old version -/* bool box = UpdateBBox(); - if (box) -{ - int cx, cy; - GetClientSize( &cx, &cy); - - // The "virtual size" of the scrolled window: - const int sx = (int)((m_maxX - m_minX) * GetScaleX()); - const int sy = (int)((m_maxY - m_minY) * GetScaleY()); - - const int px = (int)((GetPosX() - m_minX) * GetScaleX() - (cx>>1)); - - // J.L.Blanco, Aug 2007: Formula fixed: - const int py = (int)((m_maxY - GetPosY()) * GetScaleY() - (cy>>1)); - - SetScrollbars( 1, 1, sx, sy, px, py, TRUE); - -#ifdef MATHPLOT_DO_LOGGING - wxLogMessage(_("[mpWindow::UpdateAll] Size:%ix%i -ScrollBars:%i,%i"),sx,sy,px,py); -#endif -} - - FitInside(); - Refresh( FALSE ); -*/ -// } - void mpWindow::UpdateAll() { if (UpdateBBox()) @@ -2335,7 +2192,7 @@ void mpWindow::UpdateAll() if (m_enableScrollBars) { int cx, cy; - GetClientSize(&cx, &cy); + MyGetScaledClientSize(this, cx, cy); // Do x scroll bar { // Convert margin sizes from pixels to coordinates @@ -2660,66 +2517,6 @@ void mpWindow::SetColourTheme( } } -// void mpWindow::EnableCoordTooltip(bool value) -// { -// m_coordTooltip = value; -// // if (value) GetToolTip()->SetDelay(100); -// } - -/* -double mpWindow::p2x(wxCoord pixelCoordX, bool drawOutside ) -{ - if (drawOutside) { - return m_posX + pixelCoordX/m_scaleX; - } - // Draw inside margins - double marginScaleX = ((double)(m_scrX - m_marginLeft - -m_marginRight))/m_scrX; - return m_marginLeft + (m_posX + pixelCoordX/m_scaleX)/marginScaleX; -} - -double mpWindow::p2y(wxCoord pixelCoordY, bool drawOutside ) -{ - if (drawOutside) { - return m_posY - pixelCoordY/m_scaleY; - } - // Draw inside margins - double marginScaleY = ((double)(m_scrY - m_marginTop - -m_marginBottom))/m_scrY; - return m_marginTop + (m_posY - pixelCoordY/m_scaleY)/marginScaleY; -} - -wxCoord mpWindow::x2p(double x, bool drawOutside) -{ - if (drawOutside) { - return (wxCoord) ((x-m_posX) * m_scaleX); - } - // Draw inside margins - double marginScaleX = ((double)(m_scrX - m_marginLeft - -m_marginRight))/m_scrX; -#ifdef MATHPLOT_DO_LOGGING - wxLogMessage(wxT("x2p ScrX = %d, marginRight = %d, marginLeft = %d, -marginScaleX = %f"), m_scrX, m_marginRight, m_marginLeft, marginScaleX); -#endif // MATHPLOT_DO_LOGGING - return (wxCoord) (int)(((x-m_posX) * m_scaleX)*marginScaleX) - m_marginLeft; -} - -wxCoord mpWindow::y2p(double y, bool drawOutside) -{ - if (drawOutside) { - return (wxCoord) ( (m_posY-y) * m_scaleY); - } - // Draw inside margins - double marginScaleY = ((double)(m_scrY - m_marginTop - -m_marginBottom))/m_scrY; -#ifdef MATHPLOT_DO_LOGGING - wxLogMessage(wxT("y2p ScrY = %d, marginTop = %d, marginBottom = %d, -marginScaleY = %f"), m_scrY, m_marginTop, m_marginBottom, marginScaleY); -#endif // MATHPLOT_DO_LOGGING - return (wxCoord) ((int)((m_posY-y) * m_scaleY)*marginScaleY) - m_marginTop; -} -*/ - //----------------------------------------------------------------------------- // mpFXYVector implementation - by Jose Luis Blanco (AGO-2007) //----------------------------------------------------------------------------- diff --git a/libs/opengl/src/Viewport.cpp b/libs/opengl/src/Viewport.cpp index 63a8172951..fcf171e0ea 100644 --- a/libs/opengl/src/Viewport.cpp +++ b/libs/opengl/src/Viewport.cpp @@ -70,8 +70,8 @@ void Viewport::setViewportPosition( const double x, const double y, const double width, const double height) { MRPT_START - ASSERT_(m_view_width > 0); - ASSERT_(m_view_height > 0); + ASSERT_(width > 0); + ASSERT_(height > 0); m_view_x = x; m_view_y = y;