VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp@ 35564

Last change on this file since 35564 was 35564, checked in by vboxsync, 13 years ago

FE/Qt: s/VBOX_WITH_PIDFILE/VBOX_GUI_WITH_PIDFILE/ plus Makefile.kmk change

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.5 KB
Line 
1/* $Id: UISession.cpp 35564 2011-01-14 13:52:02Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UISession stuff 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 <QWidget>
23#include <QTimer>
24
25/* Local includes */
26#include "UISession.h"
27#include "UIMachine.h"
28#include "UIActionsPool.h"
29#include "UIMachineLogic.h"
30#include "UIMachineWindow.h"
31#include "UIMachineMenuBar.h"
32#include "VBoxProblemReporter.h"
33#include "UIFirstRunWzd.h"
34#include "UIConsoleEventHandler.h"
35#ifdef VBOX_WITH_VIDEOHWACCEL
36# include "VBoxFBOverlay.h"
37# include "UIFrameBuffer.h"
38#endif
39
40#ifdef Q_WS_X11
41# include <QX11Info>
42# include <X11/Xlib.h>
43# include <X11/Xutil.h>
44# ifndef VBOX_WITHOUT_XCURSOR
45# include <X11/Xcursor/Xcursor.h>
46# endif
47#endif
48
49UISession::UISession(UIMachine *pMachine, CSession &sessionReference)
50 : QObject(pMachine)
51 /* Base variables: */
52 , m_pMachine(pMachine)
53 , m_session(sessionReference)
54 /* Common variables: */
55 , m_pMenuPool(0)
56#ifdef VBOX_WITH_VIDEOHWACCEL
57 , m_FrameBufferVector(sessionReference.GetMachine().GetMonitorCount())
58#endif
59 , m_machineState(KMachineState_Null)
60#if defined(Q_WS_WIN)
61 , m_alphaCursor(0)
62#endif
63 /* Common flags: */
64 , m_fIsFirstTimeStarted(false)
65 , m_fIsIgnoreRuntimeMediumsChanging(false)
66 , m_fIsGuestResizeIgnored(false)
67 , m_fIsSeamlessModeRequested(false)
68 , m_fIsAutoCaptureDisabled(false)
69 /* Guest additions flags: */
70 , m_ulGuestAdditionsRunLevel(0)
71 , m_fIsGuestSupportsGraphics(false)
72 , m_fIsGuestSupportsSeamless(false)
73 /* Mouse flags: */
74 , m_fNumLock(false)
75 , m_fCapsLock(false)
76 , m_fScrollLock(false)
77 , m_uNumLockAdaptionCnt(2)
78 , m_uCapsLockAdaptionCnt(2)
79 /* Mouse flags: */
80 , m_fIsMouseSupportsAbsolute(false)
81 , m_fIsMouseSupportsRelative(false)
82 , m_fIsMouseHostCursorNeeded(false)
83 , m_fIsMouseCaptured(false)
84 , m_fIsMouseIntegrated(true)
85 , m_fIsValidPointerShapePresent(false)
86 , m_fIsHidingHostPointer(true)
87{
88 /* Explicit initialize the console event handler */
89 UIConsoleEventHandler::instance(this);
90
91 /* Add console event connections */
92 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
93 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
94
95 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool)),
96 this, SLOT(sltMouseCapabilityChange(bool, bool, bool)));
97
98 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
99 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
100
101 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
102 this, SLOT(sltStateChange(KMachineState)));
103
104 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
105 this, SLOT(sltAdditionsChange()));
106
107 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
108 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
109
110 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
111 this, SIGNAL(sigMediumChange(CMediumAttachment)));
112
113 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
114 this, SIGNAL(sigUSBControllerChange()));
115
116 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
117 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
118
119 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
120 this, SIGNAL(sigSharedFolderChange()));
121
122 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
123 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
124
125#ifdef Q_WS_MAC
126 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
127 this, SIGNAL(sigShowWindows()),
128 Qt::QueuedConnection);
129#endif /* Q_WS_MAC */
130
131 /* Prepare main menu: */
132 prepareMenuPool();
133
134 /* Load uisession settings: */
135 loadSessionSettings();
136}
137
138UISession::~UISession()
139{
140 /* Save uisession settings: */
141 saveSessionSettings();
142
143 /* Cleanup main menu: */
144 cleanupMenuPool();
145
146 /* Destroy the console event handler */
147 UIConsoleEventHandler::destroy();
148
149#if defined(Q_WS_WIN)
150 /* Destroy alpha cursor: */
151 if (m_alphaCursor)
152 DestroyIcon(m_alphaCursor);
153#endif
154
155#ifdef VBOX_WITH_VIDEOHWACCEL
156 for (int i = m_FrameBufferVector.size() - 1; i >= 0; --i)
157 {
158 UIFrameBuffer *pFb = m_FrameBufferVector[i];
159 if (pFb)
160 {
161 /* Warn framebuffer about its no more necessary: */
162 pFb->setDeleted(true);
163 /* Detach framebuffer from Display: */
164 CDisplay display = session().GetConsole().GetDisplay();
165 display.SetFramebuffer(i, CFramebuffer(NULL));
166 /* Release the reference: */
167 pFb->Release();
168 }
169 }
170#endif
171}
172
173void UISession::powerUp()
174{
175 /* Do nothing if we had started already: */
176 if (isRunning() || isPaused())
177 return;
178
179 /* Prepare powerup: */
180 preparePowerUp();
181
182 /* Get current machine/console: */
183 CMachine machine = session().GetMachine();
184 CConsole console = session().GetConsole();
185
186 /* Power UP machine: */
187 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled(machine) ?
188 console.PowerUpPaused() : console.PowerUp();
189
190 /* Check for immediate failure: */
191 if (!console.isOk())
192 {
193 if (vboxGlobal().showStartVMErrors())
194 vboxProblem().cannotStartMachine(console);
195 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
196 return;
197 }
198
199 /* Guard progressbar warnings from auto-closing: */
200 if (uimachine()->machineLogic())
201 uimachine()->machineLogic()->setPreventAutoClose(true);
202
203 /* Show "Starting/Restoring" progress dialog: */
204 if (isSaved())
205 vboxProblem().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_restore_90px.png", mainMachineWindow(), true, 0);
206 else
207 vboxProblem().showModalProgressDialog(progress, machine.GetName(), ":/progress_start_90px.png", mainMachineWindow(), true);
208
209 /* Check for a progress failure: */
210 if (progress.GetResultCode() != 0)
211 {
212 if (vboxGlobal().showStartVMErrors())
213 vboxProblem().cannotStartMachine(progress);
214 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
215 return;
216 }
217
218 /* Allow further auto-closing: */
219 if (uimachine()->machineLogic())
220 uimachine()->machineLogic()->setPreventAutoClose(false);
221
222 /* Check if we missed a really quick termination after successful startup, and process it if we did: */
223 if (isTurnedOff())
224 {
225 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
226 return;
227 }
228
229 /* Check if the required virtualization features are active. We get this
230 * info only when the session is active. */
231 bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetIs64Bit();
232 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx();
233 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
234 bool fIsVirtEnabled = console.GetDebugger().GetHWVirtExEnabled();
235 if (fRecommendVirtEx && !fIsVirtEnabled)
236 {
237 bool fShouldWeClose;
238
239 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx);
240
241 QApplication::processEvents();
242 setPause(true);
243
244 if (fIs64BitsGuest)
245 fShouldWeClose = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
246 else
247 fShouldWeClose = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
248
249 if (fShouldWeClose)
250 {
251 /* At this point the console is powered up. So we have to close
252 * this session again. */
253 CProgress progress = console.PowerDown();
254 if (console.isOk())
255 {
256 /* Guard progressbar warnings from auto-closing: */
257 if (uimachine()->machineLogic())
258 uimachine()->machineLogic()->setPreventAutoClose(true);
259 /* Show the power down progress dialog */
260 vboxProblem().showModalProgressDialog(progress, machine.GetName(), ":/progress_poweroff_90px.png", mainMachineWindow(), true);
261 if (progress.GetResultCode() != 0)
262 vboxProblem().cannotStopMachine(progress);
263 /* Allow further auto-closing: */
264 if (uimachine()->machineLogic())
265 uimachine()->machineLogic()->setPreventAutoClose(false);
266 }
267 else
268 vboxProblem().cannotStopMachine(console);
269 /* Now signal the destruction of the rest. */
270 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
271 return;
272 }
273 else
274 setPause(false);
275 }
276
277#ifdef VBOX_WITH_VIDEOHWACCEL
278 LogRel(("2D video acceleration is %s.\n",
279 machine.GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable()
280 ? "enabled"
281 : "disabled"));
282#endif
283
284#ifdef VBOX_GUI_WITH_PIDFILE
285 vboxGlobal().createPidfile();
286#endif
287
288 /* Warn listeners about machine was started: */
289 emit sigMachineStarted();
290}
291
292UIActionsPool* UISession::actionsPool() const
293{
294 return m_pMachine->actionsPool();
295}
296
297QWidget* UISession::mainMachineWindow() const
298{
299 return uimachine()->machineLogic()->mainMachineWindow()->machineWindow();
300}
301
302UIMachineLogic* UISession::machineLogic() const
303{
304 return uimachine()->machineLogic();
305}
306
307QMenu* UISession::newMenu(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
308{
309 /* Create new menu: */
310 QMenu *pMenu = m_pMenuPool->createMenu(actionsPool(), fOptions);
311
312 /* Re-init menu pool for the case menu were recreated: */
313 reinitMenuPool();
314
315 /* Return newly created menu: */
316 return pMenu;
317}
318
319QMenuBar* UISession::newMenuBar(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
320{
321 /* Create new menubar: */
322 QMenuBar *pMenuBar = m_pMenuPool->createMenuBar(actionsPool(), fOptions);
323
324 /* Re-init menu pool for the case menu were recreated: */
325 reinitMenuPool();
326
327 /* Return newly created menubar: */
328 return pMenuBar;
329}
330
331bool UISession::setPause(bool fOn)
332{
333 /* Commenting it out as isPaused() could reflect
334 * quite obsolete state due to synchronization: */
335 //if (isPaused() == fOn)
336 // return true;
337
338 CConsole console = session().GetConsole();
339
340 if (fOn)
341 console.Pause();
342 else
343 console.Resume();
344
345 bool ok = console.isOk();
346 if (!ok)
347 {
348 if (fOn)
349 vboxProblem().cannotPauseMachine(console);
350 else
351 vboxProblem().cannotResumeMachine(console);
352 }
353
354 return ok;
355}
356
357void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
358{
359 CMachine machine = session().GetMachine();
360 CVirtualBox vbox = vboxGlobal().virtualBox();
361
362 /*
363 * Flag indicating whether we want to do the usual .ISO mounting or not.
364 * First try updating the Guest Additions directly without mounting the .ISO.
365 */
366 bool fDoMount = false;
367 /* Auto-update in GUI currently is disabled. */
368#ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI
369 fDoMount = true;
370#else
371 CGuest guest = session().GetConsole().GetGuest();
372 /* Since we are going to show a modal progress dialog we don't want to wait for the whole
373 * update progress being complete - the user might need to interact with the VM to confirm (WHQL)
374 * popups - instead we only wait until the actual update process was started. */
375 CProgress progressInstall = guest.UpdateGuestAdditions(strSource,
376 AdditionsUpdateFlag_WaitForUpdateStartOnly);
377 bool fResult = guest.isOk();
378 if (fResult)
379 {
380 vboxProblem().showModalProgressDialog(progressInstall, tr("Install"), ":/progress_install_guest_additions_90px.png",
381 mainMachineWindow(), true, 500 /* 500ms delay. */);
382 if (progressInstall.GetCanceled())
383 return;
384
385 HRESULT rc = progressInstall.GetResultCode();
386 if (!progressInstall.isOk() || rc != S_OK)
387 {
388 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS
389 * simply isn't supported yet), so silently fall back to "old" .ISO
390 * mounting method. */
391 if ( !SUCCEEDED_WARNING(rc)
392 && rc != VBOX_E_NOT_SUPPORTED)
393 {
394 vboxProblem().cannotUpdateGuestAdditions(progressInstall, mainMachineWindow());
395
396 /* Log the error message in the release log. */
397 QString strErr = progressInstall.GetErrorInfo().GetText();
398 if (!strErr.isEmpty())
399 LogRel(("%s\n", strErr.toLatin1().constData()));
400 }
401 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */
402 }
403 }
404#endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
405
406 if (fDoMount) /* Fallback to only mounting the .ISO file. */
407 {
408 QString strUuid;
409 CMedium image = vbox.FindMedium(strSource, KDeviceType_DVD);
410 if (image.isNull())
411 {
412 image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite);
413 if (vbox.isOk())
414 strUuid = image.GetId();
415 }
416 else
417 strUuid = image.GetId();
418
419 if (!vbox.isOk())
420 {
421 vboxProblem().cannotOpenMedium(0, vbox, VBoxDefs::MediumType_DVD, strSource);
422 return;
423 }
424
425 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n"));
426
427 QString strCntName;
428 LONG iCntPort = -1, iCntDevice = -1;
429 /* Searching for the first suitable slot */
430 {
431 CStorageControllerVector controllers = machine.GetStorageControllers();
432 int i = 0;
433 while (i < controllers.size() && strCntName.isNull())
434 {
435 CStorageController controller = controllers[i];
436 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
437 int j = 0;
438 while (j < attachments.size() && strCntName.isNull())
439 {
440 CMediumAttachment attachment = attachments[j];
441 if (attachment.GetType() == KDeviceType_DVD)
442 {
443 strCntName = controller.GetName();
444 iCntPort = attachment.GetPort();
445 iCntDevice = attachment.GetDevice();
446 }
447 ++ j;
448 }
449 ++ i;
450 }
451 }
452
453 if (!strCntName.isNull())
454 {
455 /* Create a new VBoxMedium: */
456 VBoxMedium vboxMedium(image, VBoxDefs::MediumType_DVD, KMediumState_Created);
457 /* Register it in GUI internal list: */
458 vboxGlobal().addMedium(vboxMedium);
459
460 /* Mount medium to the predefined port/device: */
461 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), false /* force */);
462 if (!machine.isOk())
463 {
464 /* Ask for force mounting: */
465 if (vboxProblem().cannotRemountMedium(0, machine, vboxMedium, true /* mount? */, true /* retry? */) == QIMessageBox::Ok)
466 {
467 /* Force mount medium to the predefined port/device: */
468 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), true /* force */);
469 if (!machine.isOk())
470 vboxProblem().cannotRemountMedium(0, machine, vboxMedium, true /* mount? */, false /* retry? */);
471 }
472 }
473 }
474 else
475 vboxProblem().cannotMountGuestAdditions(machine.GetName());
476 }
477}
478
479void UISession::sltCloseVirtualSession()
480{
481 /* Recursively close all the usual modal & popup widgets... */
482 QWidget *widget = QApplication::activeModalWidget() ?
483 QApplication::activeModalWidget() :
484 QApplication::activePopupWidget() ?
485 QApplication::activePopupWidget() : 0;
486 if (widget)
487 {
488 widget->hide();
489 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
490 return;
491 }
492
493 /* Recursively close all the opened warnings... */
494 if (vboxProblem().isAnyWarningShown())
495 {
496 vboxProblem().closeAllWarnings();
497 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
498 return;
499 }
500
501 /* Finally, ask for closing virtual machine: */
502 QTimer::singleShot(0, m_pMachine, SLOT(sltCloseVirtualMachine()));
503}
504
505void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
506{
507 /* In case of shape data is present: */
508 if (shape.size() > 0)
509 {
510 /* We are ignoring visibility flag: */
511 m_fIsHidingHostPointer = false;
512
513 /* And updating current cursor shape: */
514 setPointerShape(shape.data(), fAlpha,
515 hotCorner.x(), hotCorner.y(),
516 size.width(), size.height());
517 }
518 /* In case of shape data is NOT present: */
519 else
520 {
521 /* Remember if we should hide the cursor: */
522 m_fIsHidingHostPointer = !fVisible;
523 }
524
525 /* Notify listeners about mouse capability changed: */
526 emit sigMousePointerShapeChange();
527
528}
529
530void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fNeedsHostCursor)
531{
532 /* Check if something had changed: */
533 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
534 || m_fIsMouseSupportsRelative != fSupportsRelative
535 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
536 {
537 /* Store new data: */
538 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
539 m_fIsMouseSupportsRelative = fSupportsRelative;
540 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
541
542 /* Notify listeners about mouse capability changed: */
543 emit sigMouseCapabilityChange();
544 }
545}
546
547void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
548{
549 /* Check if something had changed: */
550 if ( m_fNumLock != fNumLock
551 || m_fCapsLock != fCapsLock
552 || m_fScrollLock != fScrollLock)
553 {
554 /* Store new num lock data: */
555 if (m_fNumLock != fNumLock)
556 {
557 m_fNumLock = fNumLock;
558 m_uNumLockAdaptionCnt = 2;
559 }
560
561 /* Store new caps lock data: */
562 if (m_fCapsLock != fCapsLock)
563 {
564 m_fCapsLock = fCapsLock;
565 m_uCapsLockAdaptionCnt = 2;
566 }
567
568 /* Store new scroll lock data: */
569 if (m_fScrollLock != fScrollLock)
570 {
571 m_fScrollLock = fScrollLock;
572 }
573
574 /* Notify listeners about mouse capability changed: */
575 emit sigKeyboardLedsChange();
576 }
577}
578
579void UISession::sltStateChange(KMachineState state)
580{
581 /* Check if something had changed: */
582 if (m_machineState != state)
583 {
584 /* Store new data: */
585 m_machineState = state;
586
587 /* Notify listeners about machine state changed: */
588 emit sigMachineStateChange();
589 }
590}
591
592void UISession::sltAdditionsChange()
593{
594 /* Get our guest: */
595 CGuest guest = session().GetConsole().GetGuest();
596
597 /* Variable flags: */
598 ULONG ulGuestAdditionsRunLevel = guest.GetAdditionsRunLevel();
599 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
600 bool fIsGuestSupportsSeamless = guest.GetSupportsSeamless();
601
602 /* Check if something had changed: */
603 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
604 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
605 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
606 {
607 /* Store new data: */
608 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
609 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
610 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
611
612 /* Notify listeners about guest additions state changed: */
613 emit sigAdditionsStateChange();
614 }
615}
616
617void UISession::prepareMenuPool()
618{
619 m_pMenuPool = new UIMachineMenuBar;
620}
621
622void UISession::loadSessionSettings()
623{
624 /* Get uisession machine: */
625 CMachine machine = session().GetConsole().GetMachine();
626
627 /* Load extra-data settings: */
628 {
629 /* Temporary: */
630 QString strSettings;
631
632 /* Is there should be First RUN Wizard? */
633 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
634 if (strSettings == "yes")
635 m_fIsFirstTimeStarted = true;
636
637 /* Ignore mediums mounted at runtime? */
638 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
639 if (strSettings == "no")
640 m_fIsIgnoreRuntimeMediumsChanging = true;
641
642 /* Should guest autoresize? */
643 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
644 QAction *pGuestAutoresizeSwitch = uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize);
645 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
646
647#if 0 /* Disabled for now! */
648# ifdef Q_WS_WIN
649 /* Disable host screen-saver if requested: */
650 if (vboxGlobal().settings().hostScreenSaverDisabled())
651 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0);
652# endif /* Q_WS_WIN */
653#endif
654 }
655}
656
657void UISession::saveSessionSettings()
658{
659 /* Get uisession machine: */
660 CMachine machine = session().GetConsole().GetMachine();
661
662 /* Save extra-data settings: */
663 {
664 /* Disable First RUN Wizard for the since now: */
665 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
666
667 /* Remember if guest should autoresize: */
668 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
669 uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ?
670 QString() : "off");
671
672#if 0 /* Disabled for now! */
673# ifdef Q_WS_WIN
674 /* Restore screen-saver activity to system default: */
675 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, 0, 0);
676# endif /* Q_WS_WIN */
677#endif
678 }
679}
680
681void UISession::cleanupMenuPool()
682{
683 delete m_pMenuPool;
684 m_pMenuPool = 0;
685}
686
687WId UISession::winId() const
688{
689 return mainMachineWindow()->winId();
690}
691
692void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
693 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
694{
695 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
696
697 m_fIsValidPointerShapePresent = false;
698 const uchar *srcAndMaskPtr = pShapeData;
699 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
700 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
701 uint srcShapePtrScan = uWidth * 4;
702
703#if defined (Q_WS_WIN)
704
705 BITMAPV5HEADER bi;
706 HBITMAP hBitmap;
707 void *lpBits;
708
709 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
710 bi.bV5Size = sizeof(BITMAPV5HEADER);
711 bi.bV5Width = uWidth;
712 bi.bV5Height = - (LONG)uHeight;
713 bi.bV5Planes = 1;
714 bi.bV5BitCount = 32;
715 bi.bV5Compression = BI_BITFIELDS;
716 bi.bV5RedMask = 0x00FF0000;
717 bi.bV5GreenMask = 0x0000FF00;
718 bi.bV5BlueMask = 0x000000FF;
719 if (fHasAlpha)
720 bi.bV5AlphaMask = 0xFF000000;
721 else
722 bi.bV5AlphaMask = 0;
723
724 HDC hdc = GetDC(NULL);
725
726 /* Create the DIB section with an alpha channel: */
727 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
728
729 ReleaseDC(NULL, hdc);
730
731 HBITMAP hMonoBitmap = NULL;
732 if (fHasAlpha)
733 {
734 /* Create an empty mask bitmap: */
735 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
736 }
737 else
738 {
739 /* Word aligned AND mask. Will be allocated and created if necessary. */
740 uint8_t *pu8AndMaskWordAligned = NULL;
741
742 /* Width in bytes of the original AND mask scan line. */
743 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
744
745 if (cbAndMaskScan & 1)
746 {
747 /* Original AND mask is not word aligned. */
748
749 /* Allocate memory for aligned AND mask. */
750 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
751
752 Assert(pu8AndMaskWordAligned);
753
754 if (pu8AndMaskWordAligned)
755 {
756 /* According to MSDN the padding bits must be 0.
757 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
758 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
759 Assert(u32PaddingBits < 8);
760 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
761
762 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
763 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
764
765 uint8_t *src = (uint8_t *)srcAndMaskPtr;
766 uint8_t *dst = pu8AndMaskWordAligned;
767
768 unsigned i;
769 for (i = 0; i < uHeight; i++)
770 {
771 memcpy(dst, src, cbAndMaskScan);
772
773 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
774
775 src += cbAndMaskScan;
776 dst += cbAndMaskScan + 1;
777 }
778 }
779 }
780
781 /* Create the AND mask bitmap: */
782 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
783 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
784
785 if (pu8AndMaskWordAligned)
786 {
787 RTMemTmpFree(pu8AndMaskWordAligned);
788 }
789 }
790
791 Assert(hBitmap);
792 Assert(hMonoBitmap);
793 if (hBitmap && hMonoBitmap)
794 {
795 DWORD *dstShapePtr = (DWORD *) lpBits;
796
797 for (uint y = 0; y < uHeight; y ++)
798 {
799 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
800 srcShapePtr += srcShapePtrScan;
801 dstShapePtr += uWidth;
802 }
803
804 ICONINFO ii;
805 ii.fIcon = FALSE;
806 ii.xHotspot = uXHot;
807 ii.yHotspot = uYHot;
808 ii.hbmMask = hMonoBitmap;
809 ii.hbmColor = hBitmap;
810
811 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
812 Assert(hAlphaCursor);
813 if (hAlphaCursor)
814 {
815 /* Set the new cursor: */
816 m_cursor = QCursor(hAlphaCursor);
817 if (m_alphaCursor)
818 DestroyIcon(m_alphaCursor);
819 m_alphaCursor = hAlphaCursor;
820 m_fIsValidPointerShapePresent = true;
821 }
822 }
823
824 if (hMonoBitmap)
825 DeleteObject(hMonoBitmap);
826 if (hBitmap)
827 DeleteObject(hBitmap);
828
829#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
830
831 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
832 Assert(img);
833 if (img)
834 {
835 img->xhot = uXHot;
836 img->yhot = uYHot;
837
838 XcursorPixel *dstShapePtr = img->pixels;
839
840 for (uint y = 0; y < uHeight; y ++)
841 {
842 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
843
844 if (!fHasAlpha)
845 {
846 /* Convert AND mask to the alpha channel: */
847 uchar byte = 0;
848 for (uint x = 0; x < uWidth; x ++)
849 {
850 if (!(x % 8))
851 byte = *(srcAndMaskPtr ++);
852 else
853 byte <<= 1;
854
855 if (byte & 0x80)
856 {
857 /* Linux doesn't support inverted pixels (XOR ops,
858 * to be exact) in cursor shapes, so we detect such
859 * pixels and always replace them with black ones to
860 * make them visible at least over light colors */
861 if (dstShapePtr [x] & 0x00FFFFFF)
862 dstShapePtr [x] = 0xFF000000;
863 else
864 dstShapePtr [x] = 0x00000000;
865 }
866 else
867 dstShapePtr [x] |= 0xFF000000;
868 }
869 }
870
871 srcShapePtr += srcShapePtrScan;
872 dstShapePtr += uWidth;
873 }
874
875 /* Set the new cursor: */
876 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
877 m_fIsValidPointerShapePresent = true;
878
879 XcursorImageDestroy(img);
880 }
881
882#elif defined(Q_WS_MAC)
883
884 /* Create a ARGB image out of the shape data. */
885 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
886 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
887 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
888 for (unsigned int y = 0; y < uHeight; ++y)
889 {
890 for (unsigned int x = 0; x < uWidth; ++x)
891 {
892 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
893 /* If the alpha channel isn't in the shape data, we have to
894 * create them from the and-mask. This is a bit field where 1
895 * represent transparency & 0 opaque respectively. */
896 if (!fHasAlpha)
897 {
898 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
899 color |= 0xff000000;
900 else
901 {
902 /* This isn't quite right, but it's the best we can do I think... */
903 if (color & 0x00ffffff)
904 color = 0xff000000;
905 else
906 color = 0x00000000;
907 }
908 }
909 image.setPixel (x, y, color);
910 }
911 /* Move one scanline forward. */
912 pbSrcMask += cbSrcMaskLine;
913 }
914
915 /* Set the new cursor: */
916 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
917 m_fIsValidPointerShapePresent = true;
918 NOREF(srcShapePtrScan);
919
920#else
921
922# warning "port me"
923
924#endif
925}
926
927void UISession::reinitMenuPool()
928{
929 /* Get uisession machine: */
930 const CMachine &machine = session().GetConsole().GetMachine();
931
932 /* Storage stuff: */
933 {
934 /* Initialize CD/FD menus: */
935 int iDevicesCountCD = 0;
936 int iDevicesCountFD = 0;
937 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
938 for (int i = 0; i < attachments.size(); ++i)
939 {
940 const CMediumAttachment &attachment = attachments[i];
941 if (attachment.GetType() == KDeviceType_DVD)
942 ++iDevicesCountCD;
943 if (attachment.GetType() == KDeviceType_Floppy)
944 ++iDevicesCountFD;
945 }
946 QAction *pOpticalDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices);
947 QAction *pFloppyDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices);
948 pOpticalDevicesMenu->setData(iDevicesCountCD);
949 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
950 pFloppyDevicesMenu->setData(iDevicesCountFD);
951 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
952 }
953
954 /* VRDE stuff: */
955 {
956 /* Get VRDE server: */
957 CVRDEServer server = machine.GetVRDEServer();
958 bool fIsVRDEServerAvailable = !server.isNull();
959 /* Show/Hide VRDE action depending on VRDE server availability status: */
960 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDEServer)->setVisible(fIsVRDEServerAvailable);
961 /* Check/Uncheck VRDE action depending on VRDE server activity status: */
962 if (fIsVRDEServerAvailable)
963 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDEServer)->setChecked(server.GetEnabled());
964 }
965
966 /* Network stuff: */
967 {
968 bool fAtLeastOneAdapterActive = false;
969 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
970 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
971 {
972 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
973 if (adapter.GetEnabled())
974 {
975 fAtLeastOneAdapterActive = true;
976 break;
977 }
978 }
979 /* Show/Hide Network Adapters action depending on overall adapters activity status: */
980 uimachine()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)->setVisible(fAtLeastOneAdapterActive);
981 }
982
983 /* USB stuff: */
984 {
985 /* Get USB controller: */
986 const CUSBController &usbController = machine.GetUSBController();
987 bool fUSBControllerEnabled = !usbController.isNull() && usbController.GetEnabled() && usbController.GetProxyAvailable();
988 /* Show/Hide USB menu depending on controller availability, activity and USB-proxy presence: */
989 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(fUSBControllerEnabled);
990 }
991}
992
993void UISession::preparePowerUp()
994{
995#ifdef VBOX_WITH_UPDATE_REQUEST
996 /* Check for updates if necessary: */
997 vboxGlobal().showUpdateDialog(false /* force request? */);
998#endif
999
1000 /* Notify user about mouse&keyboard auto-capturing: */
1001 if (vboxGlobal().settings().autoCapture())
1002 vboxProblem().remindAboutAutoCapture();
1003
1004 /* Shows first run wizard if necessary: */
1005 const CMachine &machine = session().GetMachine();
1006 /* Check if we are in teleportation waiting mode. In that case no first run
1007 * wizard is necessary. */
1008 m_machineState = machine.GetState();
1009 if ( isFirstTimeStarted()
1010 && !(( m_machineState == KMachineState_PoweredOff
1011 || m_machineState == KMachineState_Aborted
1012 || m_machineState == KMachineState_Teleported)
1013 && machine.GetTeleporterEnabled()))
1014 {
1015 UIFirstRunWzd wzd(mainMachineWindow(), session().GetMachine());
1016 wzd.exec();
1017 }
1018}
1019
1020#ifdef VBOX_WITH_VIDEOHWACCEL
1021UIFrameBuffer* UISession::frameBuffer(ulong screenId) const
1022{
1023 Assert(screenId < (ulong)m_FrameBufferVector.size());
1024 return m_FrameBufferVector.value((int)screenId, NULL);
1025}
1026
1027int UISession::setFrameBuffer(ulong screenId, UIFrameBuffer* pFrameBuffer)
1028{
1029 Assert(screenId < (ulong)m_FrameBufferVector.size());
1030 if (screenId < (ulong)m_FrameBufferVector.size())
1031 {
1032 m_FrameBufferVector[(int)screenId] = pFrameBuffer;
1033 return VINF_SUCCESS;
1034 }
1035 return VERR_INVALID_PARAMETER;
1036}
1037#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use