UIKeyboardHandler.cpp revision 04b02ffb8824a60fd37777bc1f7d2f35104a274c
/* $Id$ */
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* UIKeyboardHandler class implementation
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/* Global includes */
#include <QKeyEvent>
/* Local includes */
#include "VBoxGlobal.h"
#include "VBoxProblemReporter.h"
#include "UIActionsPool.h"
#include "UIKeyboardHandlerNormal.h"
#include "UIKeyboardHandlerFullscreen.h"
#include "UIKeyboardHandlerSeamless.h"
#include "UIKeyboardHandlerScale.h"
#include "UIMouseHandler.h"
#include "UISession.h"
#include "UIMachineLogic.h"
#include "UIMachineWindow.h"
#include "UIMachineView.h"
#ifdef Q_WS_X11
# include <QX11Info>
# ifdef KeyPress
const int XKeyRelease = KeyRelease;
# endif /* KeyPress */
# include "XKeyboard.h"
#endif /* Q_WS_X11 */
#ifdef Q_WS_MAC
# include "VBoxUtils-darwin.h"
# include "DarwinKeyboard.h"
# include "UICocoaApplication.h"
#endif /* Q_WS_MAC */
/* Enums representing different keyboard-states: */
#ifdef Q_WS_WIN
#endif /* Q_WS_WIN */
/* Factory function to create keyboard-handler: */
{
/* Prepare keyboard-handler: */
/* Depending on visual-state type: */
switch (visualStateType)
{
case UIVisualStateType_Normal:
break;
break;
break;
case UIVisualStateType_Scale:
break;
default:
break;
}
#ifdef Q_WS_WIN
/* Its required to have static pointer to created handler
* because windows keyboard-hook works only with static members: */
#endif /* Q_WS_WIN */
/* Return prepared keyboard-handler: */
return pKeyboardHandler;
}
/* Factory function to destroy keyboard-handler: */
{
/* Delete keyboard-handler: */
#ifdef Q_WS_WIN
m_pKeyboardHandler = 0;
#endif /* Q_WS_WIN */
delete pKeyboardHandler;
}
/* Prepare listened objects: */
{
/* If that window is NOT registered yet: */
{
/* Add window: */
/* Install event-filter for window: */
}
/* If that view is NOT registered yet: */
{
/* Add view: */
/* Install event-filter for view: */
}
}
/* Cleanup listened objects: */
{
/* Check if we should release keyboard first: */
if ((int)uIndex == m_iKeyboardCaptureViewIndex)
/* If window still registered: */
{
/* Remove window: */
}
/* If view still registered: */
{
/* Remove view: */
}
}
{
/* Do NOT capture keyboard if its captured already: */
return;
/* If such view exists: */
{
/* Store new keyboard-captured state value: */
m_fIsKeyboardCaptured = true;
/* Remember which screen had captured keyboard: */
#if defined(Q_WS_WIN)
/* On Win, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. */
/* On X11, we are using passive XGrabKey for normal (windowed) mode
* instead of XGrabKeyboard (called by QWidget::grabKeyboard())
* because XGrabKeyboard causes a problem under metacity - a window cannot be moved
* using the mouse if it is currently actively grabbing the keyboard;
* For static modes we are using usual (active) keyboard grabbing. */
switch (machineLogic()->visualStateType())
{
/* If window is moveable we are making passive keyboard grab: */
case UIVisualStateType_Normal:
case UIVisualStateType_Scale:
{
XGrabKey(QX11Info::display(), AnyKey, AnyModifier, m_windows[m_iKeyboardCaptureViewIndex]->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync);
break;
}
/* If window is NOT moveable we are making active keyboard grab: */
{
/* Keyboard grabbing can fail because of some keyboard shortcut is still grabbed by window manager.
* We can't be sure this shortcut will be released at all, so we will retry to grab keyboard for 50 times,
* and after we will just ignore that issue: */
int cTriesLeft = 50;
while (cTriesLeft && XGrabKeyboard(QX11Info::display(), m_windows[m_iKeyboardCaptureViewIndex]->machineWindow()->winId(), False, GrabModeAsync, GrabModeAsync, CurrentTime)) { --cTriesLeft; }
break;
}
/* Should we try to grab keyboard in default case? I think - NO. */
default:
break;
}
/* On Mac, we use the Qt methods + disabling global hot keys + watching modifiers (for right/left separation). */
::DarwinDisableGlobalHotKeys(true);
#else
/* On other platforms we are just praying Qt method will work. */
#endif
/* Notify all the listeners: */
}
}
void UIKeyboardHandler::releaseKeyboard()
{
/* Do NOT capture keyboard if its captured already: */
if (!m_fIsKeyboardCaptured)
return;
/* If such view exists: */
{
/* Store new keyboard-captured state value: */
m_fIsKeyboardCaptured = false;
#if defined(Q_WS_WIN)
/* On Win, keyboard grabbing is ineffective, a low-level keyboard hook is used instead. */
/* On X11, we are using passive XGrabKey for normal (windowed) mode
* instead of XGrabKeyboard (called by QWidget::grabKeyboard())
* because XGrabKeyboard causes a problem under metacity - a window cannot be moved
* using the mouse if it is currently actively grabbing the keyboard;
* For static modes we are using usual (active) keyboard grabbing. */
switch (machineLogic()->visualStateType())
{
/* If window is moveable we are making passive keyboard ungrab: */
case UIVisualStateType_Normal:
case UIVisualStateType_Scale:
{
XUngrabKey(QX11Info::display(), AnyKey, AnyModifier, m_windows[m_iKeyboardCaptureViewIndex]->machineWindow()->winId());
break;
}
/* If window is NOT moveable we are making active keyboard ungrab: */
{
break;
}
/* Should we try to release keyboard in default case? I think - NO. */
default:
break;
}
::DarwinDisableGlobalHotKeys(false);
#else
#endif
/* Reset keyboard-capture index: */
/* Notify all the listeners: */
}
}
/* Current keyboard state: */
int UIKeyboardHandler::keyboardState() const
{
return (m_fIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) |
}
#if defined(Q_WS_WIN)
{
/* Check if some system event should be filtered-out.
* Returning 'true' means filtering-out,
* Returning 'false' means passing event to Qt. */
bool fResult = false; /* Pass to Qt by default: */
{
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
/* Check for the special flag possibly set at the end of this function: */
{
fResult = false;
break;
}
/* Scancodes 0x80 and 0x00 are ignored: */
if (!scan)
{
fResult = true;
break;
}
int flags = 0;
flags |= KeyExtended;
flags |= KeyPressed;
/* Check for special Korean keys. Based on the keyboard layout selected
* on the host, the scancode in lParam might be 0x71/0x72 or 0xF1/0xF2.
* In either case, we must deliver 0xF1/0xF2 scancode to the guest when
* the key is pressed and nothing when it's released.
*/
{
scan |= 0x80;
}
/* When one of the SHIFT keys is held and one of the cursor movement
* but with the virtual key code set to 0xFF. These virtual keys are also
* sent in some other situations (Pause, PrtScn, etc.). Ignore suc messages. */
if (vkey == 0xFF)
{
fResult = true;
break;
}
switch (vkey)
{
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
{
/* Overcome stupid Win32 modifier key generalization: */
if (flags & KeyExtended)
keyscan |= 0xE000;
switch (keyscan)
{
}
break;
}
case VK_NUMLOCK:
/* Win32 sets the extended bit for the NumLock key. Reset it: */
flags &= ~KeyExtended;
break;
case VK_SNAPSHOT:
break;
case VK_PAUSE:
break;
}
if (!result && m_fIsKeyboardCaptured)
{
/* keyEvent() returned that it didn't process the message, but since the
* keyboard is captured, we don't want to pass it to Windows. We just want
* to let Qt process the message (to handle non-alphanumeric <HOST>+key
* shortcuts for example). So send it directly to the window with the
* special flag in the reserved area of lParam (to avoid recursion). */
fResult = true;
break;
}
/* These special keys have to be handled by Windows as well to update the
{
fResult = false;
break;
}
break;
}
default:
break;
}
/* Return result: */
return fResult;
}
{
return True;
else
return False;
}
{
/* Check if some system event should be filtered-out.
* Returning 'true' means filtering-out,
* Returning 'false' means passing event to Qt. */
bool fResult = false; /* Pass to Qt by default: */
{
/* We have to handle XFocusOut right here as this event is not passed to UIMachineView::event().
* Handling this event is important for releasing the keyboard before the screen saver gets active.
* See public ticket #3894: Apparently this makes problems with newer versions of Qt
* and this hack is probably not necessary anymore. So disable it for Qt >= 4.5.0. */
case XFocusOut:
case XFocusIn:
{
{
{
{
/* Capture keyboard by chosen view number: */
/* Reset the single-time disable capture flag: */
if (uisession()->isAutoCaptureDisabled())
uisession()->setAutoCaptureDisabled(false);
}
else
{
/* Release keyboard: */
/* And all pressed keys including host-one: */
releaseAllPressedKeys(true);
}
}
}
fResult = false;
}
case XKeyPress:
case XKeyRelease:
{
/* Translate the keycode to a PC scan code. */
/* Scancodes 0x00 (no valid translation) and 0x80 are ignored: */
if (!scan & 0x7F)
{
fResult = true;
break;
}
/* Fix for http://www.virtualbox.org/ticket/1296:
* when X11 sends events for repeated keys, it always inserts an XKeyRelease before the XKeyPress. */
{
fResult = true;
break;
}
int flags = 0;
if (scan >> 8)
flags |= KeyExtended;
flags |= KeyPressed;
/* Remove the extended flag: */
scan &= 0x7F;
/* Special Korean keys must send scancode 0xF1/0xF2 when pressed and nothing
* when released.
*/
{
{
fResult = true;
break;
}
}
switch (ks)
{
case XK_Print:
break;
case XK_Pause:
{
flags |= KeyExtended;
scan = 0x46;
}
else
break;
}
}
default:
break;
}
/* Return result: */
return fResult;
}
#endif
/* Machine state-change handler: */
{
/* Get machine state: */
/* Handle particular machine states: */
switch (state)
{
case KMachineState_Paused:
case KMachineState_Stuck:
{
/* Release the keyboard: */
/* And all pressed keys except the host-one : */
releaseAllPressedKeys(false /* release host-key? */);
break;
}
case KMachineState_Running:
{
/* Capture the keyboard by the first focused view: */
for (int i = 0; i < theListOfViewIds.size(); ++i)
{
{
/* Capture keyboard: */
#ifdef Q_WS_WIN
#else /* Q_WS_WIN */
#endif /* !Q_WS_WIN */
/* Reset the single-time disable capture flag: */
if (uisession()->isAutoCaptureDisabled())
uisession()->setAutoCaptureDisabled(false);
break;
}
}
break;
}
default:
break;
}
}
/* Keyboard-handler constructor: */
, m_fIsKeyboardCaptured(false)
, m_bIsHostkeyPressed(false)
, m_bIsHostkeyAlone (false)
, m_bIsHostkeyInCapture(false)
, m_fPassCAD(false)
#if defined(Q_WS_WIN)
, m_iKeyboardHookViewIndex(-1)
, m_darwinKeyModifiers(0)
, m_fKeyboardGrabbed(false)
, m_iKeyboardGrabViewIndex(-1)
#endif
{
/* Prepare: */
/* Load settings: */
loadSettings();
/* Initialize: */
}
/* Keyboard-handler destructor: */
{
/* Cleanup: */
}
void UIKeyboardHandler::prepareCommon()
{
/* Machine state-change updater: */
/* Pressed keys: */
}
void UIKeyboardHandler::loadSettings()
{
/* Global settings: */
#ifdef Q_WS_X11
/* Initialize the X keyboard subsystem: */
initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
#endif
/* Extra data settings: */
{
/* CAD settings: */
m_fPassCAD = true;
}
}
void UIKeyboardHandler::cleanupCommon()
{
#if defined(Q_WS_WIN)
/* Cleaning keyboard-hook: */
if (m_keyboardHook)
{
}
/* We have to make sure the callback for the keyboard events
* is released when closing this view. */
if (m_fKeyboardGrabbed)
darwinGrabKeyboardEvents(false);
#endif
}
/* Machine-logic getter: */
{
return m_pMachineLogic;
}
/* UI Session getter: */
{
return machineLogic()->uisession();
}
/* Main Session getter: */
{
}
/* Event handler for prepared listener(s): */
{
/* Check if pWatchedObject object is window: */
{
/* Get corresponding screen index: */
/* Handle window events: */
{
#if defined(Q_WS_WIN)
/* Install/uninstall low-level keyboard-hook on every activation/deactivation to:
* a) avoid excess hook calls when we're not active and;
* b) be always in front of any other possible hooks. */
case QEvent::WindowActivate:
{
/* If keyboard hook is NOT currently created;
* Or created but NOT for that window: */
{
/* If keyboard-hook present: */
if (m_keyboardHook)
{
/* We should remove existing keyboard-hook first: */
}
/* Register new keyboard-hook: */
/* Remember which view had captured keyboard: */
}
break;
}
case QEvent::WindowDeactivate:
{
/* If keyboard is currently captured: */
{
/* We should remove existing keyboard-hook: */
/* Remember what there is no window captured keyboard: */
m_iKeyboardHookViewIndex = -1;
}
break;
}
case QEvent::WindowActivate:
{
/* If keyboard event handler is NOT currently installed;
* Or installed but NOT for that window: */
if (m_iKeyboardGrabViewIndex != (int)uScreenId)
{
/* If keyboard event handler is NOT currently installed: */
if (m_iKeyboardGrabViewIndex == -1)
{
/* Install the keyboard event handler: */
darwinGrabKeyboardEvents(true);
}
/* Update the id: */
}
break;
}
case QEvent::WindowDeactivate:
{
/* If keyboard event handler is installed exactly for that window: */
if (m_iKeyboardGrabViewIndex == (int)uScreenId)
{
/* Remove the keyboard event handler: */
darwinGrabKeyboardEvents(false);
/* Update the id: */
m_iKeyboardGrabViewIndex = -1;
}
break;
}
#endif
default:
break;
}
}
else
/* Check if pWatchedObject object is view: */
{
/* Get corresponding screen index: */
/* Handle view events: */
{
{
/* Capture keyboard: */
#ifdef Q_WS_WIN
#else /* Q_WS_WIN */
#endif /* !Q_WS_WIN */
/* Reset the single-time disable capture flag: */
if (uisession()->isAutoCaptureDisabled())
uisession()->setAutoCaptureDisabled(false);
}
break;
/* Release keyboard: */
/* And all pressed keys: */
releaseAllPressedKeys(true);
break;
case QEvent::KeyRelease:
{
{
/* Passing F1-F12 keys to the guest: */
{
{
}
/* There is some scan slice between F10 and F11 keys, so its separated: */
{
}
}
/* Process hot keys not processed in keyEvent() (as in case of non-alphanumeric keys): */
}
{
/* Show a possible warning on key release which seems to be more expected by the end user: */
{
/* If the reminder is disabled we pass the event to Qt to enable normal
* keyboard functionality (for example, menu access with Alt+Letter): */
if (!vboxProblem().remindAboutPausedVMInput())
break;
}
}
break;
}
default:
break;
}
}
/* Else just propagate to base-class: */
}
#if defined(Q_WS_WIN)
{
if (nCode == HC_ACTION && m_pKeyboardHandler && m_pKeyboardHandler->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT*)lParam))
return 1;
}
{
/* Check what related machine-view was NOT unregistered yet: */
return false;
/* Sometimes it happens that Win inserts additional events on some key
* the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
* to specially treat ALT_GR to enter additional chars to regular apps).
* These events are definitely unwanted in VM, so filter them out. */
/* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
* code 0x23a. If this is not passed through then it is impossible to
* cancel CapsLock on a French keyboard. I didn't find any other examples
* of these strange events. Let's hope we are not missing anything else
* of importance! */
{
return false;
else
return true;
}
if (!m_fIsKeyboardCaptured)
return false;
/* It's possible that a key has been pressed while the keyboard was not
* captured, but is being released under the capture. Detect this situation
* and return false to let Windows process the message normally and update
* its key state table (to avoid the stuck key effect). */
uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed;
return false;
/* Windows sets here the extended bit when the Right Shift key is pressed,
* which is totally wrong. Undo it. */
/* We suppose here that this hook is always called on the main GUI thread */
long dummyResult;
}
{
if (fGrab)
{
/* Disable mouse and keyboard event compression/delaying to make sure we *really* get all of the events. */
UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */,
UIKeyboardHandler::darwinEventHandlerProc, this);
::DarwinGrabKeyboard (false);
}
else
{
UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */,
UIKeyboardHandler::darwinEventHandlerProc, this);
}
}
bool UIKeyboardHandler::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
{
/* Check if this is an application key combo. In that case we will not pass
* the event to the guest, but let the host process it. */
return false;
/* All keyboard class events needs to be handled. */
if (eventClass == kEventClassKeyboard)
{
return true;
}
/* Pass the event along. */
return false;
}
{
bool ret = false;
{
/* Convert keycode to set 1 scan code. */
::GetEventParameter(inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (keyCode), NULL, &keyCode);
/* The usb keyboard driver translates these codes to different virtual
* key codes depending of the keyboard type. There are ANSI, ISO, JIS
* and unknown. For European keyboards (ISO) the key 0xa and 0x32 have
* to be switched. Here we are doing this at runtime, cause the user
* can have more than one keyboard (of different type), where he may
* switch at will all the time. Default is the ANSI standard as defined
* in g_aDarwinToSet1. Please note that the "~" on some English ISO
* keyboards will be wrongly swapped. This can maybe fixed by
* using a Apple keyboard layout in the guest. */
if (scanCode)
{
/* Calc flags. */
int flags = 0;
if (EventKind != kEventRawKeyUp)
flags |= KeyPressed;
if (scanCode & VBOXKEY_EXTENDED)
flags |= KeyExtended;
/** @todo KeyPause, KeyPrint. */
/* Get the unicode string (if present). */
AssertCompileSize(wchar_t, 2);
wchar_t ucs[8];
cbWritten = 0;
}
}
else
{
/* May contain multiple modifier changes, kind of annoying. */
if (changed)
{
{
continue;
if (!scanCode)
continue;
if (!(scanCode & VBOXKEY_LOCK))
{
if (scanCode & VBOXKEY_EXTENDED)
flags |= KeyExtended;
}
else
{
unsigned flags = 0;
if (scanCode & VBOXKEY_EXTENDED)
flags |= KeyExtended;
}
}
}
/* Always return true here because we'll otherwise getting a Qt event
we don't want and that will only cause the Pause warning to pop up. */
ret = true;
}
return ret;
}
#endif
bool UIKeyboardHandler::keyEvent(int iKey, uint8_t uScan, int fFlags, ulong uScreenId, wchar_t *pUniKey /* = NULL */)
{
uint8_t whatPressed = 0;
if (!isHostKey && !m_bIsHostkeyPressed)
{
{
if (fFlags & KeyPressed)
{
}
else
{
codes = PrintBreak;
}
}
{
if (fFlags & KeyPressed)
{
}
else
{
/* Pause shall not produce a break code */
return true;
}
}
else
{
if (fFlags & KeyPressed)
{
/* Check if the guest has the same view on the modifier keys (NumLock,
* CapsLock, ScrollLock) as the X server. If not, send KeyPress events
* to synchronize the state. */
}
if (!m_fPassCAD &&
{
/* Use the C-A-D combination as a last resort to get the
* keyboard and mouse back to the host when the user forgets
* the Host Key. Note that it's always possible to send C-A-D
* to the guest using the Host+Del combination. BTW, it would
* be preferable to completely ignore C-A-D in guests, but
* that's not possible because we cannot predict what other
* keys will be pressed next when one of C, A, D is held. */
{
}
return true;
}
/* Process the scancode and update the table of pressed keys: */
if (fFlags & KeyExtended)
{
}
if (fFlags & KeyPressed)
{
}
else
{
/* If we haven't got this key's press message, we ignore its release: */
return true;
}
else
}
}
else
{
/* Currently this is used in winLowKeyboardEvent() only: */
}
bool emitSignal = false;
int hotkey = 0;
/* Process the host key: */
if (fFlags & KeyPressed)
{
if (isHostKey)
{
if (!m_bIsHostkeyPressed)
{
m_bIsHostkeyPressed = m_bIsHostkeyAlone = true;
emitSignal = true;
}
}
else
{
if (m_bIsHostkeyPressed)
{
if (m_bIsHostkeyAlone)
{
m_bIsHostkeyAlone = false;
}
}
}
}
else
{
if (isHostKey)
{
if (m_bIsHostkeyPressed)
{
m_bIsHostkeyPressed = false;
if (m_bIsHostkeyAlone)
{
{
}
{
bool ok = true;
if (!m_fIsKeyboardCaptured)
{
/* Temporarily disable auto capture that will take
* place after this dialog is dismissed because
* the capture state is to be defined by the
* dialog result itself */
uisession()->setAutoCaptureDisabled(true);
bool autoConfirmed = false;
if (autoConfirmed)
uisession()->setAutoCaptureDisabled(false);
/* Otherwise, the disable flag will be reset in
* the next console view's focus in event (since
* may happen asynchronously on some platforms,
* after we return from this code) */
}
if (ok)
{
else
{
#ifdef Q_WS_X11
/* Make sure that pending FocusOut events from the
* previous message box are handled, otherwise the
* mouse is immediately ungrabbed. */
qApp->processEvents();
#endif
else
}
}
}
}
emitSignal = true;
}
}
else
{
if (m_bIsHostkeyPressed)
m_bIsHostkeyAlone = false;
}
}
/* Notify all listeners: */
/* Process Host+<key> shortcuts. currently, <key> is limited to
* alphanumeric chars. Other Host+<key> combinations are handled in
* event(). */
if (hotkey)
{
bool processed = false;
#if defined (Q_WS_WIN)
int n = GetKeyboardLayoutList(0, NULL);
Assert(n);
for (int i = 0; i < n && !processed; i++)
{
wchar_t ch;
ch = 0;
if (ch)
processed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(ch).toUpper().unicode())));
}
delete[] list;
int keysyms_per_keycode = getKeysymsPerKeycode();
{
char ch = 0;
ch = 0;
if (ch)
{
processed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(c).toUpper().unicode())));
}
}
processed = machineLogic()->actionsPool()->processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(pUniKey[0]).toUpper().unicode()));
/* Don't consider the hot key as pressed since the guest never saw
* it. (probably a generic thing) */
#endif
/* Grab the key from Qt if processed, or pass it to Qt otherwise
* in order to process non-alphanumeric keys in event(), after they are
* converted to Qt virtual keys. */
return processed;
}
/* No more to do, if the host key is in action or the VM is paused: */
{
/* Grab the key from Qt and from VM if it's a host key,
* otherwise just pass it to Qt */
return isHostKey;
}
#ifdef Q_WS_WIN
/* Send pending WM_PAINT events: */
#endif /* Q_WS_WIN */
/* Grab the key from Qt: */
return true;
}
{
/* Synchronize the views of the host and the guest to the modifier keys.
* This function will add up to 6 additional keycodes to codes. */
#if defined(Q_WS_X11)
unsigned uMask;
for (int i = 0; i < 8; ++ i)
{
uKeyMaskNum = 1 << i;
uKeyMaskScroll = 1 << i;
}
{
}
{
/* Some keyboard layouts require shift to be pressed to break
* capslock. For simplicity, only do this if shift is not
* already held down. */
{
}
}
{
}
if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(GetKeyState(VK_CAPITAL))))
{
/* Some keyboard layouts require shift to be pressed to break
* capslock. For simplicity, only do this if shift is not
* already held down. */
{
}
}
/* if (uisession()->numLockAdaptionCnt()) ... - NumLock isn't implemented by Mac OS X so ignore it. */
if (uisession()->capsLockAdaptionCnt() && (uisession()->isCapsLock() ^ !!(::GetCurrentEventKeyModifiers() & alphaLock)))
{
/* Some keyboard layouts require shift to be pressed to break
* capslock. For simplicity, only do this if shift is not
* already held down. */
{
}
}
#else
//#warning Adapt UIKeyboardHandler::fixModifierState
#endif
}
void UIKeyboardHandler::saveKeyStates()
{
}
{
bool fSentRESEND = false;
/* Send a dummy scan code (RESEND) to prevent the guest OS from recognizing
* a single key click (for ex., Alt) and performing an unwanted action
* (for ex., activating the menu) when we release all pressed keys below.
* Note, that it's just a guess that sending RESEND will give the desired
* effect :), but at least it works with NT and W2k guests. */
{
if (m_pressedKeys[i] & IsKeyPressed)
{
if (!fSentRESEND)
{
fSentRESEND = true;
}
}
else if (m_pressedKeys[i] & IsExtKeyPressed)
{
if (!fSentRESEND)
{
fSentRESEND = true;
}
codes[0] = 0xE0;
}
m_pressedKeys[i] = 0;
}
if (aReleaseHostKey)
m_bIsHostkeyPressed = false;
#ifdef Q_WS_MAC
/* Clear most of the modifiers: */
#endif
}
{
{
{
codes[0] = i;
if (!(ns & IsKeyPressed))
codes[0] |= 0x80;
}
{
codes[0] = 0xE0;
codes[1] = i;
if (!(ns & IsExtKeyPressed))
}
}
}
{
UIMachineWindow *pResultWindow = 0;
{
{
continue;
}
++i;
}
return pResultWindow;
}
{
UIMachineView *pResultView = 0;
{
if (pIteratedView == pWatchedObject)
{
continue;
}
++i;
}
return pResultView;
}