Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
413
Src/omBrowser/browserThread.cpp
Normal file
413
Src/omBrowser/browserThread.cpp
Normal file
|
@ -0,0 +1,413 @@
|
|||
#include "main.h"
|
||||
#include "./browserThread.h"
|
||||
#include "../nu/threadname.h"
|
||||
|
||||
#include <exdisp.h>
|
||||
|
||||
typedef struct __BROWSERTHREADCRAEATEPARAM
|
||||
{
|
||||
BTCREATEWNDPROC fnCreateWnd;
|
||||
BTKEYFILTERPROC fnKeyFilter;
|
||||
ULONG_PTR user;
|
||||
HANDLE readyEvent;
|
||||
HWND hHost;
|
||||
HWND hWinamp;
|
||||
} BROWSERTHREADCREATEPARAM;
|
||||
|
||||
typedef struct __BROWSERTHREAD
|
||||
{
|
||||
HHOOK messageHook;
|
||||
HANDLE wakeupEvent;
|
||||
UINT flags;
|
||||
} BROWSERTHREAD;
|
||||
|
||||
#define NAVIGATE_WAITTIMEOUT 30
|
||||
|
||||
static size_t tlsIndex = TLS_OUT_OF_INDEXES;
|
||||
static UINT BHTM_DESTROY = 0xFEFE;
|
||||
|
||||
static DWORD CALLBACK BrowserThread_MainLoop(LPVOID param);
|
||||
|
||||
#define GetThreadInstance() ((TLS_OUT_OF_INDEXES != tlsIndex) ? (BROWSERTHREAD*)Plugin_TlsGetValue(tlsIndex) : NULL)
|
||||
|
||||
BOOL BrowserThread_IsQuiting()
|
||||
{
|
||||
BROWSERTHREAD *thread = GetThreadInstance();
|
||||
return (NULL == thread || 0 != ((BHTF_BEGINDESTROY | BHTF_QUITLOOP) & thread->flags));
|
||||
}
|
||||
|
||||
BOOL BrowserThread_SetFlags(UINT flags, UINT flagsMask, BOOL fAlarm)
|
||||
{
|
||||
BROWSERTHREAD *thread = GetThreadInstance();
|
||||
if (NULL == thread) return FALSE;
|
||||
|
||||
thread->flags = ((thread->flags & flagsMask) | flags);
|
||||
if (FALSE == fAlarm)
|
||||
return TRUE;
|
||||
|
||||
return (NULL != thread->wakeupEvent && SetEvent(thread->wakeupEvent));
|
||||
}
|
||||
|
||||
|
||||
HANDLE BrowserThread_Create(HWND hWinamp, BTCREATEWNDPROC fnCreateWnd, ULONG_PTR user, BTKEYFILTERPROC fnKeyFilter, HWND *pWnd, DWORD *pThreadId)
|
||||
{
|
||||
if (NULL == fnCreateWnd)
|
||||
return NULL;
|
||||
|
||||
if (TLS_OUT_OF_INDEXES == tlsIndex)
|
||||
{
|
||||
tlsIndex = Plugin_TlsAlloc();
|
||||
if (TLS_OUT_OF_INDEXES == tlsIndex)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD threadId;
|
||||
|
||||
BROWSERTHREADCREATEPARAM param;
|
||||
ZeroMemory(¶m, sizeof(BROWSERTHREADCREATEPARAM));
|
||||
|
||||
param.fnCreateWnd = fnCreateWnd;
|
||||
param.fnKeyFilter = fnKeyFilter;
|
||||
param.user = user;
|
||||
param.readyEvent = CreateEvent(0, TRUE, FALSE, 0);
|
||||
param.hWinamp = hWinamp;
|
||||
|
||||
HANDLE hThread = CreateThread(NULL, 0, BrowserThread_MainLoop, (LPVOID)¶m, 0, &threadId);
|
||||
|
||||
if (NULL != hThread)
|
||||
{
|
||||
if (NULL != param.readyEvent)
|
||||
WaitForSingleObject(param.readyEvent, INFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NULL != param.hHost)
|
||||
{
|
||||
DestroyWindow(param.hHost);
|
||||
param.hHost = NULL;
|
||||
}
|
||||
threadId = 0;
|
||||
}
|
||||
|
||||
if (NULL != param.readyEvent)
|
||||
CloseHandle(param.readyEvent);
|
||||
|
||||
|
||||
if (NULL != pThreadId)
|
||||
*pThreadId = threadId;
|
||||
|
||||
if (NULL != pWnd)
|
||||
*pWnd = param.hHost;
|
||||
|
||||
return hThread;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL BrowserThread_PostDestroyEx(DWORD threadId, HWND hHost)
|
||||
{
|
||||
if (0 == BHTM_DESTROY)
|
||||
BHTM_DESTROY = RegisterWindowMessage(L"omBrowserDestroyMsg");
|
||||
|
||||
if (0 == BHTM_DESTROY ||
|
||||
FALSE == PostThreadMessage(threadId, BHTM_DESTROY, 0, (LPARAM)hHost))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BrowserThread_SetFlags(BHTF_BEGINDESTROY, BHTF_BEGINDESTROY, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL BrowserThread_PostDestroy(HWND hHost)
|
||||
{
|
||||
return BrowserThread_PostDestroyEx(GetCurrentThreadId(), hHost);
|
||||
}
|
||||
|
||||
BOOL BrowserThread_WaitNavigateComplete(IWebBrowser2 *pWeb2, UINT waitMax)
|
||||
{
|
||||
MSG msg;
|
||||
READYSTATE state;
|
||||
if (NULL == pWeb2)
|
||||
return FALSE;
|
||||
|
||||
BOOL resultOk = FALSE;
|
||||
DWORD tickStart = GetTickCount();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (FAILED(pWeb2->get_ReadyState(&state)))
|
||||
break;
|
||||
|
||||
if (READYSTATE_INTERACTIVE <= state)
|
||||
{
|
||||
resultOk = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD tickNow = GetTickCount();
|
||||
if (tickNow < tickStart || (tickNow - tickStart) >= waitMax)
|
||||
{
|
||||
break; // time out
|
||||
}
|
||||
}
|
||||
|
||||
DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, NAVIGATE_WAITTIMEOUT, QS_POSTMESSAGE | QS_TIMER | QS_SENDMESSAGE, MWMO_ALERTABLE);
|
||||
switch(status)
|
||||
{
|
||||
case (WAIT_OBJECT_0 + 0):
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (!CallMsgFilter(&msg, MSGF_BROWSERLOOP))
|
||||
{
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resultOk;
|
||||
}
|
||||
|
||||
static BOOL BrowserThread_HandleMessage(MSG *pMsg)
|
||||
{
|
||||
switch(pMsg->message)
|
||||
{
|
||||
case WM_QUIT:
|
||||
BrowserThread_SetFlags(BHTF_QUITLOOP, BHTF_QUITLOOP, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (0 != BHTM_DESTROY && BHTM_DESTROY == pMsg->message)
|
||||
{
|
||||
HWND hHost = (HWND)pMsg->lParam;
|
||||
if (NULL != hHost)
|
||||
{
|
||||
BrowserThread_SetFlags(BHTF_BEGINDESTROY, BHTF_BEGINDESTROY, FALSE);
|
||||
SendMessage(hHost, BTM_RELEASECONTAINER, 0, 0L);
|
||||
DestroyWindow(hHost);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK BrowserThread_MessageFilterProc(INT code, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
BROWSERTHREAD *thread = GetThreadInstance();
|
||||
if (code >= 0)
|
||||
{
|
||||
if (BrowserThread_HandleMessage((MSG*)lParam))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL != thread && NULL != thread->messageHook) ?
|
||||
CallNextHookEx(thread->messageHook, code, wParam, lParam) :
|
||||
FALSE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK BrowserThread_DefaultKeyFilter(HWND hwnd, MSG *pMsg)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
inline static BOOL BrowserThread_ProcessMessage(HWND hHost, HWND hWinamp, MSG *pMsg, BTKEYFILTERPROC IsHostMessage)
|
||||
{
|
||||
if (hHost != pMsg->hwnd && FALSE == IsChild(hHost, pMsg->hwnd))
|
||||
return FALSE;
|
||||
|
||||
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
|
||||
{
|
||||
if (FALSE != IsHostMessage(hHost, pMsg))
|
||||
return TRUE;
|
||||
|
||||
switch(pMsg->wParam)
|
||||
{
|
||||
case VK_TAB:
|
||||
{
|
||||
HWND hOwner = (HWND)(LONG_PTR)GetWindowLongPtr(hHost, GWLP_HWNDPARENT);
|
||||
if (NULL == hOwner || hWinamp == hOwner)
|
||||
hOwner = hHost;
|
||||
return IsDialogMessageW(hOwner, pMsg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pMsg->message == WM_MOUSEWHEEL)
|
||||
{
|
||||
POINT cursor;
|
||||
HWND targetWindow;
|
||||
|
||||
POINTSTOPOINT(cursor, pMsg->lParam);
|
||||
targetWindow = WindowFromPoint(cursor);
|
||||
|
||||
if (NULL != targetWindow &&
|
||||
FALSE == IsChild(hHost, targetWindow ) &&
|
||||
GetWindowThreadProcessId(targetWindow, NULL) != GetWindowThreadProcessId(hHost, NULL))
|
||||
{
|
||||
PostMessage(hWinamp, pMsg->message, pMsg->wParam, pMsg->lParam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void BrowserThread_FinishThread(BROWSERTHREAD *thread)
|
||||
{
|
||||
if (NULL != thread)
|
||||
{
|
||||
if (NULL != thread->messageHook)
|
||||
{
|
||||
UnhookWindowsHookEx(thread->messageHook);
|
||||
thread->messageHook = NULL;
|
||||
}
|
||||
|
||||
if (NULL != thread->wakeupEvent)
|
||||
{
|
||||
CloseHandle(thread->wakeupEvent);
|
||||
thread->wakeupEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != tlsIndex)
|
||||
Plugin_TlsSetValue(tlsIndex, NULL);
|
||||
|
||||
OleUninitialize();
|
||||
|
||||
#ifdef _DEBUG
|
||||
aTRACE_FMT("[%d] %S: thread exit\r\n", GetCurrentThreadId(), OMBROWSER_NAME);
|
||||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
static DWORD CALLBACK BrowserThread_MainLoop(LPVOID param)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
SetThreadName(GetCurrentThreadId(), "omBrowserThread");
|
||||
aTRACE_FMT("[%d] %S: thread created\r\n", GetCurrentThreadId(), OMBROWSER_NAME);
|
||||
#endif //_DEBUG
|
||||
|
||||
BROWSERTHREADCREATEPARAM *createParam = (BROWSERTHREADCREATEPARAM*)param;
|
||||
|
||||
HWND hWinamp = createParam->hWinamp;
|
||||
|
||||
BROWSERTHREAD thread;
|
||||
ZeroMemory(&thread, sizeof(BROWSERTHREAD));
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != tlsIndex)
|
||||
Plugin_TlsSetValue(tlsIndex, &thread);
|
||||
|
||||
MSG msg;
|
||||
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
||||
|
||||
BTKEYFILTERPROC IsHostMessage = (NULL != createParam->fnKeyFilter) ? createParam->fnKeyFilter : BrowserThread_DefaultKeyFilter;
|
||||
|
||||
thread.messageHook = SetWindowsHookEx(WH_MSGFILTER, BrowserThread_MessageFilterProc, NULL, GetCurrentThreadId());
|
||||
thread.wakeupEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
HWND hHost = createParam->fnCreateWnd(createParam->user);
|
||||
|
||||
createParam->hHost = hHost;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (NULL != hHost)
|
||||
aTRACE_FMT("[%d] %S: host created\r\n", GetCurrentThreadId(), OMBROWSER_NAME);
|
||||
else
|
||||
aTRACE_FMT("[%d] %S: host creation fialed\r\n", GetCurrentThreadId(), OMBROWSER_NAME);
|
||||
#endif //_DEBUG
|
||||
|
||||
if (NULL != createParam->readyEvent)
|
||||
SetEvent(createParam->readyEvent);
|
||||
|
||||
|
||||
if (NULL != hHost && FAILED(OleInitialize(0)))
|
||||
{
|
||||
DestroyWindow(hHost);
|
||||
hHost = NULL;
|
||||
}
|
||||
|
||||
if (NULL == hHost)
|
||||
{
|
||||
BrowserThread_FinishThread(&thread);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SendMessage(hHost, BTM_INITCONTAINER, (WPARAM)hWinamp, 0L);
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
|
||||
|
||||
while (0 == (BHTF_QUITLOOP & thread.flags))
|
||||
{
|
||||
DWORD status = MsgWaitForMultipleObjectsEx(1, &thread.wakeupEvent, INFINITE,
|
||||
QS_ALLPOSTMESSAGE | QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case (WAIT_OBJECT_0 + 0):
|
||||
// wake up!!!
|
||||
break;
|
||||
|
||||
case (WAIT_OBJECT_0 + 1):
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (!CallMsgFilter(&msg, MSGF_BROWSERLOOP) && NULL != msg.hwnd)
|
||||
{
|
||||
if (0 == (BHTF_BEGINDESTROY & thread.flags))
|
||||
{
|
||||
if (FALSE == BrowserThread_ProcessMessage(hHost, hWinamp, &msg, IsHostMessage))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BrowserThread_FinishThread(&thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT BrowserThread_ModalLoop(HWND hwnd, HANDLE hCancel, DWORD timeout)
|
||||
{
|
||||
MSG msg;
|
||||
for (;;)
|
||||
{
|
||||
DWORD status = MsgWaitForMultipleObjectsEx(1, &hCancel, timeout, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||||
if (WAIT_OBJECT_0 == status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ((WAIT_OBJECT_0 + 1) == status)
|
||||
{
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
PostQuitMessage((INT)msg.wParam);
|
||||
return (INT)msg.wParam;
|
||||
}
|
||||
|
||||
if (!IsDialogMessageW(hwnd, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue