VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineViewScale.cpp

Last change on this file was 106061, checked in by vboxsync, 4 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1/* $Id: UIMachineViewScale.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMachineViewScale class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QMainWindow>
30#include <QTimer>
31
32/* GUI includes */
33#include "UIDesktopWidgetWatchdog.h"
34#include "UIExtraDataManager.h"
35#include "UIFrameBuffer.h"
36#include "UILoggingDefs.h"
37#include "UIMachine.h"
38#include "UIMachineLogic.h"
39#include "UIMachineViewScale.h"
40#include "UIMachineWindow.h"
41
42/* COM includes: */
43#include "CGraphicsAdapter.h"
44
45/* Other VBox includes: */
46#include <VBox/VBoxOGL.h> // For VBOX_OGL_SCALE_FACTOR_MULTIPLIER
47
48
49UIMachineViewScale::UIMachineViewScale(UIMachineWindow *pMachineWindow, ulong uScreenId)
50 : UIMachineView(pMachineWindow, uScreenId)
51{
52}
53
54void UIMachineViewScale::sltPerformGuestScale()
55{
56 /* Assign new frame-buffer logical-size: */
57 QSize scaledSize = size();
58 const double dDevicePixelRatioFormal = frameBuffer()->devicePixelRatio();
59 const double dDevicePixelRatioActual = frameBuffer()->devicePixelRatioActual();
60 const bool fUseUnscaledHiDPIOutput = frameBuffer()->useUnscaledHiDPIOutput();
61 scaledSize *= dDevicePixelRatioFormal;
62 if (!fUseUnscaledHiDPIOutput)
63 scaledSize /= dDevicePixelRatioActual;
64 frameBuffer()->setScaledSize(scaledSize);
65 frameBuffer()->performRescale();
66
67 /* If scaled-size is valid: */
68 if (scaledSize.isValid())
69 {
70 /* Propagate scale-factor to 3D service if necessary: */
71 bool fAccelerate3DEnabled = false;
72 uimachine()->acquireWhetherAccelerate3DEnabled(fAccelerate3DEnabled);
73 if (fAccelerate3DEnabled)
74 {
75 double xScaleFactor = (double)scaledSize.width() / frameBuffer()->width();
76 double yScaleFactor = (double)scaledSize.height() / frameBuffer()->height();
77#if defined(VBOX_WS_WIN) || defined(VBOX_WS_NIX)
78 // WORKAROUND:
79 // On Windows and Linux opposing to macOS it's only Qt which can auto scale up,
80 // not 3D overlay itself, so for auto scale-up mode we have to take that into account.
81 if (!fUseUnscaledHiDPIOutput)
82 {
83 xScaleFactor *= dDevicePixelRatioActual;
84 yScaleFactor *= dDevicePixelRatioActual;
85 }
86#endif /* VBOX_WS_WIN || VBOX_WS_NIX */
87 uimachine()->notifyScaleFactorChange(m_uScreenId,
88 (uint32_t)(xScaleFactor * VBOX_OGL_SCALE_FACTOR_MULTIPLIER),
89 (uint32_t)(yScaleFactor * VBOX_OGL_SCALE_FACTOR_MULTIPLIER));
90 }
91 }
92
93 /* Scale the pause-pixmap: */
94 updateScaledPausePixmap();
95
96 /* Update viewport: */
97 viewport()->repaint();
98
99 /* Update machine-view sliders: */
100 updateSliders();
101}
102
103bool UIMachineViewScale::eventFilter(QObject *pWatched, QEvent *pEvent)
104{
105 if (pWatched != 0 && pWatched == viewport())
106 {
107 switch (pEvent->type())
108 {
109 case QEvent::Resize:
110 {
111 /* Perform the actual resize: */
112 sltPerformGuestScale();
113 break;
114 }
115 default:
116 break;
117 }
118 }
119
120 return UIMachineView::eventFilter(pWatched, pEvent);
121}
122
123void UIMachineViewScale::applyMachineViewScaleFactor()
124{
125 /* If scaled-size is valid: */
126 const QSize scaledSize = frameBuffer()->scaledSize();
127 const double dDevicePixelRatioActual = frameBuffer()->devicePixelRatioActual(); Q_UNUSED(dDevicePixelRatioActual);
128 const bool fUseUnscaledHiDPIOutput = frameBuffer()->useUnscaledHiDPIOutput();
129 if (scaledSize.isValid())
130 {
131 /* Propagate scale-factor to 3D service if necessary: */
132 bool fAccelerate3DEnabled = false;
133 uimachine()->acquireWhetherAccelerate3DEnabled(fAccelerate3DEnabled);
134 if (fAccelerate3DEnabled)
135 {
136 double xScaleFactor = (double)scaledSize.width() / frameBuffer()->width();
137 double yScaleFactor = (double)scaledSize.height() / frameBuffer()->height();
138#if defined(VBOX_WS_WIN) || defined(VBOX_WS_NIX)
139 // WORKAROUND:
140 // On Windows and Linux opposing to macOS it's only Qt which can auto scale up,
141 // not 3D overlay itself, so for auto scale-up mode we have to take that into account.
142 if (!fUseUnscaledHiDPIOutput)
143 {
144 xScaleFactor *= dDevicePixelRatioActual;
145 yScaleFactor *= dDevicePixelRatioActual;
146 }
147#endif /* VBOX_WS_WIN || VBOX_WS_NIX */
148 uimachine()->notifyScaleFactorChange(m_uScreenId,
149 (uint32_t)(xScaleFactor * VBOX_OGL_SCALE_FACTOR_MULTIPLIER),
150 (uint32_t)(yScaleFactor * VBOX_OGL_SCALE_FACTOR_MULTIPLIER));
151 }
152 }
153
154 /* Take unscaled HiDPI output mode into account: */
155 frameBuffer()->setUseUnscaledHiDPIOutput(fUseUnscaledHiDPIOutput);
156 /* Propagate unscaled-hidpi-output feature to 3D service if necessary: */
157 bool fAccelerate3DEnabled = false;
158 uimachine()->acquireWhetherAccelerate3DEnabled(fAccelerate3DEnabled);
159 if (fAccelerate3DEnabled)
160 uimachine()->notifyHiDPIOutputPolicyChange(fUseUnscaledHiDPIOutput);
161
162 /* Perform frame-buffer rescaling: */
163 frameBuffer()->performRescale();
164
165 /* Update console's display viewport and 3D overlay: */
166 updateViewport();
167}
168
169void UIMachineViewScale::resendSizeHint()
170{
171 /* Skip if VM isn't running/paused yet: */
172 if ( !uimachine()->isRunning()
173 && !uimachine()->isPaused())
174 return;
175
176 /* Get the last guest-screen size-hint, taking the scale factor into account. */
177 const QSize sizeHint = scaledBackward(storedGuestScreenSizeHint());
178 LogRel(("GUI: UIMachineViewScale::resendSizeHint: Restoring guest size-hint for screen %d to %dx%d\n",
179 (int)screenId(), sizeHint.width(), sizeHint.height()));
180
181 /* Expand current limitations: */
182 setMaximumGuestSize(sizeHint);
183
184 /* Send saved size-hint to the guest: */
185 uimachine()->setScreenVisibleHostDesires(screenId(), guestScreenVisibilityStatus());
186 uimachine()->setVideoModeHint(screenId(),
187 guestScreenVisibilityStatus(),
188 false /* change origin? */,
189 0 /* origin x */, 0 /* origin y */,
190 sizeHint.width(), sizeHint.height(),
191 0 /* bits per pixel */,
192 true /* notify? */);
193}
194
195QSize UIMachineViewScale::sizeHint() const
196{
197 /* Base-class have its own thoughts about size-hint
198 * but scale-mode needs no size-hint to be set: */
199 return QSize();
200}
201
202QRect UIMachineViewScale::workingArea() const
203{
204 return gpDesktop->availableGeometry(this);
205}
206
207QSize UIMachineViewScale::calculateMaxGuestSize() const
208{
209 /* 1) The calculation below is not reliable on some (X11) platforms until we
210 * have been visible for a fraction of a second, so so the best we can
211 * otherwise.
212 * 2) We also get called early before "machineWindow" has been fully
213 * initialised, at which time we can't perform the calculation. */
214 if (!isVisible())
215 return workingArea().size() * 0.95;
216 /* The area taken up by the machine window on the desktop, including window
217 * frame, title, menu bar and status bar. */
218 QSize windowSize = machineWindow()->frameGeometry().size();
219 /* The window shouldn't be allowed to expand beyond the working area
220 * unless it already does. In that case the guest shouldn't expand it
221 * any further though. */
222 QSize maximumSize = workingArea().size().expandedTo(windowSize);
223 /* The current size of the machine display. */
224 QSize centralWidgetSize = machineWindow()->centralWidget()->size();
225 /* To work out how big the guest display can get without the window going
226 * over the maximum size we calculated above, we work out how much space
227 * the other parts of the window (frame, menu bar, status bar and so on)
228 * take up and subtract that space from the maximum window size. The
229 * central widget shouldn't be bigger than the window, but we bound it for
230 * sanity (or insanity) reasons. */
231 return maximumSize - (windowSize - centralWidgetSize.boundedTo(windowSize));
232}
233
234void UIMachineViewScale::updateSliders()
235{
236 if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)
237 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
238 if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)
239 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
240}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette