diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp index 31b05578656..c5e3c337614 100644 --- a/dll/win32/msutb/msutb.cpp +++ b/dll/win32/msutb/msutb.cpp @@ -20,6 +20,7 @@ LONG g_DllRefCount = 0; BOOL g_bWinLogon = FALSE; BOOL g_fInClosePopupTipbar = FALSE; HWND g_hwndParent = NULL; +LIBTHREAD g_libTLS = { NULL, NULL }; #ifdef ENABLE_DESKBAND BOOL g_bEnableDeskBand = TRUE; #else @@ -76,6 +77,23 @@ class CMsUtbModule : public CComModule CMsUtbModule gModule; +void TFUninitLib_Thread(LIBTHREAD *libThread) +{ + if (!libThread) + return; + + if (libThread->m_pUnknown1) + { + libThread->m_pUnknown1->Release(); + libThread->m_pUnknown1 = NULL; + } + if (libThread->m_pDisplayAttrMgr) + { + libThread->m_pDisplayAttrMgr->Release(); + libThread->m_pDisplayAttrMgr = NULL; + } +} + class CCicLibMenuItem; class CTipbarAccItem; class CUTBMenuItem; @@ -1259,6 +1277,7 @@ public: /***********************************************************************/ class CTipbarItem; +class CTipbarBalloonItem; class CTipbarThread { @@ -1306,6 +1325,18 @@ public: LONG _AddRef() { return ++m_cRefs; } LONG _Release(); + /// @unimplemented + BOOL SetFocus(CTipbarBalloonItem *pTarget) + { + return FALSE; + } + + /// @unimplemented + HRESULT CallOnUpdateHandler() + { + return E_NOTIMPL; + } + //FIXME }; @@ -1383,6 +1414,24 @@ public: class CTipbarCtrlButtonHolder; class CDeskBand; +// Flags for m_dwTipbarWndFlags +enum +{ + TIPBAR_ATTACHED = 0x1, + TIPBAR_CHILD = 0x2, + TIPBAR_VERTICAL = 0x4, + TIPBAR_HIGHCONTRAST = 0x10, + TIPBAR_TRAYICON = 0x20, + TIPBAR_UPDATING = 0x400, + TIPBAR_ENSURING = 0x2000, + TIPBAR_NODESKBAND = 0x4000, + TIPBAR_TOOLBARENDED = 0x10000, + TIPBAR_TOPFIT = 0x40000, + TIPBAR_BOTTOMFIT = 0x80000, + TIPBAR_RIGHTFIT = 0x100000, + TIPBAR_LEFTFIT = 0x200000, +}; + class CTipbarWnd : public ITfLangBarEventSink , public ITfLangBarEventSink_P @@ -1434,6 +1483,7 @@ class CTipbarWnd friend class CTipbarGripper; friend class CTipbarThread; friend class CTipbarItem; + friend class CLBarInatItem; friend VOID WINAPI ClosePopupTipbar(VOID); friend BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand); friend LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds); @@ -1522,6 +1572,12 @@ public: void OnTerminateToolbar(); HRESULT OnThreadTerminateInternal(DWORD dwThreadId); + /// @unimplemented + HRESULT OnThreadItemChangeInternal(DWORD dwThreadId) + { + return E_NOTIMPL; + } + // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj); STDMETHOD_(ULONG, AddRef)(); @@ -2807,7 +2863,7 @@ CUTBMenuWnd *CUTBContextMenu::CreateMenuUI(BOOL bFlag) CUTBMenuItem *pVertical = InsertItem(pMenuUI, ID_VERTICAL, IDS_VERTICAL); if (pVertical) - pVertical->Check(!!(m_pTipbarWnd->m_dwTipbarWndFlags & 0x800000)); + pVertical->Check(!!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL)); } } @@ -2940,12 +2996,12 @@ BOOL CUTBContextMenu::SelectMenuItem(UINT nCommandId) } case ID_EXTRAICONS: - m_pTipbarWnd->m_dwTipbarWndFlags &= ~0x4000; + m_pTipbarWnd->m_dwTipbarWndFlags &= ~TIPBAR_NODESKBAND; m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_EXTRAICONSONMINIMIZED); break; case ID_NOEXTRAICONS: - m_pTipbarWnd->m_dwTipbarWndFlags &= ~0x4000; + m_pTipbarWnd->m_dwTipbarWndFlags &= ~TIPBAR_NODESKBAND; m_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_NOEXTRAICONSONMINIMIZED); break; @@ -2954,7 +3010,7 @@ BOOL CUTBContextMenu::SelectMenuItem(UINT nCommandId) break; case ID_VERTICAL: - m_pTipbarWnd->SetVertical((m_pTipbarWnd->m_dwTipbarWndFlags & 0x4) ? TRUE : FALSE); + m_pTipbarWnd->SetVertical(!!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL)); break; case ID_ADJUSTDESKBAND: @@ -3759,7 +3815,6 @@ STDMETHODIMP CLBarInatItem::InitMenu(ITfMenu *pMenu) } } -#if 0 // FIXME: g_pTipbarWnd DWORD dwStatus; if (g_pTipbarWnd && g_pTipbarWnd->m_pLangBarMgr && @@ -3772,7 +3827,6 @@ STDMETHODIMP CLBarInatItem::InitMenu(ITfMenu *pMenu) ::LoadStringW(g_hInst, IDS_RESTORELANGBAR2, szText, _countof(szText)); LangBarInsertMenu(pMenu, 2000, szText, FALSE, NULL); } -#endif return S_OK; } @@ -3785,18 +3839,14 @@ STDMETHODIMP CLBarInatItem::OnMenuSelect(INT nCommandId) { if (g_pTipbarWnd) { -#if 0 // FIXME: g_pTipbarWnd ITfLangBarMgr *pLangBarMgr = g_pTipbarWnd->m_pLangBarMgr; if (pLangBarMgr) pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL); -#endif } } else if (TF_GetMlngHKL(nCommandId, &hKL, NULL, 0)) { -#if 0 // FIXME: g_pTipbarWnd - g_pTipbarWnd->RestoreLastFocus(0, (g_pTipbarWnd->m_dwTipbarWndFlags & 2) != 0); -#endif + g_pTipbarWnd->RestoreLastFocus(NULL, !!(g_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_CHILD)); HWND hwndFore = ::GetForegroundWindow(); if (m_dwThreadId == ::GetWindowThreadProcessId(hwndFore, NULL)) { @@ -3912,7 +3962,6 @@ CTipbarWnd::CTipbarWnd(DWORD style) m_cRefs = 1; } -/// @unimplemented CTipbarWnd::~CTipbarWnd() { UnInit(); @@ -3922,23 +3971,66 @@ CTipbarWnd::~CTipbarWnd() if (m_hTextFont) ::DeleteObject(m_hTextFont); - //TFUninitLib_Thread(&g_libTLS); //FIXME + TFUninitLib_Thread(&g_libTLS); } /// @unimplemented void CTipbarWnd::Init(BOOL bChild, CDeskBand *pDeskBand) { + if (bChild) + m_dwTipbarWndFlags |= TIPBAR_CHILD; + else + m_dwTipbarWndFlags &= ~TIPBAR_CHILD; + + if (m_dwTipbarWndFlags & TIPBAR_CHILD) + m_dwTipbarWndFlags &= TIPBAR_HIGHCONTRAST; + + m_pDeskBand = pDeskBand; + + RECT rc = { 0, 0, 0, 0 }; + + if (g_bNewLook && !m_pWndFrame && (m_style & 0x20000000)) + { + CUIFWndFrame *pWndFrame = new(cicNoThrow) CUIFWndFrame(GetWindow(), &rc, 0); + if (pWndFrame) + { + pWndFrame->Initialize(); + AddUIObj(m_pWndFrame); + } + } + + if (!m_pTipbarGripper && !(m_dwTipbarWndFlags & TIPBAR_CHILD)) + { + m_pTipbarGripper = + new(cicNoThrow) CTipbarGripper(this, &rc, !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL)); + if (m_pTipbarGripper) + { + m_pTipbarGripper->Initialize(); + AddUIObj(m_pTipbarGripper); + } + } + + //FIXME: CTipbarCtrlButtonHolder + + if (m_dwTipbarWndFlags & TIPBAR_VERTICAL) + { + Move(m_nLeft, m_nTop, GetTipbarHeight(), 0); + } + else + { + Move(m_nLeft, m_nTop, 0, GetTipbarHeight()); + } } void CTipbarWnd::InitHighContrast() { - m_dwTipbarWndFlags &= ~0x10; + m_dwTipbarWndFlags &= ~TIPBAR_HIGHCONTRAST; HIGHCONTRAST HiCon = { sizeof(HiCon) }; if (::SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HiCon), &HiCon, 0)) { if (HiCon.dwFlags & HCF_HIGHCONTRASTON) - m_dwTipbarWndFlags |= 0x10; + m_dwTipbarWndFlags |= TIPBAR_HIGHCONTRAST; } } @@ -3999,9 +4091,29 @@ void CTipbarWnd::InitThemeMargins() theme.CloseThemeData(); } -/// @unimplemented void CTipbarWnd::UnInit() { + SetFocusThread(NULL); + for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem) + { + CTipbarThread* pThread = m_Threads[iItem]; + if (pThread) + { + pThread->_UninitItemList(TRUE); + pThread->m_pTipbarWnd = NULL; + pThread->_Release(); + } + } + m_Threads.clear(); + + if (m_pLangBarMgr) + m_pLangBarMgr->UnAdviseEventSink(m_dwSinkCookie); + + if (m_pLangBarMgr) + { + m_pLangBarMgr->Release(); + m_pLangBarMgr = NULL; + } } BOOL CTipbarWnd::IsFullScreenWindow(HWND hWnd) @@ -4029,10 +4141,11 @@ BOOL CTipbarWnd::IsHKLToSkipRedrawOnNoItem() return IsSkipRedrawHKL(hKL); } -/// @unimplemented BOOL CTipbarWnd::IsInItemChangeOrDirty(CTipbarThread *pTarget) { - return FALSE; + if (pTarget->m_dwThreadId == m_dwChangingThreadId) + return TRUE; + return pTarget->IsDirtyItem(); } void CTipbarWnd::AddThreadToThreadCreatingList(CTipbarThread *pThread) @@ -4047,9 +4160,30 @@ void CTipbarWnd::RemoveThredFromThreadCreatingList(CTipbarThread *pTarget) m_ThreadCreatingList.Remove(iItem); } -/// @unimplemented void CTipbarWnd::MoveToStub(BOOL bFlag) { + m_dwTipbarWndFlags |= 0x40; + + RECT rcWorkArea; + ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); + + if (bFlag) + { + m_nLeft = rcWorkArea.right - 38; + m_dwTipbarWndFlags &= ~0x80; + } + else + { + RECT Rect; + ::GetWindowRect(m_hWnd, &Rect); + m_nLeft = rcWorkArea.right + Rect.left - Rect.right; + m_dwTipbarWndFlags |= 0x80; + } + + m_nTop = rcWorkArea.bottom - m_cyDlgFrameX2 - GetTipbarHeight(); + + if (m_pFocusThread) + m_pFocusThread->MyMoveWnd(0, 0); } void CTipbarWnd::RestoreFromStub() @@ -4099,10 +4233,23 @@ INT CTipbarWnd::GetTipbarHeight() return m_cySmallIcon + cy + (2 * size.cy); } -/// @unimplemented BOOL CTipbarWnd::AutoAdjustDeskBandSize() { - return FALSE; + if ((m_dwTipbarWndFlags & TIPBAR_NODESKBAND) || + !m_pFocusThread || + (m_pFocusThread->m_dwFlags1 & 0x800)) + { + return FALSE; + } + + DWORD dwOldWndFlags = m_dwTipbarWndFlags; + m_dwTipbarWndFlags &= ~0x8000; + + if (!AdjustDeskBandSize(!(dwOldWndFlags & 0x8000))) + return FALSE; + + m_dwTipbarWndFlags |= TIPBAR_NODESKBAND; + return TRUE; } /// @unimplemented @@ -4124,13 +4271,13 @@ void CTipbarWnd::AdjustPosOnDisplayChange() return; INT x = m_nLeft, y = m_nTop; - if (m_dwTipbarWndFlags & 0x200000) + if (m_dwTipbarWndFlags & TIPBAR_LEFTFIT) x = rcWorkArea.left; - if (m_dwTipbarWndFlags & 0x40000) + if (m_dwTipbarWndFlags & TIPBAR_TOPFIT) y = rcWorkArea.top; - if (m_dwTipbarWndFlags & 0x100000) + if (m_dwTipbarWndFlags & TIPBAR_RIGHTFIT) x = rcWorkArea.right - m_nWidth; - if (m_dwTipbarWndFlags & 0x80000) + if (m_dwTipbarWndFlags & TIPBAR_BOTTOMFIT) y = rcWorkArea.bottom - m_nHeight; if (x != m_nLeft || y != m_nTop) Move(x, y, m_nWidth, m_nHeight); @@ -4139,9 +4286,9 @@ void CTipbarWnd::AdjustPosOnDisplayChange() void CTipbarWnd::SetVertical(BOOL bVertical) { if (bVertical) - m_dwTipbarWndFlags |= 0x4; + m_dwTipbarWndFlags |= TIPBAR_VERTICAL; else - m_dwTipbarWndFlags &= ~0x4; + m_dwTipbarWndFlags &= ~TIPBAR_VERTICAL; if (m_pTipbarGripper) { @@ -4154,11 +4301,11 @@ void CTipbarWnd::SetVertical(BOOL bVertical) } if (g_fTaskbarTheme) - SetActiveTheme(L"TASKBAR", !!(m_dwTipbarWndFlags & 0x4), 1); + SetActiveTheme(L"TASKBAR", !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL), 1); - if (!(m_dwTipbarWndFlags & 2)) + if (!(m_dwTipbarWndFlags & TIPBAR_CHILD)) { - if (m_dwTipbarWndFlags & 4) + if (m_dwTipbarWndFlags & TIPBAR_VERTICAL) { Move(m_nLeft, m_nTop, GetTipbarHeight(), 0); } @@ -4177,37 +4324,48 @@ void CTipbarWnd::SetVertical(BOOL bVertical) void CTipbarWnd::UpdatePosFlags() { - if (m_dwTipbarWndFlags & 0x2) + if (m_dwTipbarWndFlags & TIPBAR_CHILD) return; RECT rc = { m_nLeft, m_nTop, m_nLeft + m_nWidth, m_nTop + m_nHeight }, rcWorkArea; if (!GetWorkArea(&rc, &rcWorkArea)) return; - if (m_nLeft > rcWorkArea.left + 2) - m_dwTipbarWndFlags &= ~0x200000; + if (rcWorkArea.left + 2 < m_nLeft) + m_dwTipbarWndFlags &= ~TIPBAR_LEFTFIT; else - m_dwTipbarWndFlags |= 0x200000; + m_dwTipbarWndFlags |= TIPBAR_LEFTFIT; - if ( m_nTop> rcWorkArea.top + 2 ) - m_dwTipbarWndFlags &= ~0x40000; + if (rcWorkArea.top + 2 < m_nTop) + m_dwTipbarWndFlags &= ~TIPBAR_TOPFIT; else - m_dwTipbarWndFlags |= 0x40000; + m_dwTipbarWndFlags |= TIPBAR_TOPFIT; if (m_nLeft + m_nWidth < rcWorkArea.right - 2) - m_dwTipbarWndFlags &= ~0x100000; + m_dwTipbarWndFlags &= ~TIPBAR_RIGHTFIT; else - m_dwTipbarWndFlags |= 0x100000; + m_dwTipbarWndFlags |= TIPBAR_RIGHTFIT; if (m_nTop + m_nHeight < rcWorkArea.bottom - 2) - m_dwTipbarWndFlags &= ~0x80000; + m_dwTipbarWndFlags &= ~TIPBAR_BOTTOMFIT; else - m_dwTipbarWndFlags |= 0x80000; + m_dwTipbarWndFlags |= TIPBAR_BOTTOMFIT; } -/// @unimplemented void CTipbarWnd::CancelMenu() { + if (!m_pThread) + return; + + CTipbarWnd *pTipbarWnd = m_pThread->m_pTipbarWnd; + if (pTipbarWnd) + { + if (pTipbarWnd->m_pLangBarMgr) + pTipbarWnd->StartModalInput(NULL, m_pThread->m_dwThreadId); + } + + m_pModalMenu->CancelMenu(); + StartBackToAlphaTimer(); } BOOL CTipbarWnd::CheckExcludeCaptionButtonMode(LPRECT prc1, LPCRECT prc2) @@ -4215,9 +4373,11 @@ BOOL CTipbarWnd::CheckExcludeCaptionButtonMode(LPRECT prc1, LPCRECT prc2) return (prc1->top < prc2->top + 5) && (prc2->right <= prc1->right + (5 * m_ButtonWidth)); } -/// @unimplemented void CTipbarWnd::ClearLBItemList() { + m_TipbarGUIDArray.clear(); + if (m_pFocusThread) + OnThreadItemChange(m_pFocusThread->m_dwThreadId); } HFONT CTipbarWnd::CreateVerticalFont() @@ -4253,7 +4413,7 @@ HFONT CTipbarWnd::CreateVerticalFont() void CTipbarWnd::UpdateVerticalFont() { - if (m_dwTipbarWndFlags & 4) + if (m_dwTipbarWndFlags & TIPBAR_VERTICAL) { if (m_hTextFont) { @@ -4273,6 +4433,7 @@ void CTipbarWnd::UpdateVerticalFont() /// @unimplemented void CTipbarWnd::ShowOverScreenSizeBalloon() { + //FIXME: CTipbarCtrlButtonHolder } void CTipbarWnd::DestroyOverScreenSizeBalloon() @@ -4292,15 +4453,26 @@ void CTipbarWnd::DestroyWnd() ::DestroyWindow(m_hWnd); } -/// @unimplemented HKL CTipbarWnd::GetFocusKeyboardLayout() { - return NULL; + DWORD dwThreadId = 0; + if (m_pFocusThread) + dwThreadId = m_pFocusThread->m_dwThreadId; + return ::GetKeyboardLayout(dwThreadId); } -/// @unimplemented void CTipbarWnd::KillOnTheadItemChangeTimer() { + DWORD dwChangingThreadId = m_dwChangingThreadId; + m_dwChangingThreadId = 0; + KillTimer(4); + + if (dwChangingThreadId) + { + CTipbarThread *pThread = _FindThread(dwChangingThreadId); + if (pThread) + pThread->m_dwUnknown34 |= 0x1; + } } UINT_PTR CTipbarWnd::SetTimer(UINT_PTR nIDEvent, UINT uElapse) @@ -4347,7 +4519,7 @@ void CTipbarWnd::SavePosition() ::ClientToScreen(m_hWnd, &pt); regKey.SetDword(TEXT("Left"), pt.x); regKey.SetDword(TEXT("Top"), pt.y); - regKey.SetDword(TEXT("Vertical"), !!(m_dwTipbarWndFlags & 4)); + regKey.SetDword(TEXT("Vertical"), !!(m_dwTipbarWndFlags & TIPBAR_VERTICAL)); } } @@ -4379,13 +4551,10 @@ BOOL CTipbarWnd::SetLangBand(BOOL bDeskBand, BOOL bFlag2) ret = FALSE; } - if (!(m_dwTipbarWndFlags & 2)) + if (!(m_dwTipbarWndFlags & TIPBAR_CHILD) && bDeskBand) { - if (bDeskBand) - { - KillTimer(7); - SetTimer(7, g_uTimerElapseSYSCOLORCHANGED); - } + KillTimer(7); + SetTimer(7, g_uTimerElapseSYSCOLORCHANGED); } return ret; @@ -4393,7 +4562,7 @@ BOOL CTipbarWnd::SetLangBand(BOOL bDeskBand, BOOL bFlag2) void CTipbarWnd::SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight) { - if (m_dwTipbarWndFlags & 0x2) + if (m_dwTipbarWndFlags & TIPBAR_CHILD) { m_nWidth = nWidth; m_nHeight = nHeight; @@ -4402,7 +4571,7 @@ void CTipbarWnd::SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight) ++m_bInCallOn; - m_dwTipbarWndFlags |= 0x400; + m_dwTipbarWndFlags |= TIPBAR_UPDATING; m_X = X; m_Y = Y; @@ -4420,7 +4589,7 @@ void CTipbarWnd::SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight) if (m_pTipbarGripper) { - if (m_dwTipbarWndFlags & 4) + if (m_dwTipbarWndFlags & TIPBAR_VERTICAL) { INT GripperWidth = GetGripperWidth(); ::SetRect(&rc, size.cx, size.cy, nWidth - m_cxDlgFrameX2 - size.cx, size.cy + GripperWidth); @@ -4437,19 +4606,27 @@ void CTipbarWnd::SetMoveRect(INT X, INT Y, INT nWidth, INT nHeight) --m_bInCallOn; } -/// @unimplemented void CTipbarWnd::SetShowText(BOOL bShow) { + if (bShow) + m_dwTipbarWndFlags |= TIPBAR_HIGHCONTRAST; + else + m_dwTipbarWndFlags &= ~TIPBAR_HIGHCONTRAST; + + if (m_pFocusThread) + OnThreadItemChange(m_pFocusThread->m_dwThreadId); + + TerminateAllThreads(FALSE); } void CTipbarWnd::SetShowTrayIcon(BOOL bShow) { - if (m_dwTipbarWndFlags & 0x20) - m_dwTipbarWndFlags &= ~0x20; + if (m_dwTipbarWndFlags & TIPBAR_TRAYICON) + m_dwTipbarWndFlags &= ~TIPBAR_TRAYICON; else - m_dwTipbarWndFlags |= 0x20; + m_dwTipbarWndFlags |= TIPBAR_TRAYICON; - if ((m_dwTipbarWndFlags & 0x20) && m_pFocusThread) + if ((m_dwTipbarWndFlags & TIPBAR_TRAYICON) && m_pFocusThread) { KillTimer(10); SetTimer(10, g_uTimerElapseMOVETOTRAY); @@ -4461,9 +4638,45 @@ void CTipbarWnd::SetShowTrayIcon(BOOL bShow) } } -/// @unimplemented void CTipbarWnd::ShowContextMenu(POINT pt, LPCRECT prc, BOOL bFlag) { + AddRef(); + + RECT rc; + if (!prc) + { + rc = { pt.x, pt.y, pt.x, pt.y }; + prc = &rc; + } + + if (m_pFocusThread) + { + CUTBContextMenu *pContextMenu = new(cicNoThrow) CUTBContextMenu(this); + if (pContextMenu) + { + if (pContextMenu->Init()) + { + m_pThread = m_pFocusThread; + StartModalInput(this, m_pFocusThread->m_dwThreadId); + + m_pModalMenu = pContextMenu; + DWORD dwCommandId = pContextMenu->ShowPopup(GetWindow(), pt, prc, bFlag); + m_pModalMenu = NULL; + + if (m_pThread) + StopModalInput(m_pThread->m_dwThreadId); + + m_pThread = NULL; + + if (dwCommandId != (DWORD)-1) + pContextMenu->SelectMenuItem(dwCommandId); + } + + delete pContextMenu; + } + } + + Release(); } void CTipbarWnd::StartBackToAlphaTimer() @@ -4472,10 +4685,17 @@ void CTipbarWnd::StartBackToAlphaTimer() ::SetTimer(m_hWnd, 3, 3 * uTime, NULL); } -/// @unimplemented BOOL CTipbarWnd::StartDoAccDefaultActionTimer(CTipbarItem *pTarget) { - return FALSE; + if (!m_pTipbarAccessible) + return FALSE; + INT IDOfItem = m_pTipbarAccessible->GetIDOfItem(pTarget); + m_nID = IDOfItem; + if (!IDOfItem || IDOfItem == -1) + return FALSE; + KillTimer(11); + SetTimer(11, g_uTimerElapseDOACCDEFAULTACTION); + return TRUE; } void CTipbarWnd::StartModalInput(ITfLangBarEventSink *pSink, DWORD dwThreadId) @@ -4504,27 +4724,87 @@ void CTipbarWnd::StopModalInput(DWORD dwThreadId) m_pLangBarMgr->SetModalInput(NULL, dwCurThreadId, 0); } -/// @unimplemented -CTipbarThread *CTipbarWnd::_CreateThread(DWORD dwThreadId) +LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds) { - return NULL; + if (g_pTipbarWnd && (g_pTipbarWnd->m_dwShowType & TF_SFT_DESKBAND)) + return 0; + + if (TF_IsInMarshaling(dwThreadId)) + return STATUS_TIMEOUT; + + DWORD dwFlags1 = 0, dwFlags2 = 0; + if (!TF_GetThreadFlags(dwThreadId, &dwFlags1, &dwFlags2, NULL) && dwFlags2) + return -1; + + return TF_CheckThreadInputIdle(dwThreadId, dwMilliseconds); +} + +CTipbarThread *CTipbarWnd::_CreateThread(DWORD dwThreadId) +{ + CTipbarThread *pTarget = _FindThread(dwThreadId); + if (pTarget) + return pTarget; + + MyWaitForInputIdle(dwThreadId, 2000); + + pTarget = new(cicNoThrow) CTipbarThread(this); + if (!pTarget) + return NULL; + + AddThreadToThreadCreatingList(pTarget); + + HRESULT hr = pTarget->Init(dwThreadId); + + RemoveThredFromThreadCreatingList(pTarget); + + if (SUCCEEDED(hr) && !m_Threads.Add(pTarget)) + { + pTarget->_UninitItemList(TRUE); + pTarget->m_pTipbarWnd = NULL; + pTarget->_Release(); + return NULL; + } + + return pTarget; } -/// @unimplemented CTipbarThread *CTipbarWnd::_FindThread(DWORD dwThreadId) { - return NULL; + if (g_bWinLogon) + return NULL; + + CTipbarThread *pTarget = NULL; + for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem) + { + CTipbarThread *pThread = m_Threads[iItem]; + if (pThread && pThread->m_dwThreadId == dwThreadId) + { + pTarget = pThread; + break; + } + } + + if (!pTarget) + return NULL; + + DWORD dwFlags1, dwFlags2, dwFlags3; + TF_GetThreadFlags(dwThreadId, &dwFlags1, &dwFlags2, &dwFlags3); + + if (!dwFlags2 || (dwFlags2 != pTarget->m_dwFlags2) || (dwFlags3 != pTarget->m_dwFlags3)) + { + OnThreadTerminateInternal(dwThreadId); + return NULL; + } + + return pTarget; } void CTipbarWnd::EnsureFocusThread() { - if (m_pFocusThread) + if (m_pFocusThread || (m_dwTipbarWndFlags & (TIPBAR_TOOLBARENDED | TIPBAR_ENSURING))) return; - if (m_dwTipbarWndFlags & 0x12000) - return; - - m_dwTipbarWndFlags |= 0x2000; + m_dwTipbarWndFlags |= TIPBAR_ENSURING; HWND hwndFore = ::GetForegroundWindow(); if (!hwndFore) @@ -4534,19 +4814,41 @@ void CTipbarWnd::EnsureFocusThread() if (dwThreadId) OnSetFocus(dwThreadId); - m_dwTipbarWndFlags &= ~0x2000; + m_dwTipbarWndFlags &= ~TIPBAR_ENSURING; } -/// @unimplemented HRESULT CTipbarWnd::SetFocusThread(CTipbarThread *pFocusThread) { - return E_NOTIMPL; + if (pFocusThread == m_pFocusThread) + return S_OK; + + DWORD dwThreadId = ::GetCurrentThreadId(); + DestroyOverScreenSizeBalloon(); + + if (m_pFocusThread) + { + m_pFocusThread->SetFocus(NULL); + ::AttachThreadInput(dwThreadId, m_pFocusThread->m_dwThreadId, FALSE); + } + + m_dwTipbarWndFlags &= ~TIPBAR_ATTACHED; + m_pFocusThread = pFocusThread; + return S_OK; } -/// @unimplemented HRESULT CTipbarWnd::AttachFocusThread() { - return E_NOTIMPL; + if (m_dwTipbarWndFlags & TIPBAR_ATTACHED) + return S_FALSE; + + if (m_pFocusThread) + { + DWORD dwThreadId = ::GetCurrentThreadId(); + ::AttachThreadInput(dwThreadId, m_pFocusThread->m_dwThreadId, TRUE); + m_dwTipbarWndFlags |= TIPBAR_ATTACHED; + } + + return S_OK; } void CTipbarWnd::RestoreLastFocus(DWORD *pdwThreadId, BOOL fPrev) @@ -4574,9 +4876,31 @@ void CTipbarWnd::CleanUpThreadPointer(CTipbarThread *pThread, BOOL bRemove) m_pUnknownThread = NULL; } -/// @unimplemented void CTipbarWnd::TerminateAllThreads(BOOL bFlag) { + const size_t cItems = m_Threads.size(); + + DWORD *pdwThreadIds = new(cicNoThrow) DWORD[cItems]; + if (!pdwThreadIds) + return; + + for (size_t iItem = 0; iItem < cItems; ++iItem) + { + pdwThreadIds[iItem] = 0; + CTipbarThread* pThread = m_Threads[iItem]; + if (pThread && (bFlag || (pThread != m_pFocusThread))) + { + pdwThreadIds[iItem] = pThread->m_dwThreadId; + } + } + + for (size_t iItem = 0; iItem < cItems; ++iItem) + { + if (pdwThreadIds[iItem]) + OnThreadTerminateInternal(pdwThreadIds[iItem]); + } + + delete[] pdwThreadIds; } STDMETHODIMP CTipbarWnd::QueryInterface(REFIID riid, void **ppvObj) @@ -4632,16 +4956,61 @@ STDMETHODIMP CTipbarWnd::OnThreadTerminate(DWORD dwThreadId) return hr; } -/// @unimplemented HRESULT CTipbarWnd::OnThreadTerminateInternal(DWORD dwThreadId) { - return E_NOTIMPL; + for (size_t iItem = 0; iItem < m_Threads.size(); ++iItem) + { + CTipbarThread *pThread = m_Threads[iItem]; + if (pThread && pThread->m_dwThreadId == dwThreadId) + { + m_Threads.Remove(iItem); + pThread->RemoveUIObjs(); + CleanUpThreadPointer(pThread, FALSE); + pThread->_UninitItemList(TRUE); + pThread->m_pTipbarWnd = NULL; + pThread->_Release(); + break; + } + } + + return S_OK; } -/// @unimplemented STDMETHODIMP CTipbarWnd::OnThreadItemChange(DWORD dwThreadId) { - return E_NOTIMPL; + if (m_dwTipbarWndFlags & TIPBAR_TOOLBARENDED) + return S_OK; + if (!(m_dwTipbarWndFlags & TIPBAR_CHILD) && (m_dwShowType & TF_SFT_DESKBAND)) + return S_OK; + + CTipbarThread *pThread = _FindThread(dwThreadId); + if (pThread) + { + if ((!m_dwUnknown23 || m_dwUnknown23 == dwThreadId) && pThread == m_pFocusThread) + { + KillOnTheadItemChangeTimer(); + m_dwChangingThreadId = dwThreadId; + KillTimer(6); + SetTimer(4, g_uTimerElapseONTHREADITEMCHANGE); + } + else + { + pThread->m_dwUnknown34 |= 0x1; + } + } + else + { + for (size_t iItem = 0; iItem < m_ThreadCreatingList.size(); ++iItem) + { + CTipbarThread *pItem = m_ThreadCreatingList[iItem]; + if (pItem && pItem->m_dwThreadId == dwThreadId) + { + pItem->m_dwUnknown34 |= 0x1; + } + } + } + + return S_OK; } STDMETHODIMP CTipbarWnd::OnModalInput(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -4700,10 +5069,28 @@ STDMETHODIMP CTipbarWnd::ShowFloating(DWORD dwFlags) return E_NOTIMPL; } -/// @unimplemented STDMETHODIMP CTipbarWnd::GetItemFloatingRect(DWORD dwThreadId, REFGUID rguid, RECT *prc) { - return E_NOTIMPL; + if (m_dwTipbarWndFlags & TIPBAR_TRAYICON) + return E_UNEXPECTED; + + if (!m_pFocusThread || (m_pFocusThread->m_dwThreadId != dwThreadId)) + return E_FAIL; + + for (size_t iItem = 0; iItem < m_pFocusThread->m_UIObjects.size(); ++iItem) + { + CTipbarItem* pItem = m_pFocusThread->m_UIObjects[iItem]; + if (pItem) + { + if ((pItem->m_dwItemFlags & 0x8) && IsEqualGUID(pItem->m_ItemInfo.guidItem, rguid)) + { + pItem->OnUnknown57(prc); + return S_OK; + } + } + } + + return E_FAIL; } /// @unimplemented @@ -4724,9 +5111,20 @@ STDMETHODIMP_(void) CTipbarWnd::GetAccLocation(LPRECT lprc) GetRect(lprc); } -/// @unimplemented STDMETHODIMP_(void) CTipbarWnd::PaintObject(HDC hDC, LPCRECT prc) { + if (m_dwTipbarWndFlags & TIPBAR_UPDATING) + { + Move(m_X, m_Y, m_CX, m_CY); + m_dwTipbarWndFlags &= ~TIPBAR_UPDATING; + } + + if (!m_pFocusThread || !m_pFocusThread->IsDirtyItem()) + { + m_pFocusThread->CallOnUpdateHandler(); + if (g_pTipbarWnd) + CUIFWindow::PaintObject(hDC, prc); + } } STDMETHODIMP_(DWORD) CTipbarWnd::GetWndStyle() @@ -4775,6 +5173,140 @@ STDMETHODIMP_(void) CTipbarWnd::OnDestroy(HWND hWnd) /// @unimplemented STDMETHODIMP_(void) CTipbarWnd::OnTimer(WPARAM wParam) { + AddRef(); + switch (wParam) + { + case 1: + KillTimer(1); + MoveToStub(FALSE); + break; + case 2: + KillTimer(2); + MoveToStub(TRUE); + break; + case 3: + KillTimer(3); + SetAlpha((BYTE)m_dwAlphaValue, TRUE); + break; + case 4: + { + LONG status = MyWaitForInputIdle(m_dwChangingThreadId, 2000); + if (status) + { + if (status != STATUS_TIMEOUT) + { + KillTimer(4); + m_dwChangingThreadId = 0; + } + } + else if (!m_pThread) + { + KillTimer(4); + DWORD dwOldThreadId = m_dwChangingThreadId; + m_dwChangingThreadId = 0; + OnThreadItemChangeInternal(dwOldThreadId); + } + break; + } + case 5: + KillTimer(5); + ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); + break; + case 6: + KillTimer(6); + if (m_pFocusThread) + { + if (m_pFocusThread->m_dwThreadId != m_dwChangingThreadId && + !m_pFocusThread->CallOnUpdateHandler()) + { + if (m_pFocusThread) + OnThreadItemChange(m_pFocusThread->m_dwThreadId); + } + } + break; + case 7: + { + DWORD dwThreadId = 0; + if (KillTimer(7)) + { + if (m_pFocusThread) + dwThreadId = m_pFocusThread->m_dwThreadId; + + TerminateAllThreads(TRUE); + UpdateVerticalFont(); + + if (dwThreadId) + OnSetFocus(dwThreadId); + + InitMetrics(); + // FIXME: CTipbarCtrlButtonHolder + + InitHighContrast(); + SetAlpha(0xFF, TRUE); + ::RedrawWindow(m_hWnd, NULL, NULL, (RDW_FRAME | RDW_UPDATENOW | RDW_INVALIDATE)); + } + break; + } + case 8: + KillTimer(8); + UpdateUI(NULL); + break; + case 9: + KillTimer(9); + //FIXME + if (m_pUnknownThread == m_pFocusThread) + Show(!!(m_dwUnknown23_5[3] & 0x80000000)); + m_pUnknownThread = NULL; + if ((m_dwUnknown23_5[3] & 0x2)) + ShowOverScreenSizeBalloon(); + break; + case 10: + KillTimer(10); + MoveToTray(); + break; + case 11: + KillTimer(11); + if (m_pTipbarAccessible) + { + if (m_nID) + { + m_pTipbarAccessible->DoDefaultActionReal(m_nID); + m_nID = 0; + } + } + break; + case 12: + KillTimer(12); + AdjustPosOnDisplayChange(); + break; + case 13: +#ifdef ENABLE_DESKBAND + if (!m_pDeskBand || !m_pDeskBand->m_dwUnknown19) + { + KillTimer(13); + if (!m_pFocusThread) + EnsureFocusThread(); + } +#endif + break; + case 14: + if (SetLangBand(TRUE, TRUE)) + { + m_dwShowType = TF_SFT_DESKBAND; + KillTimer(14); + } + break; + default: + { + if ((10000 <= wParam) && (wParam <= 10049)) + { + // FIXME: CLangBarItemList + } + break; + } + } + + Release(); } STDMETHODIMP_(void) CTipbarWnd::OnSysColorChange() @@ -4785,10 +5317,10 @@ STDMETHODIMP_(void) CTipbarWnd::OnSysColorChange() void CTipbarWnd::OnTerminateToolbar() { - m_dwTipbarWndFlags |= 0x10000; + m_dwTipbarWndFlags |= TIPBAR_TOOLBARENDED; DestroyOverScreenSizeBalloon(); TerminateAllThreads(TRUE); - if (!(m_dwTipbarWndFlags & 0x2)) + if (!(m_dwTipbarWndFlags & TIPBAR_CHILD)) SavePosition(); } @@ -4829,11 +5361,20 @@ STDMETHODIMP_(void) CTipbarWnd::OnUser(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR } } -/// @unimplemented STDMETHODIMP_(LRESULT) CTipbarWnd::OnWindowPosChanged(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - return 0; + if (m_pFocusThread) + { + for (size_t iItem = 0; iItem < m_pFocusThread->m_UIObjects.size(); ++iItem) + { + CTipbarItem *pItem = m_pFocusThread->m_UIObjects[iItem]; + if (pItem) + pItem->OnUnknown44(); + } + } + + return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } STDMETHODIMP_(LRESULT) @@ -4880,7 +5421,7 @@ CTipbarWnd::OnSettingChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) STDMETHODIMP_(LRESULT) CTipbarWnd::OnDisplayChange(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - if (!(m_dwTipbarWndFlags & 2)) + if (!(m_dwTipbarWndFlags & TIPBAR_CHILD)) { KillTimer(12); SetTimer(12, g_uTimerElapseDISPLAYCHANGE); @@ -4927,9 +5468,25 @@ STDMETHODIMP_(void) CTipbarWnd::OnThemeChanged(HWND hWnd, WPARAM wParam, LPARAM CUIFWindow::OnThemeChanged(hWnd, wParam, lParam); } -/// @unimplemented STDMETHODIMP_(void) CTipbarWnd::UpdateUI(LPCRECT prc) { + KillTimer(8); + + if (m_dwChangingThreadId || m_bInCallOn || (m_pFocusThread && m_pFocusThread->IsDirtyItem())) + { + SetTimer(8, g_uTimerElapseUPDATEUI); + return; + } + + if (m_dwTipbarWndFlags & TIPBAR_UPDATING) + { + ++m_bInCallOn; + Move(m_X, m_Y, m_CX, m_CY); + m_dwTipbarWndFlags &= ~TIPBAR_UPDATING; + --m_bInCallOn; + } + + CUIFWindow::UpdateUI(NULL); } /// @unimplemented @@ -4984,21 +5541,6 @@ HRESULT CTipbarThread::InitItemList() return E_NOTIMPL; } -LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds) -{ - if (g_pTipbarWnd && (g_pTipbarWnd->m_dwShowType & TF_SFT_DESKBAND)) - return 0; - - if (TF_IsInMarshaling(dwThreadId)) - return STATUS_TIMEOUT; - - DWORD dwFlags1 = 0, dwFlags2 = 0; - if (!TF_GetThreadFlags(dwThreadId, &dwFlags1, &dwFlags2, NULL) && dwFlags2) - return -1; - - return TF_CheckThreadInputIdle(dwThreadId, dwMilliseconds); -} - HRESULT CTipbarThread::_UninitItemList(BOOL bUnAdvise) { for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem) @@ -5175,7 +5717,7 @@ BOOL CTipbarThread::IsVertical() { if (!m_pTipbarWnd) return FALSE; - return !!(m_pTipbarWnd->m_dwTipbarWndFlags & 0x20000000); + return !!(m_pTipbarWnd->m_dwTipbarWndFlags & TIPBAR_VERTICAL); } /// @unimplemented @@ -5522,7 +6064,7 @@ BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand) g_pTipbarWnd->ShowFloating(dwStatus); if (!bParent && (dwOldStatus & TF_SFT_DESKBAND)) - g_pTipbarWnd->m_dwTipbarWndFlags |= 0x4000; + g_pTipbarWnd->m_dwTipbarWndFlags |= TIPBAR_NODESKBAND; g_hwndParent = hWnd; return TRUE; @@ -5531,13 +6073,13 @@ BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand) /*********************************************************************** * GetLibTls (MSUTB.@) * - * @unimplemented + * @implemented */ -EXTERN_C LPVOID WINAPI +EXTERN_C PLIBTHREAD WINAPI GetLibTls(VOID) { - FIXME("stub:()\n"); - return NULL; + TRACE("()\n"); + return &g_libTLS; } /*********************************************************************** diff --git a/sdk/include/reactos/cicero/cicutb.h b/sdk/include/reactos/cicero/cicutb.h index 774be036cb4..abda6e7baff 100644 --- a/sdk/include/reactos/cicero/cicutb.h +++ b/sdk/include/reactos/cicero/cicutb.h @@ -18,7 +18,13 @@ DEFINE_GUID(IID_ITfLangBarEventSink_P, 0x7A460360, 0xDA21, 0x4B09, 0xA8, DEFINE_GUID(CLSID_MSUTBDeskBand, 0x540D8A8B, 0x1C3F, 0x4E32, 0x81, 0x32, 0x53, 0x0F, 0x6A, 0x50, 0x20, 0x90); DEFINE_GUID(CATID_DeskBand, 0x00021492, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); -EXTERN_C LPVOID WINAPI GetLibTls(VOID); +typedef struct LIBTHREAD +{ + IUnknown *m_pUnknown1; + ITfDisplayAttributeMgr *m_pDisplayAttrMgr; +} LIBTHREAD, *PLIBTHREAD; + +EXTERN_C PLIBTHREAD WINAPI GetLibTls(VOID); EXTERN_C BOOL WINAPI GetPopupTipbar(HWND hWnd, BOOL fWinLogon); EXTERN_C HRESULT WINAPI SetRegisterLangBand(BOOL bRegister); EXTERN_C VOID WINAPI ClosePopupTipbar(VOID);