VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/UIDesktopWidgetWatchdog.cpp@ 82781

Last change on this file since 82781 was 79365, checked in by vboxsync, 5 years ago

Renaming VBoxGlobal to UICommon for bugref:9049 as planned.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.1 KB
Line 
1/* $Id: UIDesktopWidgetWatchdog.cpp 79365 2019-06-26 15:57:32Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIDesktopWidgetWatchdog class implementation.
4 */
5
6/*
7 * Copyright (C) 2015-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/* Qt includes: */
19#include <QApplication>
20#include <QDesktopWidget>
21#include <QScreen>
22#ifdef VBOX_WS_WIN
23# include <QLibrary>
24#endif
25#ifdef VBOX_WS_X11
26# include <QTimer>
27#endif
28
29/* GUI includes: */
30#include "UIDesktopWidgetWatchdog.h"
31#ifdef VBOX_WS_X11
32# include "UICommon.h"
33#endif /* VBOX_WS_X11 */
34
35/* Other VBox includes: */
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/ldr.h>
39#include <VBox/log.h>
40
41/* Platform includes: */
42#ifdef VBOX_WS_WIN
43# include <iprt/win/windows.h>
44#endif
45
46
47#ifdef VBOX_WS_WIN
48
49# ifndef DPI_ENUMS_DECLARED
50typedef enum _MONITOR_DPI_TYPE // gently stolen from MSDN
51{
52 MDT_EFFECTIVE_DPI = 0,
53 MDT_ANGULAR_DPI = 1,
54 MDT_RAW_DPI = 2,
55 MDT_DEFAULT = MDT_EFFECTIVE_DPI
56} MONITOR_DPI_TYPE;
57# endif
58typedef void (WINAPI *PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *);
59
60/** Set when dynamic API import is reoslved. */
61static bool volatile g_fResolved;
62/** Pointer to Shcore.dll!GetDpiForMonitor, introduced in windows 8.1. */
63static PFN_GetDpiForMonitor g_pfnGetDpiForMonitor = NULL;
64
65/** @returns true if all APIs found, false if missing APIs */
66static bool ResolveDynamicImports(void)
67{
68 if (!g_fResolved)
69 {
70 PFN_GetDpiForMonitor pfn = (decltype(pfn))RTLdrGetSystemSymbol("Shcore.dll", "GetDpiForMonitor");
71 g_pfnGetDpiForMonitor = pfn;
72 ASMCompilerBarrier();
73
74 g_fResolved = true;
75 }
76 return g_pfnGetDpiForMonitor != NULL;
77}
78
79static BOOL CALLBACK MonitorEnumProcF(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lpClipRect, LPARAM dwData)
80{
81 /* These required for clipped screens only: */
82 RT_NOREF(hdcMonitor, lpClipRect);
83
84 /* Acquire effective DPI (available since Windows 8.1): */
85 AssertReturn(g_pfnGetDpiForMonitor, false);
86 UINT uOutX = 0;
87 UINT uOutY = 0;
88 g_pfnGetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &uOutX, &uOutY);
89 reinterpret_cast<QList<QPair<int, int> >*>(dwData)->append(qMakePair(uOutX, uOutY));
90
91 return TRUE;
92}
93
94#endif /* VBOX_WS_WIN */
95
96
97#ifdef VBOX_WS_X11
98
99/** QWidget extension used as
100 * an invisible window on the basis of which we
101 * can calculate available host-screen geometry. */
102class UIInvisibleWindow : public QWidget
103{
104 Q_OBJECT;
105
106signals:
107
108 /** Notifies listeners about host-screen available-geometry was calulated.
109 * @param iHostScreenIndex holds the index of the host-screen this window created for.
110 * @param availableGeometry holds the available-geometry of the host-screen this window created for. */
111 void sigHostScreenAvailableGeometryCalculated(int iHostScreenIndex, QRect availableGeometry);
112
113public:
114
115 /** Constructs invisible window for the host-screen with @a iHostScreenIndex. */
116 UIInvisibleWindow(int iHostScreenIndex);
117
118private slots:
119
120 /** Performs fallback drop. */
121 void sltFallback();
122
123private:
124
125 /** Move @a pEvent handler. */
126 void moveEvent(QMoveEvent *pEvent);
127 /** Resize @a pEvent handler. */
128 void resizeEvent(QResizeEvent *pEvent);
129
130 /** Holds the index of the host-screen this window created for. */
131 const int m_iHostScreenIndex;
132
133 /** Holds whether the move event came. */
134 bool m_fMoveCame;
135 /** Holds whether the resize event came. */
136 bool m_fResizeCame;
137};
138
139
140/*********************************************************************************************************************************
141* Class UIInvisibleWindow implementation. *
142*********************************************************************************************************************************/
143
144UIInvisibleWindow::UIInvisibleWindow(int iHostScreenIndex)
145 : QWidget(0, Qt::Window | Qt::FramelessWindowHint)
146 , m_iHostScreenIndex(iHostScreenIndex)
147 , m_fMoveCame(false)
148 , m_fResizeCame(false)
149{
150 /* Resize to minimum size of 1 pixel: */
151 resize(1, 1);
152 /* Apply visual and mouse-event mask for that 1 pixel: */
153 setMask(QRect(0, 0, 1, 1));
154 /* For composite WMs make this 1 pixel transparent: */
155 if (uiCommon().isCompositingManagerRunning())
156 setAttribute(Qt::WA_TranslucentBackground);
157 /* Install fallback handler: */
158 QTimer::singleShot(5000, this, SLOT(sltFallback()));
159}
160
161void UIInvisibleWindow::sltFallback()
162{
163 /* Sanity check for fallback geometry: */
164 QRect fallbackGeometry(x(), y(), width(), height());
165 if ( fallbackGeometry.width() <= 1
166 || fallbackGeometry.height() <= 1)
167 fallbackGeometry = gpDesktop->screenGeometry(m_iHostScreenIndex);
168 LogRel(("GUI: UIInvisibleWindow::sltFallback: %s event haven't came. "
169 "Screen: %d, work area: %dx%d x %dx%d\n",
170 !m_fMoveCame ? "Move" : !m_fResizeCame ? "Resize" : "Some",
171 m_iHostScreenIndex, fallbackGeometry.x(), fallbackGeometry.y(), fallbackGeometry.width(), fallbackGeometry.height()));
172 emit sigHostScreenAvailableGeometryCalculated(m_iHostScreenIndex, fallbackGeometry);
173}
174
175void UIInvisibleWindow::moveEvent(QMoveEvent *pEvent)
176{
177 /* We do have both move and resize events,
178 * with no idea who will come first, but we need
179 * to send a final signal after last of events arrived. */
180
181 /* Call to base-class: */
182 QWidget::moveEvent(pEvent);
183
184 /* Ignore 'not-yet-shown' case: */
185 if (!isVisible())
186 return;
187
188 /* Mark move event as received: */
189 m_fMoveCame = true;
190
191 /* If the resize event already came: */
192 if (m_fResizeCame)
193 {
194 /* Notify listeners about host-screen available-geometry was calulated: */
195 LogRel2(("GUI: UIInvisibleWindow::moveEvent: Screen: %d, work area: %dx%d x %dx%d\n", m_iHostScreenIndex,
196 x(), y(), width(), height()));
197 emit sigHostScreenAvailableGeometryCalculated(m_iHostScreenIndex, QRect(x(), y(), width(), height()));
198 }
199}
200
201void UIInvisibleWindow::resizeEvent(QResizeEvent *pEvent)
202{
203 /* We do have both move and resize events,
204 * with no idea who will come first, but we need
205 * to send a final signal after last of events arrived. */
206
207 /* Call to base-class: */
208 QWidget::resizeEvent(pEvent);
209
210 /* Ignore 'not-yet-shown' case: */
211 if (!isVisible())
212 return;
213
214 /* Mark resize event as received: */
215 m_fResizeCame = true;
216
217 /* If the move event already came: */
218 if (m_fMoveCame)
219 {
220 /* Notify listeners about host-screen available-geometry was calulated: */
221 LogRel2(("GUI: UIInvisibleWindow::resizeEvent: Screen: %d, work area: %dx%d x %dx%d\n", m_iHostScreenIndex,
222 x(), y(), width(), height()));
223 emit sigHostScreenAvailableGeometryCalculated(m_iHostScreenIndex, QRect(x(), y(), width(), height()));
224 }
225}
226
227#endif /* VBOX_WS_X11 */
228
229
230/*********************************************************************************************************************************
231* Class UIDesktopWidgetWatchdog implementation. *
232*********************************************************************************************************************************/
233
234/* static */
235UIDesktopWidgetWatchdog *UIDesktopWidgetWatchdog::s_pInstance = 0;
236
237/* static */
238void UIDesktopWidgetWatchdog::create()
239{
240 /* Make sure instance isn't created: */
241 AssertReturnVoid(!s_pInstance);
242
243 /* Create/prepare instance: */
244 new UIDesktopWidgetWatchdog;
245 AssertReturnVoid(s_pInstance);
246 s_pInstance->prepare();
247}
248
249/* static */
250void UIDesktopWidgetWatchdog::destroy()
251{
252 /* Make sure instance is created: */
253 AssertReturnVoid(s_pInstance);
254
255 /* Cleanup/destroy instance: */
256 s_pInstance->cleanup();
257 delete s_pInstance;
258 AssertReturnVoid(!s_pInstance);
259}
260
261UIDesktopWidgetWatchdog::UIDesktopWidgetWatchdog()
262{
263 /* Initialize instance: */
264 s_pInstance = this;
265}
266
267UIDesktopWidgetWatchdog::~UIDesktopWidgetWatchdog()
268{
269 /* Deinitialize instance: */
270 s_pInstance = 0;
271}
272
273int UIDesktopWidgetWatchdog::overallDesktopWidth() const
274{
275 /* Redirect call to desktop-widget: */
276 return QApplication::desktop()->width();
277}
278
279int UIDesktopWidgetWatchdog::overallDesktopHeight() const
280{
281 /* Redirect call to desktop-widget: */
282 return QApplication::desktop()->height();
283}
284
285int UIDesktopWidgetWatchdog::screenCount() const
286{
287 /* Redirect call to desktop-widget: */
288 return QApplication::desktop()->screenCount();
289}
290
291int UIDesktopWidgetWatchdog::primaryScreen() const
292{
293 /* Redirect call to desktop-widget: */
294 return QApplication::desktop()->primaryScreen();
295}
296
297int UIDesktopWidgetWatchdog::screenNumber(const QWidget *pWidget) const
298{
299 /* Redirect call to desktop-widget: */
300 return QApplication::desktop()->screenNumber(pWidget);
301}
302
303int UIDesktopWidgetWatchdog::screenNumber(const QPoint &point) const
304{
305 /* Redirect call to desktop-widget: */
306 return QApplication::desktop()->screenNumber(point);
307}
308
309const QRect UIDesktopWidgetWatchdog::screenGeometry(int iHostScreenIndex /* = -1 */) const
310{
311 /* Make sure index is valid: */
312 if (iHostScreenIndex < 0 || iHostScreenIndex >= screenCount())
313 iHostScreenIndex = QApplication::desktop()->primaryScreen();
314 AssertReturn(iHostScreenIndex >= 0 && iHostScreenIndex < screenCount(), QRect());
315
316 /* Redirect call to desktop-widget: */
317 return QApplication::desktop()->screenGeometry(iHostScreenIndex);
318}
319
320const QRect UIDesktopWidgetWatchdog::screenGeometry(const QWidget *pWidget) const
321{
322 /* Redirect call to wrapper above: */
323 return screenGeometry(screenNumber(pWidget));
324}
325
326const QRect UIDesktopWidgetWatchdog::screenGeometry(const QPoint &point) const
327{
328 /* Redirect call to wrapper above: */
329 return screenGeometry(screenNumber(point));
330}
331
332const QRect UIDesktopWidgetWatchdog::availableGeometry(int iHostScreenIndex /* = -1 */) const
333{
334 /* Make sure index is valid: */
335 if (iHostScreenIndex < 0 || iHostScreenIndex >= screenCount())
336 iHostScreenIndex = QApplication::desktop()->primaryScreen();
337 AssertReturn(iHostScreenIndex >= 0 && iHostScreenIndex < screenCount(), QRect());
338
339#ifdef VBOX_WS_X11
340 /* Get cached available-geometry: */
341 const QRect availableGeometry = m_availableGeometryData.value(iHostScreenIndex);
342 /* Return cached available-geometry if it's valid or screen-geometry otherwise: */
343 return availableGeometry.isValid() ? availableGeometry :
344 QApplication::desktop()->screenGeometry(iHostScreenIndex);
345#else /* !VBOX_WS_X11 */
346 /* Redirect call to desktop-widget: */
347 return QApplication::desktop()->availableGeometry(iHostScreenIndex);
348#endif /* !VBOX_WS_X11 */
349}
350
351const QRect UIDesktopWidgetWatchdog::availableGeometry(const QWidget *pWidget) const
352{
353 /* Redirect call to wrapper above: */
354 return availableGeometry(screenNumber(pWidget));
355}
356
357const QRect UIDesktopWidgetWatchdog::availableGeometry(const QPoint &point) const
358{
359 /* Redirect call to wrapper above: */
360 return availableGeometry(screenNumber(point));
361}
362
363const QRegion UIDesktopWidgetWatchdog::overallScreenRegion() const
364{
365 /* Calculate region: */
366 QRegion region;
367 for (int iScreenIndex = 0; iScreenIndex < gpDesktop->screenCount(); ++iScreenIndex)
368 {
369 /* Get enumerated screen's available area: */
370 QRect rect = gpDesktop->screenGeometry(iScreenIndex);
371#ifdef VBOX_WS_WIN
372 /* On Windows host window can exceed the available
373 * area in maximized/sticky-borders state: */
374 rect.adjust(-10, -10, 10, 10);
375#endif /* VBOX_WS_WIN */
376 /* Append rectangle: */
377 region += rect;
378 }
379 /* Return region: */
380 return region;
381}
382
383const QRegion UIDesktopWidgetWatchdog::overallAvailableRegion() const
384{
385 /* Calculate region: */
386 QRegion region;
387 for (int iScreenIndex = 0; iScreenIndex < gpDesktop->screenCount(); ++iScreenIndex)
388 {
389 /* Get enumerated screen's available area: */
390 QRect rect = gpDesktop->availableGeometry(iScreenIndex);
391#ifdef VBOX_WS_WIN
392 /* On Windows host window can exceed the available
393 * area in maximized/sticky-borders state: */
394 rect.adjust(-10, -10, 10, 10);
395#endif /* VBOX_WS_WIN */
396 /* Append rectangle: */
397 region += rect;
398 }
399 /* Return region: */
400 return region;
401}
402
403#ifdef VBOX_WS_X11
404bool UIDesktopWidgetWatchdog::isFakeScreenDetected() const
405{
406 // WORKAROUND:
407 // In 5.6.1 Qt devs taught the XCB plugin to silently swap last detached screen
408 // with a fake one, and there is no API-way to distinguish fake from real one
409 // because all they do is erasing output for the last real screen, keeping
410 // all other screen attributes stale. Gladly output influencing screen name
411 // so we can use that horrible workaround to detect a fake XCB screen.
412 return qApp->screens().size() == 0 /* zero-screen case is impossible after 5.6.1 */
413 || (qApp->screens().size() == 1 && qApp->screens().first()->name() == ":0.0");
414}
415#endif /* VBOX_WS_X11 */
416
417double UIDesktopWidgetWatchdog::devicePixelRatio(int iHostScreenIndex /* = -1 */)
418{
419 /* First, we should check whether the screen is valid: */
420 QScreen *pScreen = iHostScreenIndex == -1
421 ? QGuiApplication::primaryScreen()
422 : QGuiApplication::screens().value(iHostScreenIndex);
423 AssertPtrReturn(pScreen, 1.0);
424
425 /* Then acquire device-pixel-ratio: */
426 return pScreen->devicePixelRatio();
427}
428
429double UIDesktopWidgetWatchdog::devicePixelRatio(QWidget *pWidget)
430{
431 /* Redirect call to wrapper above: */
432 return devicePixelRatio(screenNumber(pWidget));
433}
434
435double UIDesktopWidgetWatchdog::devicePixelRatioActual(int iHostScreenIndex /* = -1 */)
436{
437 /* First, we should check whether the screen is valid: */
438 QScreen *pScreen = 0;
439 if (iHostScreenIndex == -1)
440 {
441 pScreen = QGuiApplication::primaryScreen();
442 iHostScreenIndex = QGuiApplication::screens().indexOf(pScreen);
443 }
444 else
445 pScreen = QGuiApplication::screens().value(iHostScreenIndex);
446 AssertPtrReturn(pScreen, 1.0);
447
448#ifdef VBOX_WS_WIN
449 /* Enumerate available monitors through EnumDisplayMonitors if GetDpiForMonitor is available: */
450 if (ResolveDynamicImports())
451 {
452 QList<QPair<int, int> > listOfScreenDPI;
453 EnumDisplayMonitors(0, 0, MonitorEnumProcF, (LPARAM)&listOfScreenDPI);
454 if (iHostScreenIndex >= 0 && iHostScreenIndex < listOfScreenDPI.size())
455 {
456 const QPair<int, int> dpiPair = listOfScreenDPI.at(iHostScreenIndex);
457 if (dpiPair.first > 0)
458 return (double)dpiPair.first / 96 /* dpi unawarness value */;
459 }
460 }
461
462#endif /* VBOX_WS_WIN */
463
464 /* Then acquire device-pixel-ratio: */
465 return pScreen->devicePixelRatio();
466}
467
468double UIDesktopWidgetWatchdog::devicePixelRatioActual(QWidget *pWidget)
469{
470 /* Redirect call to wrapper above: */
471 return devicePixelRatioActual(screenNumber(pWidget));
472}
473
474void UIDesktopWidgetWatchdog::sltHostScreenAdded(QScreen *pHostScreen)
475{
476// printf("UIDesktopWidgetWatchdog::sltHostScreenAdded(%d)\n", screenCount());
477
478 /* Listen for screen signals: */
479 connect(pHostScreen, &QScreen::geometryChanged,
480 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenResized);
481 connect(pHostScreen, &QScreen::availableGeometryChanged,
482 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized);
483
484# ifdef VBOX_WS_X11
485 /* Update host-screen configuration: */
486 updateHostScreenConfiguration();
487# endif /* VBOX_WS_X11 */
488
489 /* Notify listeners: */
490 emit sigHostScreenCountChanged(screenCount());
491}
492
493void UIDesktopWidgetWatchdog::sltHostScreenRemoved(QScreen *pHostScreen)
494{
495// printf("UIDesktopWidgetWatchdog::sltHostScreenRemoved(%d)\n", screenCount());
496
497 /* Forget about screen signals: */
498 disconnect(pHostScreen, &QScreen::geometryChanged,
499 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenResized);
500 disconnect(pHostScreen, &QScreen::availableGeometryChanged,
501 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized);
502
503# ifdef VBOX_WS_X11
504 /* Update host-screen configuration: */
505 updateHostScreenConfiguration();
506# endif /* VBOX_WS_X11 */
507
508 /* Notify listeners: */
509 emit sigHostScreenCountChanged(screenCount());
510}
511
512void UIDesktopWidgetWatchdog::sltHandleHostScreenResized(const QRect &geometry)
513{
514 /* Get the screen: */
515 QScreen *pScreen = sender() ? qobject_cast<QScreen*>(sender()) : 0;
516 AssertPtrReturnVoid(pScreen);
517
518 /* Determine screen index: */
519 const int iHostScreenIndex = qApp->screens().indexOf(pScreen);
520 AssertReturnVoid(iHostScreenIndex != -1);
521 LogRel(("GUI: UIDesktopWidgetWatchdog::sltHandleHostScreenResized: "
522 "Screen %d is formally resized to: %dx%d x %dx%d\n",
523 iHostScreenIndex, geometry.x(), geometry.y(),
524 geometry.width(), geometry.height()));
525
526# ifdef VBOX_WS_X11
527 /* Update host-screen available-geometry: */
528 updateHostScreenAvailableGeometry(iHostScreenIndex);
529# endif /* VBOX_WS_X11 */
530
531 /* Notify listeners: */
532 emit sigHostScreenResized(iHostScreenIndex);
533}
534
535void UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized(const QRect &availableGeometry)
536{
537 /* Get the screen: */
538 QScreen *pScreen = sender() ? qobject_cast<QScreen*>(sender()) : 0;
539 AssertPtrReturnVoid(pScreen);
540
541 /* Determine screen index: */
542 const int iHostScreenIndex = qApp->screens().indexOf(pScreen);
543 AssertReturnVoid(iHostScreenIndex != -1);
544 LogRel(("GUI: UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized: "
545 "Screen %d work area is formally resized to: %dx%d x %dx%d\n",
546 iHostScreenIndex, availableGeometry.x(), availableGeometry.y(),
547 availableGeometry.width(), availableGeometry.height()));
548
549# ifdef VBOX_WS_X11
550 /* Update host-screen available-geometry: */
551 updateHostScreenAvailableGeometry(iHostScreenIndex);
552# endif /* VBOX_WS_X11 */
553
554 /* Notify listeners: */
555 emit sigHostScreenWorkAreaResized(iHostScreenIndex);
556}
557
558#ifdef VBOX_WS_X11
559void UIDesktopWidgetWatchdog::sltHandleHostScreenAvailableGeometryCalculated(int iHostScreenIndex, QRect availableGeometry)
560{
561 LogRel(("GUI: UIDesktopWidgetWatchdog::sltHandleHostScreenAvailableGeometryCalculated: "
562 "Screen %d work area is actually resized to: %dx%d x %dx%d\n",
563 iHostScreenIndex, availableGeometry.x(), availableGeometry.y(),
564 availableGeometry.width(), availableGeometry.height()));
565
566 /* Apply received data: */
567 const bool fSendSignal = m_availableGeometryData.value(iHostScreenIndex).isValid();
568 m_availableGeometryData[iHostScreenIndex] = availableGeometry;
569 /* Forget finished worker: */
570 AssertPtrReturnVoid(m_availableGeometryWorkers.value(iHostScreenIndex));
571 m_availableGeometryWorkers.value(iHostScreenIndex)->disconnect();
572 m_availableGeometryWorkers.value(iHostScreenIndex)->deleteLater();
573 m_availableGeometryWorkers[iHostScreenIndex] = 0;
574
575 /* Notify listeners: */
576 if (fSendSignal)
577 emit sigHostScreenWorkAreaRecalculated(iHostScreenIndex);
578}
579#endif /* VBOX_WS_X11 */
580
581void UIDesktopWidgetWatchdog::prepare()
582{
583 /* Prepare connections: */
584 connect(qApp, &QGuiApplication::screenAdded,
585 this, &UIDesktopWidgetWatchdog::sltHostScreenAdded);
586 connect(qApp, &QGuiApplication::screenRemoved,
587 this, &UIDesktopWidgetWatchdog::sltHostScreenRemoved);
588 foreach (QScreen *pHostScreen, qApp->screens())
589 {
590 connect(pHostScreen, &QScreen::geometryChanged,
591 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenResized);
592 connect(pHostScreen, &QScreen::availableGeometryChanged,
593 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized);
594 }
595
596#ifdef VBOX_WS_X11
597 /* Update host-screen configuration: */
598 updateHostScreenConfiguration();
599#endif /* VBOX_WS_X11 */
600}
601
602void UIDesktopWidgetWatchdog::cleanup()
603{
604 /* Cleanup connections: */
605 disconnect(qApp, &QGuiApplication::screenAdded,
606 this, &UIDesktopWidgetWatchdog::sltHostScreenAdded);
607 disconnect(qApp, &QGuiApplication::screenRemoved,
608 this, &UIDesktopWidgetWatchdog::sltHostScreenRemoved);
609 foreach (QScreen *pHostScreen, qApp->screens())
610 {
611 disconnect(pHostScreen, &QScreen::geometryChanged,
612 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenResized);
613 disconnect(pHostScreen, &QScreen::availableGeometryChanged,
614 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenWorkAreaResized);
615 }
616
617#ifdef VBOX_WS_X11
618 /* Cleanup existing workers finally: */
619 cleanupExistingWorkers();
620#endif /* VBOX_WS_X11 */
621}
622
623#ifdef VBOX_WS_X11
624void UIDesktopWidgetWatchdog::updateHostScreenConfiguration(int cHostScreenCount /* = -1 */)
625{
626 /* Acquire new host-screen count: */
627 if (cHostScreenCount == -1)
628 cHostScreenCount = screenCount();
629
630 /* Cleanup existing workers first: */
631 cleanupExistingWorkers();
632
633 /* Resize workers vectors to new host-screen count: */
634 m_availableGeometryWorkers.resize(cHostScreenCount);
635 m_availableGeometryData.resize(cHostScreenCount);
636
637 /* Update host-screen available-geometry for each particular host-screen: */
638 for (int iHostScreenIndex = 0; iHostScreenIndex < cHostScreenCount; ++iHostScreenIndex)
639 updateHostScreenAvailableGeometry(iHostScreenIndex);
640}
641
642void UIDesktopWidgetWatchdog::updateHostScreenAvailableGeometry(int iHostScreenIndex)
643{
644 /* Make sure index is valid: */
645 if (iHostScreenIndex < 0 || iHostScreenIndex >= screenCount())
646 iHostScreenIndex = QApplication::desktop()->primaryScreen();
647 AssertReturnVoid(iHostScreenIndex >= 0 && iHostScreenIndex < screenCount());
648
649 /* Create invisible frame-less window worker: */
650 UIInvisibleWindow *pWorker = new UIInvisibleWindow(iHostScreenIndex);
651 AssertPtrReturnVoid(pWorker);
652 {
653 /* Remember created worker (replace if necessary): */
654 if (m_availableGeometryWorkers.value(iHostScreenIndex))
655 delete m_availableGeometryWorkers.value(iHostScreenIndex);
656 m_availableGeometryWorkers[iHostScreenIndex] = pWorker;
657
658 /* Get the screen-geometry: */
659 const QRect hostScreenGeometry = screenGeometry(iHostScreenIndex);
660
661 /* Connect worker listener: */
662 connect(pWorker, &UIInvisibleWindow::sigHostScreenAvailableGeometryCalculated,
663 this, &UIDesktopWidgetWatchdog::sltHandleHostScreenAvailableGeometryCalculated);
664
665 /* Place worker to corresponding host-screen: */
666 pWorker->move(hostScreenGeometry.center());
667 /* And finally, maximize it: */
668 pWorker->showMaximized();
669 }
670}
671
672void UIDesktopWidgetWatchdog::cleanupExistingWorkers()
673{
674 /* Destroy existing workers: */
675 qDeleteAll(m_availableGeometryWorkers);
676 /* And clear their vector: */
677 m_availableGeometryWorkers.clear();
678}
679
680# include "UIDesktopWidgetWatchdog.moc"
681#endif /* VBOX_WS_X11 */
682
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use