summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp')
-rw-r--r--src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp145
1 files changed, 103 insertions, 42 deletions
diff --git a/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp b/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
index 9c1fbecc..1b81c26d 100644
--- a/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
+++ b/src/VBox/Additions/WINNT/VBoxTray/VBoxSeamless.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -24,16 +24,17 @@
#include <VBoxDisplay.h>
#include <VBox/VMMDev.h>
#include <iprt/assert.h>
+#include <iprt/ldr.h>
#include <VBoxGuestInternal.h>
typedef struct _VBOXSEAMLESSCONTEXT
{
const VBOXSERVICEENV *pEnv;
- HMODULE hModule;
+ RTLDRMOD hModHook;
- BOOL (* pfnVBoxInstallHook)(HMODULE hDll);
- BOOL (* pfnVBoxRemoveHook)();
+ BOOL (* pfnVBoxHookInstallWindowTracker)(HMODULE hDll);
+ BOOL (* pfnVBoxHookRemoveWindowTracker)();
PVBOXDISPIFESCAPE lpEscapeData;
} VBOXSEAMLESSCONTEXT;
@@ -54,6 +55,7 @@ int VBoxSeamlessInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStar
*pfStartThread = false;
gCtx.pEnv = pEnv;
+ gCtx.hModHook = NIL_RTLDRMOD;
OSVERSIONINFO OSinfo;
OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
@@ -71,27 +73,25 @@ int VBoxSeamlessInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStar
else
{
/* Will fail if SetWinEventHook is not present (version < NT4 SP6 apparently) */
- gCtx.hModule = LoadLibrary(VBOXHOOK_DLL_NAME);
- if (gCtx.hModule)
+ rc = RTLdrLoadAppPriv(VBOXHOOK_DLL_NAME, &gCtx.hModHook);
+ if (RT_SUCCESS(rc))
{
- *(uintptr_t *)&gCtx.pfnVBoxInstallHook = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxInstallHook");
- *(uintptr_t *)&gCtx.pfnVBoxRemoveHook = (uintptr_t)GetProcAddress(gCtx.hModule, "VBoxRemoveHook");
+ *(PFNRT *)&gCtx.pfnVBoxHookInstallWindowTracker = RTLdrGetFunction(gCtx.hModHook, "VBoxHookInstallWindowTracker");
+ *(PFNRT *)&gCtx.pfnVBoxHookRemoveWindowTracker = RTLdrGetFunction(gCtx.hModHook, "VBoxHookRemoveWindowTracker");
- /* Inform the host that we support the seamless window mode. */
- rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_SEAMLESS, 0);
- if (RT_SUCCESS(rc))
+ /* rc should contain success status */
+ AssertRC(rc);
+
+ VBoxSeamlessSetSupported(TRUE);
+
+// if (RT_SUCCESS(rc))
{
*pfStartThread = true;
*ppInstance = &gCtx;
}
- else
- Log(("VBoxTray: VBoxSeamlessInit: Failed to set seamless capability\n"));
}
else
- {
- rc = RTErrConvertFromWin32(GetLastError());
Log(("VBoxTray: VBoxSeamlessInit: LoadLibrary of \"%s\" failed with rc=%Rrc\n", VBOXHOOK_DLL_NAME, rc));
- }
}
return rc;
@@ -102,34 +102,36 @@ void VBoxSeamlessDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
{
Log(("VBoxTray: VBoxSeamlessDestroy\n"));
+ VBoxSeamlessSetSupported(FALSE);
+
/* Inform the host that we no longer support the seamless window mode. */
- int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_SEAMLESS);
- if (RT_FAILURE(rc))
- Log(("VBoxTray: VBoxSeamlessDestroy: Failed to unset seamless capability, rc=%Rrc\n", rc));
-
- if (gCtx.pfnVBoxRemoveHook)
- gCtx.pfnVBoxRemoveHook();
- if (gCtx.hModule)
- FreeLibrary(gCtx.hModule);
- gCtx.hModule = 0;
+ if (gCtx.pfnVBoxHookRemoveWindowTracker)
+ gCtx.pfnVBoxHookRemoveWindowTracker();
+ if (gCtx.hModHook != NIL_RTLDRMOD)
+ {
+ RTLdrClose(gCtx.hModHook);
+ gCtx.hModHook = NIL_RTLDRMOD;
+ }
return;
}
-void VBoxSeamlessInstallHook()
+static void VBoxSeamlessInstallHook()
{
- if (gCtx.pfnVBoxInstallHook)
+ if (gCtx.pfnVBoxHookInstallWindowTracker)
{
/* Check current visible region state */
- VBoxSeamlessCheckWindows();
+ VBoxSeamlessCheckWindows(true);
- gCtx.pfnVBoxInstallHook(gCtx.hModule);
+ HMODULE hMod = (HMODULE)RTLdrGetNativeHandle(gCtx.hModHook);
+ Assert(hMod != (HMODULE)~(uintptr_t)0);
+ gCtx.pfnVBoxHookInstallWindowTracker(hMod);
}
}
-void VBoxSeamlessRemoveHook()
+static void VBoxSeamlessRemoveHook()
{
- if (gCtx.pfnVBoxRemoveHook)
- gCtx.pfnVBoxRemoveHook();
+ if (gCtx.pfnVBoxHookRemoveWindowTracker)
+ gCtx.pfnVBoxHookRemoveWindowTracker();
if (gCtx.lpEscapeData)
{
@@ -138,6 +140,27 @@ void VBoxSeamlessRemoveHook()
}
}
+extern HANDLE ghSeamlessKmNotifyEvent;
+
+static VBOXDISPIF_SEAMLESS gVBoxDispIfSeamless;
+
+
+void VBoxSeamlessEnable()
+{
+ Assert(ghSeamlessKmNotifyEvent);
+
+ VBoxDispIfSeamlesCreate(&gCtx.pEnv->dispIf, &gVBoxDispIfSeamless, ghSeamlessKmNotifyEvent);
+
+ VBoxSeamlessInstallHook();
+}
+
+void VBoxSeamlessDisable()
+{
+ VBoxSeamlessRemoveHook();
+
+ VBoxDispIfSeamlesTerm(&gVBoxDispIfSeamless);
+}
+
BOOL CALLBACK VBoxEnumFunc(HWND hwnd, LPARAM lParam)
{
PVBOX_ENUM_PARAM lpParam = (PVBOX_ENUM_PARAM)lParam;
@@ -154,27 +177,60 @@ BOOL CALLBACK VBoxEnumFunc(HWND hwnd, LPARAM lParam)
/* Only visible windows that are present on the desktop are interesting here */
if (GetWindowRect(hwnd, &rectWindow))
{
- rectVisible = rectWindow;
-
char szWindowText[256];
szWindowText[0] = 0;
+ OSVERSIONINFO OSinfo;
+ HWND hStart = NULL;
GetWindowText(hwnd, szWindowText, sizeof(szWindowText));
+ OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
+ GetVersionEx (&OSinfo);
+ if (OSinfo.dwMajorVersion >= 6)
+ {
+ hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", "Start");
+ if ( hwnd == hStart && szWindowText != NULL
+ && !(strcmp(szWindowText, "Start"))
+ )
+ {
+ /* for vista and above. To solve the issue of small bar above
+ * the Start button when mouse is hovered over the start button in seamless mode.
+ * Difference of 7 is observed in Win 7 platform between the dimensionsof rectangle with Start title and its shadow.
+ */
+ rectWindow.top += 7;
+ rectWindow.bottom -=7;
+ }
+ }
+ rectVisible = rectWindow;
+
+#ifdef LOG_ENABLED
+ DWORD pid = 0;
+ DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
+#endif
/* Filter out Windows XP shadow windows */
/** @todo still shows inside the guest */
if ( szWindowText[0] == 0
- && dwStyle == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS)
- && dwExStyle == (WS_EX_LAYERED|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|WS_EX_TOPMOST))
+ && (
+ (dwStyle == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS)
+ && dwExStyle == (WS_EX_LAYERED|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|WS_EX_TOPMOST))
+ || (dwStyle == (WS_POPUP|WS_VISIBLE|WS_DISABLED|WS_CLIPSIBLINGS|WS_CLIPCHILDREN)
+ && dwExStyle == (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE))
+ || (dwStyle == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN)
+ && dwExStyle == (WS_EX_TOOLWINDOW))
+ ))
{
Log(("VBoxTray: Filter out shadow window style=%x exstyle=%x\n", dwStyle, dwExStyle));
+ Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (filtered)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
+ Log(("VBoxTray: title=%s style=%x exStyle=%x\n", szWindowText, dwStyle, dwExStyle));
+ Log(("VBoxTray: pid=%d tid=%d\n", pid, tid));
return TRUE;
}
/** @todo will this suffice? The Program Manager window covers the whole screen */
if (strcmp(szWindowText, "Program Manager"))
{
- Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
+ Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (applying)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
Log(("VBoxTray: title=%s style=%x exStyle=%x\n", szWindowText, dwStyle, dwExStyle));
+ Log(("VBoxTray: pid=%d tid=%d\n", pid, tid));
HRGN hrgn = CreateRectRgn(0,0,0,0);
@@ -203,13 +259,17 @@ BOOL CALLBACK VBoxEnumFunc(HWND hwnd, LPARAM lParam)
{
Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (ignored)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
Log(("VBoxTray: title=%s style=%x\n", szWindowText, dwStyle));
+ Log(("VBoxTray: pid=%d tid=%d\n", pid, tid));
}
}
return TRUE; /* continue enumeration */
}
-void VBoxSeamlessCheckWindows()
+void VBoxSeamlessCheckWindows(bool fForce)
{
+ if (!VBoxDispIfSeamlesIsValid(&gVBoxDispIfSeamless))
+ return;
+
VBOX_ENUM_PARAM param;
param.hdc = GetDC(HWND_DESKTOP);
@@ -243,12 +303,13 @@ void VBoxSeamlessCheckWindows()
}
#endif
LPRGNDATA lpCtxRgnData = VBOXDISPIFESCAPE_DATA(gCtx.lpEscapeData, RGNDATA);
- if ( !gCtx.lpEscapeData
+ if (fForce
+ || !gCtx.lpEscapeData
|| (lpCtxRgnData->rdh.dwSize + lpCtxRgnData->rdh.nRgnSize != cbSize)
|| memcmp(lpCtxRgnData, lpRgnData, cbSize))
{
/* send to display driver */
- VBoxDispIfEscape(&gCtx.pEnv->dispIf, lpEscapeData, cbSize);
+ VBoxDispIfSeamlesSubmit(&gVBoxDispIfSeamless, lpEscapeData, cbSize);
if (gCtx.lpEscapeData)
free(gCtx.lpEscapeData);
@@ -341,7 +402,7 @@ unsigned __stdcall VBoxSeamlessThread(void *pInstance)
if (!ret)
Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError()));
}
- PostMessage(ghwndToolWindow, WM_VBOX_REMOVE_SEAMLESS_HOOK, 0, 0);
+ PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0);
break;
case VMMDev_Seamless_Visible_Region:
@@ -355,7 +416,7 @@ unsigned __stdcall VBoxSeamlessThread(void *pInstance)
ret = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
if (!ret)
Log(("VBoxTray: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %d\n", GetLastError()));
- PostMessage(ghwndToolWindow, WM_VBOX_INSTALL_SEAMLESS_HOOK, 0, 0);
+ PostMessage(ghwndToolWindow, WM_VBOX_SEAMLESS_ENABLE, 0, 0);
break;
case VMMDev_Seamless_Host_Window: