Windows QPA: Cache "forcedScreenForGLWindow" to avoid overhead

The fix for QTBUG-50371 caused an overhead when you hover over a
secondary window like a tool tip, menu or combo box due to the
forcedScreenForGLWindow() function being called, which loads
dx9.dll and sub-dlls and unloads them afterwards. This fix
caches the required info on the first call, and only refreshes
it when required by a display/settings change.

Fixes: QTBUG-73008
Change-Id: Ie604ba4034ad8041b971f5aa46bd43ae03decd55
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
bb10
Andre de la Rocha 2019-01-22 20:28:49 +01:00
parent fffe5d6225
commit 4c46e3189a
3 changed files with 30 additions and 7 deletions

View File

@ -1115,8 +1115,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::DisplayChangedEvent:
if (QWindowsTheme *t = QWindowsTheme::instance())
t->displayChanged();
QWindowsWindow::displayChanged();
return d->m_screenManager.handleDisplayChange(wParam, lParam);
case QtWindows::SettingChangedEvent:
QWindowsWindow::settingsChanged();
return d->m_screenManager.handleScreenChanges();
default:
break;

View File

@ -551,12 +551,6 @@ static QScreen *screenForName(const QWindow *w, const QString &name)
return winScreen;
}
static QScreen *forcedScreenForGLWindow(const QWindow *w)
{
const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen;
return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
}
static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
{
const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
@ -565,7 +559,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co
return orgPos;
// Workaround for QTBUG-50371
const QScreen *screenForGL = forcedScreenForGLWindow(w);
const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w);
if (!screenForGL)
return orgPos;
@ -1359,6 +1353,28 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled)
#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop)
}
bool QWindowsWindow::m_screenForGLInitialized = false;
void QWindowsWindow::displayChanged()
{
m_screenForGLInitialized = false;
}
void QWindowsWindow::settingsChanged()
{
m_screenForGLInitialized = false;
}
QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w)
{
static QString forceToScreen;
if (!m_screenForGLInitialized) {
forceToScreen = GpuDescription::detect().gpuSuitableScreen;
m_screenForGLInitialized = true;
}
return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
}
// Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain.
// Returns this window if it is the topmost ancestor.
QWindow *QWindowsWindow::topLevelOf(QWindow *w)

View File

@ -297,6 +297,9 @@ public:
void handleHidden();
void handleCompositionSettingsChanged();
static void displayChanged();
static void settingsChanged();
static QScreen *forcedScreenForGLWindow(const QWindow *w);
static QWindowsWindow *windowsWindowOf(const QWindow *w);
static QWindow *topLevelOf(QWindow *w);
static inline void *userDataOf(HWND hwnd);
@ -377,6 +380,8 @@ private:
HICON m_iconBig = 0;
void *m_surface = nullptr;
static bool m_screenForGLInitialized;
#if QT_CONFIG(vulkan)
// note: intentionally not using void * in order to avoid breaking x86
VkSurfaceKHR m_vkSurface = 0;