VBoxSDL.cpp revision 05fb7454f402098331166b59778f1b03d2e7c8c1
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VBox frontends: VBoxSDL (simple frontend based on SDL):
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Main code
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync * Copyright (C) 2006-2007 innotek GmbH
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License (GPL) as published by the Free Software
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Header Files *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncusing namespace com;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/* Xlib would re-define our enums */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Defined Constants And Macros *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** extra data key for the secure label */
710a6316a22868b04400caf79719f96c18163cd3vboxsync#define VBOXSDL_SECURELABEL_EXTRADATA "VBoxSDL/SecureLabel"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** label area height in pixels */
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync/** Enables the rawr[0|3], patm, and casm options. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/*******************************************************************************
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync* Structures and Typedefs *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/** Pointer shape change event data strucure */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync PointerShapeChangeData (BOOL aVisible, BOOL aAlpha, ULONG aXHot, ULONG aYHot,
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync ULONG aWidth, ULONG aHeight, const uint8_t *aShape)
6febf3149010855617e4a37e2c49f93d68930d44vboxsync : visible (aVisible), alpha (aAlpha), xHot (aXHot), yHot (aYHot),
80e46f984efd827517661c0e081a36014ca41af8vboxsync // make a copy of the shape
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync uint32_t shapeSize = ((((aWidth + 7) / 8) * aHeight + 3) & ~3) + aWidth * 4 * aHeight;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync memcpy ((void *) shape, (void *) aShape, shapeSize);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Internal Functions *
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic bool UseAbsoluteMouse(void);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void ResetKeys(void);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void InputGrabStart(void);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void InputGrabEnd(void);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void SendMouseEvent(int dz, int button, int down);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void UpdateTitlebar(TitlebarMode mode, uint32_t u32User = 0);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void SetPointerShape(const PointerShapeChangeData *data);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic void HandleGuestCapsChanged(void);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic int HandleHostKey(const SDL_KeyboardEvent *pEv);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic Uint32 StartupTimer(Uint32 interval, void *param);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncstatic Uint32 ResizeTimer(Uint32 interval, void *param);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic Uint32 QuitTimer(Uint32 interval, void *param);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Global Variables *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync// my mini kbd doesn't have RCTRL...
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync/** modifier keypress status (scancode as index) */
63b785c3291332a86a9bc473e68f08121368898bvboxsyncstatic volatile int32_t g_cNotifyUpdateEventsPending;
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * Callback handler for VirtualBox events
80e46f984efd827517661c0e081a36014ca41af8vboxsync delete this;
80e46f984efd827517661c0e081a36014ca41af8vboxsync STDMETHOD(QueryInterface)(REFIID riid , void **ppObj)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnMachineStateChange)(INPTR GUIDPARAM machineId, MachineState_T state)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnMachineDataChange)(INPTR GUIDPARAM machineId)
48dafba24ef28f07a241e5857a43b327822574a8vboxsync STDMETHOD(OnExtraDataCanChange)(INPTR GUIDPARAM machineId, INPTR BSTR key, INPTR BSTR value,
48dafba24ef28f07a241e5857a43b327822574a8vboxsync /* we never disagree */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnExtraDataChange)(INPTR GUIDPARAM machineId, INPTR BSTR key, INPTR BSTR value)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * check if we're interested in the message
194a8ad893b721dfc22ac5f955671f09db015a3fvboxsync if (keyString && keyString == VBOXSDL_SECURELABEL_EXTRADATA)
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync * Notify SDL thread of the string update
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync event.user.type = SDL_USER_EVENT_SECURELABEL_UPDATE;
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync#endif /* VBOX_SECURELABEL */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync STDMETHOD(OnMediaRegistered) (INPTR GUIDPARAM mediaId, DeviceType_T mediaType,
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnMachineRegistered)(INPTR GUIDPARAM machineId, BOOL registered)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnSessionStateChange)(INPTR GUIDPARAM machineId, SessionState_T state)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync STDMETHOD(OnSnapshotTaken) (INPTR GUIDPARAM aMachineId, INPTR GUIDPARAM aSnapshotId)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync STDMETHOD(OnSnapshotDiscarded) (INPTR GUIDPARAM aMachineId, INPTR GUIDPARAM aSnapshotId)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync STDMETHOD(OnSnapshotChange) (INPTR GUIDPARAM aMachineId, INPTR GUIDPARAM aSnapshotId)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Callback handler for machine events
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync VBoxSDLConsoleCallback() : m_fIgnorePowerOffEvents(false)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync delete this;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(QueryInterface)(REFIID riid , void **ppObj)
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync STDMETHOD(OnMousePointerShapeChange) (BOOL visible, BOOL alpha, ULONG xHot, ULONG yHot,
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync data = new PointerShapeChangeData (visible, alpha, xHot, yHot, width, height,
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnMouseCapabilityChange)(BOOL supportsAbsolute, BOOL needsHostCursor)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync LogFlow(("OnMouseCapabilityChange: supportsAbsolute = %d\n", supportsAbsolute));
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync event.user.type = SDL_USER_EVENT_GUEST_CAP_CHANGED;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnKeyboardLedsChange)(BOOL fNumLock, BOOL fCapsLock, BOOL fScrollLock)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Don't bother the guest with NumLock scancodes if he doesn't set the NumLock LED */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnStateChange)(MachineState_T machineState)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync LogFlow(("OnStateChange: machineState = %d (%s)\n", machineState, GetStateName(machineState)));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || (machineState == MachineState_Saved && !m_fIgnorePowerOffEvents)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || (machineState == MachineState_PoweredOff && !m_fIgnorePowerOffEvents))
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * We have to inform the SDL thread that the application has be terminated
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync event.user.code = machineState == MachineState_Aborted
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Inform the SDL thread to refresh the titlebar
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnNetworkAdapterChange) (INetworkAdapter *aNetworkAdapter)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnSerialPortChange) (ISerialPort *aSerialPort)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnParallelPortChange) (IParallelPort *aParallelPort)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STDMETHOD(OnUSBDeviceStateChange) (IUSBDevice *aDevice, BOOL aAttached,
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync STDMETHOD(OnRuntimeError)(BOOL fFatal, INPTR BSTR id, INPTR BSTR message)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync const char *pszType;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync bool fPaused = machineState == MachineState_Paused;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTPrintf("\n%s: ** %lS **\n%lS\n%s\n", pszType, id, message,
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync fPaused ? "The VM was paused. Continue with HostKey + P after you solved the problem.\n" : "");
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* SDL feature not available on Quartz */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#endif /* !RT_OS_DARWIN */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync static const char *GetStateName(MachineState_T machineState)
48dafba24ef28f07a241e5857a43b327822574a8vboxsync default: return "no idea";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncNS_IMPL_ISUPPORTS1_CI(VBoxSDLCallback, IVirtualBoxCallback)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncNS_IMPL_ISUPPORTS1_CI(VBoxSDLConsoleCallback, IConsoleCallback)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#endif /* VBOX_WITH_XPCOM */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -vm <id|name> Virtual machine to start, either UUID or name\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -hda <file> Set temporary first hard disk to file\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -fda <file> Set temporary first floppy disk to file\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -cdrom <file> Set temporary CDROM/DVD to file/device ('none' to unmount)\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -boot <a|c|d|n> Set temporary boot device (a = floppy, c = 1st HD, d = DVD, n = network)\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -m <size> Set temporary memory size in megabytes\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -vram <size> Set temporary size of video memory in megabytes\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -fullscreen Start VM in fullscreen mode\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -fixedmode <w> <h> <bpp> Use a fixed SDL video mode with given width, height and bits per pixel\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -nofstoggle Forbid switching to/from fullscreen mode\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -noresize Make the SDL frame non resizable\n"
93771df67d4047d8b965665899b6a5bdf06ae277vboxsync " -nohostkey Disable hostkey\n"
93771df67d4047d8b965665899b6a5bdf06ae277vboxsync " -nograbonclick Disable mouse/keyboard grabbing on mouse click w/o additions\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -detecthostkey Get the hostkey identifier and modifier state\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -hostkey <key> {<key2>} <mod> Set the host key to the values obtained using -detecthostkey\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -termacpi Send an ACPI power button event when closing the window\n"
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) /** @todo UNIXISH_TAP stuff out of main and up to Config.kmk! */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync " -tapdev<1-N> <dev> Use existing persistent TAP device with the given name\n"
80e46f984efd827517661c0e081a36014ca41af8vboxsync " -tapfd<1-N> <fd> Use existing TAP device, don't allocate\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " -evdevkeymap Use evdev keycode map\n"
80e46f984efd827517661c0e081a36014ca41af8vboxsync " -vrdp <port> Listen for VRDP connections on port (default if not specified)\n"
80e46f984efd827517661c0e081a36014ca41af8vboxsync " -discardstate Discard saved state (if present) and revert to last snapshot (if present)\n"
80e46f984efd827517661c0e081a36014ca41af8vboxsync " -securelabel Display a secure VM label at the top of the screen\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -seclabelfnt TrueType (.ttf) font file for secure session label\n"
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync " -seclabelsiz Font point size for secure session label (default 12)\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -seclabelfgcol <rgb> Secure label text color RGB value in 6 digit hexadecimal (eg: FFFF00)\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -seclabelbgcol <rgb> Secure label background color RGB value in 6 digit hexadecimal (eg: FF0000)\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -[no]rawr0 Enable or disable raw ring 3\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -[no]rawr3 Enable or disable raw ring 0\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -[no]patm Enable or disable PATM\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -[no]csam Enable or disable CSAM\n"
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync " -[no]hwvirtex Permit or deny the usage of VMX/SVN\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync "Key bindings:\n"
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync " <hostkey> + f Switch to full screen / restore to previous view\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " h Press ACPI power button\n"
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync " n Take a snapshot and continue execution\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " p Pause / resume execution\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " q Power off\n"
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync " r VM reset\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " s Save state and power off\n"
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync " <del> Send <ctrl><alt><del>\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync " <F1>...<F12> Send <ctrl><alt><Fx>\n"
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsyncstatic void PrintError(const char *pszName, const BSTR pwszDescr, const BSTR pwszComponent=NULL)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync RTStrPrintf(pszBuffer, sizeof(pszBuffer), "%lS", pwszDescr);
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync && (pszStat = strstr(pszBuffer, "VBox status code: ")))
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * Custom signal handler. Currently it is only used to release modifier
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * keys when receiving the USR1 signal. When switching VTs, we might not
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * get release events for Ctrl-Alt and in case a savestate is performed
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * on the new VT, the VM will be saved with modifier keys stuck. This is
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * annoying enough for introducing this hack.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid signal_handler(int sig, siginfo_t *info, void *secret)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* only SIGUSR1 is interesting */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* just release the modifiers */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync#endif /* VBOXSDL_WITH_X11 */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync/** entry point */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Before we do *anything*, we initialize the runtime.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTPrintf("Error: RTR3Init failed rcRC=%d\n", rcRT);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Lock keys on SDL behave different from normal keys: A KeyPress event is generated
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * if the lock mode gets active and a keyRelease event is genereated if the lock mode
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * gets inactive, that is KeyPress and KeyRelease are sent when pressing the lock key
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * to change the mode. The current lock mode is reflected in SDL_GetModState().
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Debian patched libSDL to make the lock keys behave like normal keys generating a
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * KeyPress/KeyRelease event if the lock key was pressed/released. But the lock status
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * is not reflected in the mod status anymore. We disable the Debian-specific extension
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * to ensure a defined environment and work around the missing KeyPress/KeyRelease
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * events in ProcessKeys().
63b785c3291332a86a9bc473e68f08121368898bvboxsync * the hostkey detection mode is unrelated to VM processing, so handle it before
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync * we initialize anything COM related
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync if (argc == 2 && !strcmp(argv[1], "-detecthostkey"))
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync int rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync RTPrintf("Error: SDL_InitSubSystem failed with message '%s'\n", SDL_GetError());
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync /* we need a video window for the keyboard stuff to work */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync if (!SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE))
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync RTPrintf("Please hit one or two function key(s) to get the -hostkey value...\n");
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync unsigned mod = SDL_GetModState() & ~(KMOD_MODE | KMOD_NUM | KMOD_RESERVED);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync if (event2.type == SDL_KEYDOWN || event2.type == SDL_KEYUP)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* pressed additional host key */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync RTPrintf(" %d\n", SDL_GetModState() & ~(KMOD_MODE | KMOD_NUM | KMOD_RESERVED));
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* we're done */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* we're down */
6febf3149010855617e4a37e2c49f93d68930d44vboxsync bool fFullscreen = false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync unsigned fRawR0 = ~0U;
63b785c3291332a86a9bc473e68f08121368898bvboxsync unsigned fRawR3 = ~0U;
63b785c3291332a86a9bc473e68f08121368898bvboxsync unsigned fPATM = ~0U;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync unsigned fCSAM = ~0U;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync bool fWin32UI = false;
63b785c3291332a86a9bc473e68f08121368898bvboxsync /* The damned GOTOs forces this to be up here - totally out of place. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Host key handling.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * The golden rule is that host-key combinations should not be seen
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * by the guest. For instance a CAD should not have any extra RCtrl down
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * and RCtrl up around itself. Nor should a resume be followed by a Ctrl-P
63b785c3291332a86a9bc473e68f08121368898bvboxsync * that could encourage applications to start printing.
63b785c3291332a86a9bc473e68f08121368898bvboxsync * We must not confuse the hostkey processing into any release sequences
63b785c3291332a86a9bc473e68f08121368898bvboxsync * either, the host key is supposed to be explicitly pressing one key.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Quick state diagram:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * host key down alone
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * (Normal) ---------------
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * | | v host combination key down
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * | | (Host key down) ----------------
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * | | host key up v | |
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * | |-------------- | other key down v host combination key down
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * | | (host key used) -------------
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * | | | ^ |
825c2485cf84eec495985ffd605a1c9cddee8c32vboxsync * | (not host key)-- | |---------------
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * | | | | |
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * | | ---- other |
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * | modifiers = 0 v v
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * -----------------------------------------------
2294b1479e3fb6f4e9c9550b3e15f3d3a3f1fc24vboxsync /** The initial and most common state, pass keystrokes to the guest.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_DOWN
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * Prev state: Any */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The first host key was pressed down
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The second host key was pressed down (if gHostKeySym2 != SDLK_UNKNOWN)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The host key has been pressed down.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Prev state: HKEYSTATE_NORMAL
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_NORMAL - host key up, capture toggle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_USED - host key combination down.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_NOT_IT - non-host key combination down.
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync /** A host key combination was pressed.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Prev state: HKEYSTATE_DOWN
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_NORMAL - when modifiers are all 0
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** A non-host key combination was attempted. Send hostkey down to the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * guest and continue until all modifiers have been released.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Prev state: HKEYSTATE_DOWN
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Next state: HKEYSTATE_NORMAL - when modifiers are all 0
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /** The host key down event which we have been hiding from the guest.
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync * Used when going from HKEYSTATE_DOWN to HKEYSTATE_NOT_IT. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync // less than one parameter is not possible
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: COM initialization failed, rc = 0x%x!\n", rc);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync // scopes all the stuff till shutdown
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync ////////////////////////////////////////////////////////////////////////////
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = virtualBox.createLocalObject (CLSID_VirtualBox);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Failed to create VirtualBox object! No error information available (rc = 0x%x).\n", rc);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Failed to create session object, rc = 0x%x!\n", rc);
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync // create the event queue
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync // (here it is necessary only to process remaining XPCOM/IPC events
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync // after the session is closed)
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync// EventQueue eventQ;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#endif /* USE_XPCOM_QUEUE_THREAD */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Get the number of network adapters */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync virtualBox->COMGETTER(SystemProperties) (sysInfo.asOutParam());
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync sysInfo->COMGETTER (NetworkAdapterCount) (&NetworkAdapterCount);
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync // command line argument parsing stuff
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: VM not specified (UUID or name)!\n");
825c2485cf84eec495985ffd605a1c9cddee8c32vboxsync // first check if a UUID was supplied
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync if (VBOX_FAILURE(RTUuidFromStr(uuid.ptr(), argv[curArg])))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogFlow(("invalid UUID format, assuming it's a VM name\n"));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: missing argument for boot drive!\n");
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTPrintf("Error: wrong argument for boot drive!\n");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: missing argument for memory size!\n");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: missing argument for vram size!\n");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* three parameters follow */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync RTPrintf("Error: missing arguments for fixed video mode!\n");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else if (strcmp(argv[curArg], "-nograbonclick") == 0)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTPrintf("Error: missing file name for first hard disk!\n");
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /* resolve it. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTPrintf("Error: The path to the specified harddisk, '%s', could not be resolved.\n", argv[curArg]);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync RTPrintf("Error: missing file/device name for first floppy disk!\n");
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync /* resolve it. */
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync RTPrintf("Error: The path to the specified floppy disk, '%s', could not be resolved.\n", argv[curArg]);
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync RTPrintf("Error: missing file/device name for cdrom!\n");
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync /* resolve it. */
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync RTPrintf("Error: The path to the specified cdrom, '%s', could not be resolved.\n", argv[curArg]);
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync else if (strcmp(argv[curArg], "-evdevkeymap") == 0)
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync#endif /* RT_OS_LINUX */
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync if (!argv[curArg][7] || ((n = strtoul(&argv[curArg][7], NULL, 10)) < 1) ||
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync (n > NetworkAdapterCount) || (argc <= (curArg + 1)))
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!argv[curArg][6] || ((n = strtoul(&argv[curArg][6], NULL, 10)) < 1) ||
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync (n > NetworkAdapterCount) || (argc <= (curArg + 1)))
825c2485cf84eec495985ffd605a1c9cddee8c32vboxsync RTPrintf("Error: invalid TAP file descriptor option!\n");
#ifdef VBOX_VRDP
portVRDP = 0;
if (port > 0)
curArg++;
fDiscardState = true;
#ifdef VBOX_SECURELABEL
fSecureLabel = true;
#ifdef VBOXSDL_ADVANCED_OPTIONS
fRawR0 = true;
fRawR0 = false;
fRawR3 = true;
fRawR3 = false;
fPATM = true;
fPATM = false;
fCSAM = true;
fCSAM = false;
#ifdef VBOX_WIN32_UI
fWin32UI = true;
fShowSDLConfig = true;
show_usage();
goto leave;
goto leave;
goto leave;
if (!session)
goto leave;
sessionOpened = true;
if (!gMachine)
goto leave;
if (!gConsole)
goto leave;
if (hdaFile)
if (!hardDisk)
if (hardDisk)
if (hardDisk)
goto leave;
if (fdaFile)
bool done = false;
done = true;
if (!done)
goto leave;
if (cdromFile)
bool done = false;
done = true;
if (!done)
goto leave;
if (fDiscardState)
if (cSnapshots)
if (gMachineDebugger)
if (!gDisplay)
goto leave;
if (memorySize)
if (vramSize)
#ifdef VBOX_WIN32_UI
if (fWin32UI)
if (!gpFrameBuffer)
goto leave;
goto leave;
if (fFullscreen)
#ifdef VBOX_SECURELABEL
if (fSecureLabel)
if (!secureLabelFontFile)
goto leave;
int rcVBox;
rcVBox = gpFrameBuffer->initSecureLabel(SECURE_LABEL_HEIGHT, secureLabelFontFile, secureLabelPointSize);
goto leave;
goto leave;
if (networkAdapter)
if (tapdev[i])
#ifdef VBOX_VRDP
if (portVRDP != ~0)
if (gVrdpServer)
if (portVRDP > 0)
goto leave;
goto leave;
#ifdef VBOXSDL_ADVANCED_OPTIONS
if (fRawR0 != ~0U)
if (!gMachineDebugger)
goto leave;
if (fRawR3 != ~0U)
if (!gMachineDebugger)
goto leave;
if (fPATM != ~0U)
if (!gMachineDebugger)
goto leave;
if (fCSAM != ~0U)
if (!gMachineDebugger)
goto leave;
if (u32WarpDrive != 0)
if (!gMachineDebugger)
goto leave;
#ifdef VBOXSDL_WITH_X11
goto leave;
# if !defined(VBOX_WITHOUT_XCURSOR)
#ifdef VBOXSDL_WITH_X11
goto leave;
#ifdef USE_XPCOM_QUEUE_THREAD
bool fTerminateDuringStartup;
fTerminateDuringStartup = false;
#ifdef USE_XPCOM_QUEUE_THREAD
fXPCOMEventThreadSignaled = true;
case SDL_USER_EVENT_TIMER:
case SDL_USER_EVENT_RESIZE:
#ifdef USE_XPCOM_QUEUE_THREAD
case SDL_USER_EVENT_TERMINATE:
fTerminateDuringStartup = true;
sdlTimer = 0;
goto leave;
RTPrintf("Error: failed to power up VM! No error text available (rc = 0x%x state = %d)\n", rc, machineState);
goto leave;
if (!gKeyboard)
goto leave;
if (!gMouse)
goto leave;
#ifdef USE_XPCOM_QUEUE_THREAD
case SDL_VIDEOEXPOSE:
case SDL_KEYDOWN:
case SDL_KEYUP:
switch (enmHKeyState)
case HKEYSTATE_NORMAL:
case HKEYSTATE_DOWN_1ST:
case HKEYSTATE_DOWN_2ND:
case HKEYSTATE_DOWN:
goto leave;
if (!gfGrabbed)
InputGrabEnd();
ResetKeys();
case HKEYSTATE_USED:
goto leave;
case HKEYSTATE_NOT_IT:
case SDL_QUIT:
goto leave;
if (gConsole)
case SDL_MOUSEMOTION:
SendMouseEvent(0, 0, 0);
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
switch (enmHKeyState)
case HKEYSTATE_DOWN_1ST:
case HKEYSTATE_DOWN_2ND:
case HKEYSTATE_DOWN:
case SDL_ACTIVEEVENT:
InputGrabEnd();
case SDL_VIDEORESIZE:
if (gDisplay)
#ifdef VBOX_SECURELABEL
if (gSdlResizeTimer)
case SDL_USER_EVENT_RESIZE:
#ifdef USE_XPCOM_QUEUE_THREAD
case SDL_USER_EVENT_TERMINATE:
goto leave;
#ifdef VBOX_SECURELABEL
delete data;
#ifdef VBOX_VRDP
if (gVrdpServer)
if (gMachine)
if ( gConsole
RTPrintf("Failed to power down virtual machine! No error information available (rc = 0x%x).\n", rc);
if ( gMachine
if (sessionOpened)
if (gpDefaultCursor)
#ifdef VBOXSDL_WITH_X11
if (gpCustomCursor)
if (pCustomTempWMCursor)
#if defined (RT_OS_WINDOWS)
if (gDisplay)
if (gpFrameBuffer)
#ifdef VBOX_SECURELABEL
if (gLibrarySDL_ttf)
if (callback)
if (consoleCallback)
static bool UseAbsoluteMouse(void)
switch (sym)
case SDLK_EXCLAIM:
case SDLK_AT:
case SDLK_HASH:
case SDLK_DOLLAR:
case SDLK_CARET:
case SDLK_AMPERSAND:
case SDLK_ASTERISK:
case SDLK_LEFTPAREN:
case SDLK_RIGHTPAREN:
case SDLK_UNDERSCORE:
case SDLK_EQUALS:
case SDLK_COLON:
case SDLK_QUOTEDBL:
case SDLK_LESS:
case SDLK_GREATER:
case SDLK_QUESTION:
case SDLK_KP_MULTIPLY:
case SDLK_LMETA:
case SDLK_RMETA:
case SDLK_CLEAR: return 0x;
case SDLK_KP_EQUALS: return 0x;
case SDLK_COMPOSE: return 0x;
case SDLK_HELP: return 0x;
case SDLK_BREAK: return 0x;
case SDLK_POWER: return 0x;
case SDLK_EURO: return 0x;
case SDLK_UNDO: return 0x;
#ifdef VBOXSDL_WITH_X11
keycode = 0;
// Japanese backslash/underscore and Brazilian backslash/question mark
keycode = 0;
/* This is derived partially from SDL_QuartzKeys.h and partially from testing. */
/* set-1 SDL_QuartzKeys.h */
if (keycode == 0)
case SDLK_RMETA:
case SDLK_LMETA:
keycode = 0;
if (!keycode)
#ifdef DEBUG_bird
#ifdef DEBUG_bird
return keycode;
static void ResetKeys(void)
if (!gKeyboard)
if (gaModifiersState[i])
gaModifiersState[i] = 0;
case SDLK_F12:
case SDLK_F11:
case SDLK_F12:
case SDLK_F11:
case SDLK_F10:
case SDLK_F9:
case SDLK_F8:
#ifdef DEBUG_bird
switch(keycode)
ResetKeys();
#ifdef RT_OS_DARWIN
typedef int CGSConnection;
extern CGError CGSGetGlobalHotKeyOperatingMode(CGSConnection Connection, CGSGlobalHotKeyOperatingMode *enmMode);
extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection Connection, CGSGlobalHotKeyOperatingMode enmMode);
static bool g_fHotKeysDisabled = false;
static bool g_fConnectedToCGS = false;
if (!g_fConnectedToCGS)
g_fConnectedToCGS = true;
if (fDisable)
static void InputGrabStart(void)
#ifdef RT_OS_DARWIN
DisableGlobalHotKeys(true);
if (!gfGuestNeedsHostCursor)
static void InputGrabEnd(void)
if (!gfGuestNeedsHostCursor)
#ifdef RT_OS_DARWIN
DisableGlobalHotKeys(false);
bool abs;
buttons = 0;
if (abs)
button = 0;
if (!gpOffCursor)
if (gpOffCursor)
int tmp_button = 0;
switch (button)
if (abs)
if (abs)
void ResetVM(void)
if (gConsole)
void SaveState(void)
ResetKeys();
if (gfGrabbed)
InputGrabEnd();
case SDL_USER_EVENT_TIMER:
#ifdef USE_XPCOM_QUEUE_THREAD
case SDL_USER_EVENT_RESIZE:
case SDL_USER_EVENT_TERMINATE:
sdlTimer = 0;
lrc = ~0;
if (!lrc)
if (name)
switch (mode)
case TITLEBAR_NORMAL:
if (gfGrabbed)
if (gMachineDebugger)
case TITLEBAR_STARTUP:
case TITLEBAR_SAVE:
case TITLEBAR_SNAPSHOT:
#ifdef VBOX_WIN32_UI
static void vbox_show_shape (unsigned short w, unsigned short h,
size_t x, y;
unsigned short pitch;
if (c == bg)
if (gpOffCursor)
bool ok = false;
uint32_t shapeSize = ((((data->width + 7) / 8) * data->height + 3) & ~3) + data->width * 4 * data->height;
#if defined (RT_OS_WINDOWS)
void *lpBits;
if (hAlphaCursor)
// see SDL12/src/video/wincommon/SDL_sysmouse.c
if (pCustomTempWMCursor)
ok = true;
if (hMonoBitmap)
if (hBitmap)
if (img)
if (cur)
// see SDL12/src/video/x11/SDL_x11mouse.c
if (pCustomTempWMCursor)
ok = true;
if (!ok)
else if (gfAbsoluteMouseGuest)
static void HandleGuestCapsChanged(void)
if (!gfAbsoluteMouseGuest)
if (gfGrabbed)
InputGrabEnd();
return VERR_NOT_SUPPORTED;
case SDLK_DELETE:
case SDLK_f:
case SDLK_p:
if (gfGrabbed)
InputGrabEnd();
case SDLK_r:
ResetVM();
case SDLK_q:
return VINF_EM_TERMINATE;
case SDLK_s:
SaveState();
return VINF_EM_TERMINATE;
case SDLK_h:
if (gConsole)
case SDLK_n:
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
return VINF_SUCCESS;
return interval;
if (gConsole)
#ifdef USE_XPCOM_QUEUE_THREAD
if (rc == 0)
#ifdef VBOXSDL_WITH_X11
if (!rc)