VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/seamless/UIMachineViewSeamless.cpp@ 35740

Last change on this file since 35740 was 32174, checked in by vboxsync, 14 years ago

FE/Qt: New running VM core: Cumulative fix for VBoxDefs::ResizeEventType processing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: UIMachineViewSeamless.cpp 32174 2010-09-01 12:52:17Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UIMachineViewSeamless class implementation
6 */
7
8/*
9 * Copyright (C) 2010 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Global includes */
21#include <QApplication>
22#include <QDesktopWidget>
23#include <QMainWindow>
24#include <QTimer>
25#ifdef Q_WS_MAC
26#include <QMenuBar>
27#endif
28#ifdef Q_WS_X11
29#include <limits.h>
30#endif
31
32/* Local includes */
33#include "VBoxGlobal.h"
34#include "UISession.h"
35#include "UIMachineLogicSeamless.h"
36#include "UIMachineWindow.h"
37#include "UIMachineViewSeamless.h"
38#include "UIFrameBuffer.h"
39
40UIMachineViewSeamless::UIMachineViewSeamless( UIMachineWindow *pMachineWindow
41 , ulong uScreenId
42#ifdef VBOX_WITH_VIDEOHWACCEL
43 , bool bAccelerate2DVideo
44#endif
45 )
46 : UIMachineView( pMachineWindow
47 , uScreenId
48#ifdef VBOX_WITH_VIDEOHWACCEL
49 , bAccelerate2DVideo
50#endif
51 )
52 , m_fShouldWeDoResize(false)
53 , m_pSyncBlocker(0)
54{
55 /* Load machine view settings: */
56 loadMachineViewSettings();
57
58 /* Prepare viewport: */
59 prepareViewport();
60
61 /* Prepare frame buffer: */
62 prepareFrameBuffer();
63
64 /* Prepare common things: */
65 prepareCommon();
66
67 /* Prepare event-filters: */
68 prepareFilters();
69
70 /* Prepare connections: */
71 prepareConnections();
72
73 /* Prepare console connections: */
74 prepareConsoleConnections();
75
76 /* Prepare seamless view: */
77 prepareSeamless();
78
79 /* Initialization: */
80 sltMachineStateChanged();
81 sltAdditionsStateChanged();
82}
83
84UIMachineViewSeamless::~UIMachineViewSeamless()
85{
86 /* Cleanup seamless mode: */
87 cleanupSeamless();
88
89 /* Cleanup frame buffer: */
90 cleanupFrameBuffer();
91}
92
93void UIMachineViewSeamless::sltPerformGuestResize(const QSize &toSize)
94{
95 if (uisession()->isGuestSupportsGraphics())
96 {
97 /* Get machine window: */
98 QMainWindow *pMachineWindow = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
99 qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow()) : 0;
100
101 /* If this slot is invoked directly then use the passed size otherwise get
102 * the available size for the guest display. We assume here that centralWidget()
103 * contains this view only and gives it all available space: */
104 QSize newSize(toSize.isValid() ? toSize : pMachineWindow ? pMachineWindow->centralWidget()->size() : QSize());
105 AssertMsg(newSize.isValid(), ("Size should be valid!\n"));
106
107 /* Do not send the same hints as we already have: */
108 if ((newSize.width() == storedConsoleSize().width()) && (newSize.height() == storedConsoleSize().height()))
109 return;
110
111 /* We only actually send the hint if either an explicit new size was given
112 * (e.g. if the request was triggered directly by a console resize event) or
113 * if no explicit size was specified but a resize is flagged as being needed
114 * (e.g. the autoresize was just enabled and the console was resized while it was disabled). */
115 if (toSize.isValid() || m_fShouldWeDoResize)
116 {
117 /* Remember the new size: */
118 storeConsoleSize(newSize.width(), newSize.height());
119
120 /* Send new size-hint to the guest: */
121 session().GetConsole().GetDisplay().SetVideoModeHint(newSize.width(), newSize.height(), 0, screenId());
122 }
123
124 /* We had requested resize now, rejecting other accident requests: */
125 m_fShouldWeDoResize = false;
126 }
127}
128
129void UIMachineViewSeamless::sltAdditionsStateChanged()
130{
131 // TODO: Exit seamless if additions doesn't support it!
132}
133
134void UIMachineViewSeamless::sltDesktopResized()
135{
136 // TODO: Try to resize framebuffer according new desktop size, exit seamless if resize is failed!
137
138 /* If the desktop geometry is set automatically, this will update it: */
139 calculateDesktopGeometry();
140}
141
142bool UIMachineViewSeamless::event(QEvent *pEvent)
143{
144 switch (pEvent->type())
145 {
146 case VBoxDefs::SetRegionEventType:
147 {
148 /* Get region-update event: */
149 UISetRegionEvent *pSetRegionEvent = static_cast<UISetRegionEvent*>(pEvent);
150
151 /* Apply new region: */
152 if (pSetRegionEvent->region() != m_lastVisibleRegion)
153 {
154 m_lastVisibleRegion = pSetRegionEvent->region();
155 machineWindowWrapper()->setMask(m_lastVisibleRegion);
156 }
157 return true;
158 }
159
160 case VBoxDefs::ResizeEventType:
161 {
162 /* Some situations require framebuffer resize events to be ignored at all,
163 * leaving machine-window, machine-view and framebuffer sizes preserved: */
164 if (uisession()->isGuestResizeIgnored())
165 return true;
166
167 /* We are starting to perform machine-view resize,
168 * we should temporary ignore other if they are trying to be: */
169 bool fWasMachineWindowResizeIgnored = isMachineWindowResizeIgnored();
170 setMachineWindowResizeIgnored(true);
171
172 /* Get guest resize-event: */
173 UIResizeEvent *pResizeEvent = static_cast<UIResizeEvent*>(pEvent);
174
175 /* Perform framebuffer resize: */
176 frameBuffer()->resizeEvent(pResizeEvent);
177
178 /* Reapply maximum size restriction for machine-view: */
179 setMaximumSize(sizeHint());
180
181 /* Store the new size to prevent unwanted resize hints being sent back: */
182 storeConsoleSize(pResizeEvent->width(), pResizeEvent->height());
183
184 /* Perform machine-view resize: */
185 resize(pResizeEvent->width(), pResizeEvent->height());
186
187 /* Let our toplevel widget calculate its sizeHint properly: */
188 QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
189
190#ifdef Q_WS_MAC
191 machineLogic()->updateDockIconSize(screenId(), pResizeEvent->width(), pResizeEvent->height());
192#endif /* Q_WS_MAC */
193
194 /* Update machine-view sliders: */
195 updateSliders();
196
197 /* Report to the VM thread that we finished resizing: */
198 session().GetConsole().GetDisplay().ResizeCompleted(screenId());
199
200 /* We are finishing to perform machine-view resize: */
201 setMachineWindowResizeIgnored(fWasMachineWindowResizeIgnored);
202
203 /* We also recalculate the desktop geometry if this is determined
204 * automatically. In fact, we only need this on the first resize,
205 * but it is done every time to keep the code simpler. */
206 calculateDesktopGeometry();
207
208 /* Emit a signal about guest was resized: */
209 emit resizeHintDone();
210
211 /* Unlock after processing guest resize event: */
212 if (m_pSyncBlocker && m_pSyncBlocker->isRunning())
213 m_pSyncBlocker->quit();
214
215 pEvent->accept();
216 return true;
217 }
218
219 default:
220 break;
221 }
222 return UIMachineView::event(pEvent);
223}
224
225bool UIMachineViewSeamless::eventFilter(QObject *pWatched, QEvent *pEvent)
226{
227 /* Who are we watching? */
228 QMainWindow *pMainDialog = machineWindowWrapper() && machineWindowWrapper()->machineWindow() ?
229 qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow()) : 0;
230
231 if (pWatched != 0 && pWatched == pMainDialog)
232 {
233 switch (pEvent->type())
234 {
235 case QEvent::Resize:
236 {
237 /* Send guest-resize hint only if top window resizing to required dimension: */
238 QResizeEvent *pResizeEvent = static_cast<QResizeEvent*>(pEvent);
239 if (pResizeEvent->size() != workingArea().size())
240 break;
241
242 /* Set the "guest needs to resize" hint.
243 * This hint is acted upon when (and only when) the autoresize property is "true": */
244 m_fShouldWeDoResize = uisession()->isGuestSupportsGraphics();
245 if (m_fShouldWeDoResize)
246 QTimer::singleShot(0, this, SLOT(sltPerformGuestResize()));
247 break;
248 }
249 default:
250 break;
251 }
252 }
253
254 return UIMachineView::eventFilter(pWatched, pEvent);
255}
256
257void UIMachineViewSeamless::prepareCommon()
258{
259 /* Base class common settings: */
260 UIMachineView::prepareCommon();
261
262 /* Setup size-policy: */
263 setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
264 /* Maximum size to sizehint: */
265 setMaximumSize(sizeHint());
266 /* Minimum size is ignored: */
267 setMinimumSize(0, 0);
268 /* No scrollbars: */
269 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
270 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
271}
272
273void UIMachineViewSeamless::prepareFilters()
274{
275 /* Base class filters: */
276 UIMachineView::prepareFilters();
277
278#ifdef Q_WS_MAC // TODO: Is it really needed? See UIMachineViewSeamless::eventFilter(...);
279 /* Menu bar filter: */
280 qobject_cast<QMainWindow*>(machineWindowWrapper()->machineWindow())->menuBar()->installEventFilter(this);
281#endif
282}
283
284void UIMachineViewSeamless::prepareConnections()
285{
286 connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(sltDesktopResized()));
287}
288
289void UIMachineViewSeamless::prepareConsoleConnections()
290{
291 /* Base class connections: */
292 UIMachineView::prepareConsoleConnections();
293
294 /* Guest additions state-change updater: */
295 connect(uisession(), SIGNAL(sigAdditionsStateChange()), this, SLOT(sltAdditionsStateChanged()));
296}
297
298void UIMachineViewSeamless::prepareSeamless()
299{
300 /* Set seamless feature flag to the guest: */
301 session().GetConsole().GetDisplay().SetSeamlessMode(true);
302 /* Create sync-blocker: */
303 m_pSyncBlocker = new UIMachineViewBlocker;
304}
305
306void UIMachineViewSeamless::cleanupSeamless()
307{
308 /* If machine still running: */
309 if (uisession()->isRunning())
310 {
311 /* Reset seamless feature flag of the guest: */
312 session().GetConsole().GetDisplay().SetSeamlessMode(false);
313
314 /* Rollback seamless frame-buffer size to normal: */
315 machineWindowWrapper()->machineWindow()->hide();
316 sltPerformGuestResize(guestSizeHint());
317 m_pSyncBlocker->exec();
318
319 /* Delete sync-blocker: */
320 m_pSyncBlocker->deleteLater();
321 }
322}
323
324QRect UIMachineViewSeamless::workingArea()
325{
326 /* Get corresponding screen: */
327 int iScreen = static_cast<UIMachineLogicSeamless*>(machineLogic())->hostScreenForGuestScreen(screenId());
328 /* Return available geometry for that screen: */
329 return vboxGlobal().availableGeometry(iScreen);
330}
331
332void UIMachineViewSeamless::calculateDesktopGeometry()
333{
334 /* This method should not get called until we have initially set up the desktop geometry type: */
335 Assert((desktopGeometryType() != DesktopGeo_Invalid));
336 /* If we are not doing automatic geometry calculation then there is nothing to do: */
337 if (desktopGeometryType() == DesktopGeo_Automatic)
338 m_desktopGeometry = workingArea().size();
339}
340
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use