From c6d1a851da109213fd7866a7974b89e9663d20c0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 10 Jul 2020 02:15:39 +0200 Subject: [PATCH 1/3] Make wxUSE_TIPWINDOW dependent on wxUSE_POPUPWIN It doesn't seem to make sense to provide wxFrame-based implementation of wxTipWindow, if anything we should use similar code to implement wxPopupTransientWindow itself on the platforms not providing it. So simplify wxTipWindow code by leaving only a single implementation, using wxPopupTransientWindow. This should have arguably been done back in 8962e1d938 (wxTipWindow is now a wxPopupTransientWindow instead of a wxFrame., 2001-11-30) which introduced the use of wxPopupTransientWindow in this code. --- include/wx/chkconf.h | 11 ++++++ include/wx/tipwin.h | 16 ++------- src/generic/tipwin.cpp | 80 +++--------------------------------------- 3 files changed, 17 insertions(+), 90 deletions(-) diff --git a/include/wx/chkconf.h b/include/wx/chkconf.h index ff7cf9da65..8c96d1b787 100644 --- a/include/wx/chkconf.h +++ b/include/wx/chkconf.h @@ -2414,6 +2414,17 @@ # endif #endif /* wxUSE_PROPGRID */ +#if wxUSE_TIPWINDOW +# if !wxUSE_POPUPWIN +# ifdef wxABORT_ON_CONFIG_ERROR +# error "wxTipWindow requires wxUSE_POPUPWIN" +# else +# undef wxUSE_POPUPWIN +# define wxUSE_POPUPWIN 1 +# endif +# endif +#endif /* wxUSE_TIPWINDOW */ + #endif /* wxUSE_GUI */ #endif /* _WX_CHKCONF_H_ */ diff --git a/include/wx/tipwin.h b/include/wx/tipwin.h index 08c0957e5b..ea3f85d29f 100644 --- a/include/wx/tipwin.h +++ b/include/wx/tipwin.h @@ -14,15 +14,8 @@ #if wxUSE_TIPWINDOW -#if wxUSE_POPUPWIN - #include "wx/popupwin.h" +#include "wx/popupwin.h" - #define wxTipWindowBase wxPopupTransientWindow -#else - #include "wx/frame.h" - - #define wxTipWindowBase wxFrame -#endif #include "wx/arrstr.h" class WXDLLIMPEXP_FWD_CORE wxTipWindowView; @@ -31,7 +24,7 @@ class WXDLLIMPEXP_FWD_CORE wxTipWindowView; // wxTipWindow // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_CORE wxTipWindow : public wxTipWindowBase +class WXDLLIMPEXP_CORE wxTipWindow : public wxPopupTransientWindow { public: // the mandatory ctor parameters are: the parent window and the text to @@ -69,12 +62,7 @@ protected: // event handlers void OnMouseClick(wxMouseEvent& event); -#if !wxUSE_POPUPWIN - void OnActivate(wxActivateEvent& event); - void OnKillFocus(wxFocusEvent& event); -#else // wxUSE_POPUPWIN virtual void OnDismiss() wxOVERRIDE; -#endif // wxUSE_POPUPWIN/!wxUSE_POPUPWIN private: wxArrayString m_textLines; diff --git a/src/generic/tipwin.cpp b/src/generic/tipwin.cpp index b3f56f51d6..b753c9655c 100644 --- a/src/generic/tipwin.cpp +++ b/src/generic/tipwin.cpp @@ -55,20 +55,12 @@ public: void OnMouseClick(wxMouseEvent& event); void OnMouseMove(wxMouseEvent& event); -#if !wxUSE_POPUPWIN - void OnKillFocus(wxFocusEvent& event); -#endif // wxUSE_POPUPWIN - // calculate the client rect we need to display the text void Adjust(const wxString& text, wxCoord maxLength); private: wxTipWindow* m_parent; -#if !wxUSE_POPUPWIN - long m_creationTime; -#endif // !wxUSE_POPUPWIN - wxDECLARE_EVENT_TABLE(); wxDECLARE_NO_COPY_CLASS(wxTipWindowView); }; @@ -81,15 +73,10 @@ private: // event tables // ---------------------------------------------------------------------------- -wxBEGIN_EVENT_TABLE(wxTipWindow, wxTipWindowBase) +wxBEGIN_EVENT_TABLE(wxTipWindow, wxPopupTransientWindow) EVT_LEFT_DOWN(wxTipWindow::OnMouseClick) EVT_RIGHT_DOWN(wxTipWindow::OnMouseClick) EVT_MIDDLE_DOWN(wxTipWindow::OnMouseClick) - -#if !wxUSE_POPUPWIN - EVT_KILL_FOCUS(wxTipWindow::OnKillFocus) - EVT_ACTIVATE(wxTipWindow::OnActivate) -#endif // !wxUSE_POPUPWIN wxEND_EVENT_TABLE() wxBEGIN_EVENT_TABLE(wxTipWindowView, wxWindow) @@ -100,10 +87,6 @@ wxBEGIN_EVENT_TABLE(wxTipWindowView, wxWindow) EVT_MIDDLE_DOWN(wxTipWindowView::OnMouseClick) EVT_MOTION(wxTipWindowView::OnMouseMove) - -#if !wxUSE_POPUPWIN - EVT_KILL_FOCUS(wxTipWindowView::OnKillFocus) -#endif // !wxUSE_POPUPWIN wxEND_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -115,13 +98,7 @@ wxTipWindow::wxTipWindow(wxWindow *parent, wxCoord maxLength, wxTipWindow** windowPtr, wxRect *rectBounds) -#if wxUSE_POPUPWIN : wxPopupTransientWindow(parent) -#else - : wxFrame(parent, wxID_ANY, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - wxNO_BORDER | wxFRAME_NO_TASKBAR ) -#endif { SetTipWindowPtr(windowPtr); if ( rectBounds ) @@ -136,9 +113,6 @@ wxTipWindow::wxTipWindow(wxWindow *parent, // set size, position and show it m_view = new wxTipWindowView(this); m_view->Adjust(text, maxLength); -#if !wxUSE_POPUPWIN - m_view->SetFocus(); -#endif int x, y; wxGetMousePosition(&x, &y); @@ -150,16 +124,11 @@ wxTipWindow::wxTipWindow(wxWindow *parent, // though y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this) / 2; -#if wxUSE_POPUPWIN Position(wxPoint(x, y), wxSize(0,0)); Popup(m_view); #ifdef __WXGTK__ m_view->CaptureMouse(); #endif -#else - Move(x, y); - Show(true); -#endif } wxTipWindow::~wxTipWindow() @@ -168,11 +137,9 @@ wxTipWindow::~wxTipWindow() { *m_windowPtr = NULL; } - #if wxUSE_POPUPWIN - #ifdef __WXGTK__ - if ( m_view->HasCapture() ) - m_view->ReleaseMouse(); - #endif + #ifdef __WXGTK__ + if ( m_view->HasCapture() ) + m_view->ReleaseMouse(); #endif } @@ -181,33 +148,11 @@ void wxTipWindow::OnMouseClick(wxMouseEvent& WXUNUSED(event)) Close(); } -#if wxUSE_POPUPWIN - void wxTipWindow::OnDismiss() { Close(); } -#else // !wxUSE_POPUPWIN - -void wxTipWindow::OnActivate(wxActivateEvent& event) -{ - if (!event.GetActive()) - Close(); -} - -void wxTipWindow::OnKillFocus(wxFocusEvent& WXUNUSED(event)) -{ - // Under Windows at least, we will get this immediately - // because when the view window is focussed, the - // tip window goes out of focus. -#ifdef __WXGTK__ - Close(); -#endif -} - -#endif // wxUSE_POPUPWIN // !wxUSE_POPUPWIN - void wxTipWindow::SetBoundingRect(const wxRect& rectBound) { m_rectBound = rectBound; @@ -221,7 +166,6 @@ void wxTipWindow::Close() m_windowPtr = NULL; } -#if wxUSE_POPUPWIN Show(false); #ifdef __WXGTK__ if ( m_view->HasCapture() ) @@ -232,9 +176,6 @@ void wxTipWindow::Close() #ifndef __WXOSX__ Destroy(); #endif -#else - wxFrame::Close(); -#endif } // ---------------------------------------------------------------------------- @@ -250,10 +191,6 @@ wxTipWindowView::wxTipWindowView(wxWindow *parent) SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); -#if !wxUSE_POPUPWIN - m_creationTime = wxGetLocalTime(); -#endif // !wxUSE_POPUPWIN - m_parent = (wxTipWindow*)parent; } @@ -373,13 +310,4 @@ void wxTipWindowView::OnMouseMove(wxMouseEvent& event) } } -#if !wxUSE_POPUPWIN -void wxTipWindowView::OnKillFocus(wxFocusEvent& WXUNUSED(event)) -{ - // Workaround the kill focus event happening just after creation in wxGTK - if (wxGetLocalTime() > m_creationTime + 1) - m_parent->Close(); -} -#endif // !wxUSE_POPUPWIN - #endif // wxUSE_TIPWINDOW From 01b0a50f8f854ae3962ffc0bb2c056a6c61e3f67 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 10 Jul 2020 02:22:30 +0200 Subject: [PATCH 2/3] Move wxTipWindow members used only by wxTipWindowView there No real changes, just move m_textLines and m_heightLine from wxTipWindow to wxTipWindowView as they were only used by the latter and so can just as well be its members. Also use this as an opportunity to replace wxArrayString with wxVector. --- include/wx/tipwin.h | 5 ----- src/generic/tipwin.cpp | 29 ++++++++++++++++++----------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/include/wx/tipwin.h b/include/wx/tipwin.h index ea3f85d29f..2f16cbb03a 100644 --- a/include/wx/tipwin.h +++ b/include/wx/tipwin.h @@ -16,8 +16,6 @@ #include "wx/popupwin.h" -#include "wx/arrstr.h" - class WXDLLIMPEXP_FWD_CORE wxTipWindowView; // ---------------------------------------------------------------------------- @@ -65,9 +63,6 @@ protected: virtual void OnDismiss() wxOVERRIDE; private: - wxArrayString m_textLines; - wxCoord m_heightLine; - wxTipWindowView *m_view; wxTipWindow** m_windowPtr; diff --git a/src/generic/tipwin.cpp b/src/generic/tipwin.cpp index b753c9655c..0e45e87c20 100644 --- a/src/generic/tipwin.cpp +++ b/src/generic/tipwin.cpp @@ -33,6 +33,8 @@ #include "wx/settings.h" #endif // WX_PRECOMP +#include "wx/vector.h" + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -61,6 +63,10 @@ public: private: wxTipWindow* m_parent; + wxVector m_textLines; + wxCoord m_heightLine; + + wxDECLARE_EVENT_TABLE(); wxDECLARE_NO_COPY_CLASS(wxTipWindowView); }; @@ -192,6 +198,8 @@ wxTipWindowView::wxTipWindowView(wxWindow *parent) SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); m_parent = (wxTipWindow*)parent; + + m_heightLine = 0; } void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength) @@ -204,7 +212,6 @@ void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength) wxString current; wxCoord height, width, widthMax = 0; - m_parent->m_heightLine = 0; bool breakLine = false; for ( const wxChar *p = text.c_str(); ; p++ ) @@ -215,10 +222,10 @@ void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength) if ( width > widthMax ) widthMax = width; - if ( height > m_parent->m_heightLine ) - m_parent->m_heightLine = height; + if ( height > m_heightLine ) + m_heightLine = height; - m_parent->m_textLines.Add(current); + m_textLines.push_back(current); if ( !*p ) { @@ -232,7 +239,7 @@ void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength) else if ( breakLine && (*p == wxT(' ') || *p == wxT('\t')) ) { // word boundary - break the line here - m_parent->m_textLines.Add(current); + m_textLines.push_back(current); current.clear(); breakLine = false; } @@ -246,14 +253,14 @@ void wxTipWindowView::Adjust(const wxString& text, wxCoord maxLength) if ( width > widthMax ) widthMax = width; - if ( height > m_parent->m_heightLine ) - m_parent->m_heightLine = height; + if ( height > m_heightLine ) + m_heightLine = height; } } // take into account the border size and the margins width = 2*(TEXT_MARGIN_X + 1) + widthMax; - height = 2*(TEXT_MARGIN_Y + 1) + wx_truncate_cast(wxCoord, m_parent->m_textLines.GetCount())*m_parent->m_heightLine; + height = 2*(TEXT_MARGIN_Y + 1) + wx_truncate_cast(wxCoord, m_textLines.size())*m_heightLine; m_parent->SetClientSize(width, height); SetSize(0, 0, width, height); } @@ -280,12 +287,12 @@ void wxTipWindowView::OnPaint(wxPaintEvent& WXUNUSED(event)) wxPoint pt; pt.x = TEXT_MARGIN_X; pt.y = TEXT_MARGIN_Y; - size_t count = m_parent->m_textLines.GetCount(); + const size_t count = m_textLines.size(); for ( size_t n = 0; n < count; n++ ) { - dc.DrawText(m_parent->m_textLines[n], pt); + dc.DrawText(m_textLines[n], pt); - pt.y += m_parent->m_heightLine; + pt.y += m_heightLine; } } From 10ac26d6e5639cb2ccc394a965feae57d2fe7908 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Fri, 10 Jul 2020 20:41:35 +0200 Subject: [PATCH 3/3] Fix DPI of wxTipWindow Take care to use the DPI of the display the window will be actually displayed on and not that of its parent window, which can be different. --- src/generic/tipwin.cpp | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/generic/tipwin.cpp b/src/generic/tipwin.cpp index 0e45e87c20..2ecb4b206b 100644 --- a/src/generic/tipwin.cpp +++ b/src/generic/tipwin.cpp @@ -33,6 +33,7 @@ #include "wx/settings.h" #endif // WX_PRECOMP +#include "wx/display.h" #include "wx/vector.h" // ---------------------------------------------------------------------------- @@ -116,19 +117,45 @@ wxTipWindow::wxTipWindow(wxWindow *parent, SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOTEXT)); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_INFOBK)); - // set size, position and show it - m_view = new wxTipWindowView(this); - m_view->Adjust(text, maxLength); - int x, y; wxGetMousePosition(&x, &y); - // we want to show the tip below the mouse, not over it + // move to the center of the target display so wxTipWindowView will use the + // correct DPI + wxPoint posScreen; + wxSize sizeScreen; + + const int displayNum = wxDisplay::GetFromPoint(wxPoint(x, y)); + if ( displayNum != wxNOT_FOUND ) + { + const wxRect rectScreen = wxDisplay(displayNum).GetGeometry(); + posScreen = rectScreen.GetPosition(); + sizeScreen = rectScreen.GetSize(); + } + else // outside of any display? + { + // just use the primary one then + posScreen = wxPoint(0, 0); + sizeScreen = wxGetDisplaySize(); + } + wxPoint center(posScreen.x + sizeScreen.GetWidth() / 2, + posScreen.y + sizeScreen.GetHeight() / 2); + Move(center, wxSIZE_NO_ADJUSTMENTS); + + // set size, position and show it + m_view = new wxTipWindowView(this); + m_view->Adjust(text, FromDIP(parent->ToDIP(maxLength)) ); + + // we want to show the tip below the mouse, not over it, make sure to not + // overflow into the next display // // NB: the reason we use "/ 2" here is that we don't know where the current // cursors hot spot is... it would be nice if we could find this out // though - y += wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this) / 2; + int cursorOffset = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, this) / 2; + if (y + cursorOffset >= posScreen.y + sizeScreen.GetHeight()) + cursorOffset = posScreen.y + sizeScreen.GetHeight() - y - 1; + y += cursorOffset; Position(wxPoint(x, y), wxSize(0,0)); Popup(m_view);