//#define ENABLE_DESKBAND
+typedef struct LANGBARITEMSTATE
+{
+ CLSID m_clsid;
+ DWORD m_dwDemoteLevel;
+ UINT_PTR m_nTimerID;
+ UINT m_uTimeOut;
+ BOOL m_bStartedIntentionally;
+ BOOL m_bDisableDemoting;
+
+ BOOL IsShown()
+ {
+ return m_dwDemoteLevel < 2;
+ }
+} LANGBARITEMSTATE, *PLANGBARITEMSTATE;
+
HINSTANCE g_hInst = NULL;
UINT g_wmTaskbarCreated = 0;
UINT g_uACP = CP_ACP;
/***********************************************************************/
+class CLangBarItemList : public CicArray<LANGBARITEMSTATE>
+{
+public:
+ BOOL IsStartedIntentionally(REFCLSID rclsid);
+
+ LANGBARITEMSTATE *AddItem(REFCLSID rclsid);
+ void Clear();
+ BOOL SetDemoteLevel(REFCLSID rclsid, DWORD dwDemoteLevel);
+
+ LANGBARITEMSTATE *FindItem(REFCLSID rclsid);
+ LANGBARITEMSTATE *GetItemStateFromTimerId(UINT_PTR nTimerID);
+
+ void Load();
+ void SaveItem(CicRegKey *pRegKey, const LANGBARITEMSTATE *pState);
+
+ void StartDemotingTimer(REFCLSID rclsid, BOOL bIntentional);
+ UINT_PTR FindDemotingTimerId();
+};
+
+/***********************************************************************/
+
class CTrayIconWnd
{
protected:
void AddUIObjs();
void RemoveUIObjs();
+ CTipbarItem *GetItem(REFCLSID rclsid);
void GetTextSize(BSTR bstr, LPSIZE pSize);
void LocateItems();
void MyMoveWnd(LONG xDelta, LONG yDelta);
DWORD m_dwSinkCookie;
CModalMenu *m_pModalMenu;
CTipbarThread *m_pThread;
- CicArray<GUID*> m_TipbarGUIDArray;
+ CLangBarItemList m_LangBarItemList;
DWORD m_dwUnknown20;
CUIFWndFrame *m_pWndFrame;
CTipbarGripper *m_pTipbarGripper;
friend class CTipbarThread;
friend class CTipbarItem;
friend class CLBarInatItem;
+ friend class CMainIconItem;
friend VOID WINAPI ClosePopupTipbar(VOID);
friend BOOL GetTipbarInternal(HWND hWnd, DWORD dwFlags, CDeskBand *pDeskBand);
friend LONG MyWaitForInputIdle(DWORD dwThreadId, DWORD dwMilliseconds);
m_pTipbarWnd = pTipbarWnd;
}
-/// @unimplemented
+/// @implemented
BOOL CUTBContextMenu::Init()
{
m_pTipbarThread = m_pTipbarWnd->m_pFocusThread;
* CMainIconItem
*/
+/// @implemented
CMainIconItem::CMainIconItem(CTrayIconWnd *pWnd)
: CButtonIconItem(pWnd, 1)
{
}
+/// @implemented
BOOL CMainIconItem::Init(HWND hWnd)
{
return CTrayIconItem::_Init(hWnd, WM_USER, 0, GUID_LBI_TRAYMAIN);
}
-/// @unimplemented
+/// @implemented
STDMETHODIMP_(BOOL) CMainIconItem::OnDelayMsg(UINT uMsg)
{
if (!CButtonIconItem::OnDelayMsg(uMsg))
if (uMsg == WM_LBUTTONDBLCLK)
{
- //FIXME
- //if (g_pTipbarWnd->m_dwUnknown20)
- // g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
+ if (g_pTipbarWnd->m_dwUnknown20)
+ g_pTipbarWnd->m_pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
}
else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN)
{
- //FIXME
- //g_pTipbarWnd->ShowContextMenu(m_ptCursor, &m_rcClient, uMsg == WM_RBUTTONDOWN);
+ g_pTipbarWnd->ShowContextMenu(m_ptCursor, &m_rcMenu, uMsg == WM_RBUTTONDOWN);
}
return TRUE;
}
return m_hNotifyWnd;
}
-/// @unimplemented
+/// @implemented
BOOL CTrayIconWnd::OnIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- //FIXME
- //if (g_pTipbarWnd)
- // g_pTipbarWnd->AttachFocusThread();
+ if (g_pTipbarWnd)
+ g_pTipbarWnd->AttachFocusThread();
for (size_t iItem = 0; iItem < m_Items.size(); ++iItem)
{
- auto pItem = m_Items[iItem];
+ auto *pItem = m_Items[iItem];
if (pItem)
{
if (uMsg == pItem->m_uCallbackMessage)
return CUIFGripper::OnSetCursor(uMsg, x, y);
}
+/***********************************************************************
+ * CLangBarItemList
+ */
+
+BOOL CLangBarItemList::IsStartedIntentionally(REFCLSID rclsid)
+{
+ auto *pItem = FindItem(rclsid);
+ if (!pItem)
+ return FALSE;
+ return pItem->m_bStartedIntentionally;
+}
+
+LANGBARITEMSTATE *CLangBarItemList::AddItem(REFCLSID rclsid)
+{
+ auto *pItem = FindItem(rclsid);
+ if (pItem)
+ return pItem;
+
+ pItem = Append(1);
+ if (!pItem)
+ return NULL;
+
+ ZeroMemory(pItem, sizeof(*pItem));
+ pItem->m_clsid = rclsid;
+ pItem->m_dwDemoteLevel = 0;
+ return pItem;
+}
+
+void CLangBarItemList::Clear()
+{
+ clear();
+
+ CicRegKey regKey;
+ LSTATUS error;
+ error = regKey.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar", KEY_ALL_ACCESS);
+ if (error == ERROR_SUCCESS)
+ regKey.RecurseDeleteKey(L"ItemState");
+}
+
+BOOL CLangBarItemList::SetDemoteLevel(REFCLSID rclsid, DWORD dwDemoteLevel)
+{
+ auto *pItem = AddItem(rclsid);
+ if (!pItem)
+ return TRUE;
+
+ pItem->m_dwDemoteLevel = dwDemoteLevel;
+ if (!pItem->IsShown())
+ {
+ if (pItem->m_nTimerID)
+ {
+ if (g_pTipbarWnd)
+ g_pTipbarWnd->KillTimer(pItem->m_nTimerID);
+ pItem->m_nTimerID = 0;
+ pItem->m_uTimeOut = 0;
+ }
+ pItem->m_bDisableDemoting = FALSE;
+ }
+
+ SaveItem(0, pItem);
+ return TRUE;
+}
+
+LANGBARITEMSTATE *CLangBarItemList::FindItem(REFCLSID rclsid)
+{
+ for (size_t iItem = 0; iItem < size(); ++iItem)
+ {
+ auto& item = (*this)[iItem];
+ if (IsEqualCLSID(item.m_clsid, rclsid))
+ return &item;
+ }
+ return NULL;
+}
+
+LANGBARITEMSTATE *CLangBarItemList::GetItemStateFromTimerId(UINT_PTR nTimerID)
+{
+ for (size_t iItem = 0; iItem < size(); ++iItem)
+ {
+ auto& item = (*this)[iItem];
+ if (item.m_nTimerID == nTimerID)
+ return &item;
+ }
+ return NULL;
+}
+
+void CLangBarItemList::Load()
+{
+ CicRegKey regKey;
+ LSTATUS error;
+ error = regKey.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar\\ItemState");
+ if (error != ERROR_SUCCESS)
+ return;
+
+ WCHAR szKeyName[MAX_PATH];
+ for (DWORD dwIndex = 0; ; ++dwIndex)
+ {
+ error = ::RegEnumKeyW(regKey, dwIndex, szKeyName, _countof(szKeyName));
+ if (error != ERROR_SUCCESS)
+ break;
+
+ CLSID clsid;
+ if (::CLSIDFromString(szKeyName, &clsid) != S_OK)
+ continue;
+
+ CicRegKey regKey2;
+ error = regKey2.Open(regKey, szKeyName);
+ if (error != ERROR_SUCCESS)
+ continue;
+
+ auto *pItem = AddItem(clsid);
+ if (!pItem)
+ continue;
+
+ DWORD Data = 0;
+ regKey2.QueryDword(L"DemoteLevel", &Data);
+ pItem->m_dwDemoteLevel = Data;
+ regKey2.QueryDword(L"DisableDemoting", &Data);
+ pItem->m_bDisableDemoting = !!Data;
+ }
+}
+
+void CLangBarItemList::SaveItem(CicRegKey *pRegKey, const LANGBARITEMSTATE *pState)
+{
+ LSTATUS error;
+ CicRegKey regKey;
+
+ if (!pRegKey)
+ {
+ error = regKey.Create(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF\\LangBar\\ItemState");
+ if (error != ERROR_SUCCESS)
+ return;
+
+ pRegKey = ®Key;
+ }
+
+ WCHAR szSubKey[MAX_PATH];
+ ::StringFromGUID2(pState->m_clsid, szSubKey, _countof(szSubKey));
+
+ if (pState->m_dwDemoteLevel || pState->m_bDisableDemoting)
+ {
+ CicRegKey regKey2;
+ error = regKey2.Create(*pRegKey, szSubKey);
+ if (error == ERROR_SUCCESS)
+ {
+ DWORD dwDemoteLevel = pState->m_dwDemoteLevel;
+ if (dwDemoteLevel)
+ regKey2.SetDword(L"DemoteLevel", dwDemoteLevel);
+ else
+ regKey2.DeleteValue(L"DemoteLevel");
+
+ regKey2.SetDword(L"DisableDemoting", pState->m_bDisableDemoting);
+ }
+ }
+ else
+ {
+ pRegKey->RecurseDeleteKey(szSubKey);
+ }
+}
+
+void CLangBarItemList::StartDemotingTimer(REFCLSID rclsid, BOOL bIntentional)
+{
+ if (!g_bIntelliSense)
+ return;
+
+ auto *pItem = AddItem(rclsid);
+ if (!pItem || pItem->m_bDisableDemoting)
+ return;
+
+ if (pItem->m_nTimerID)
+ {
+ if (!bIntentional)
+ return;
+
+ if (g_pTipbarWnd)
+ g_pTipbarWnd->KillTimer(pItem->m_nTimerID);
+
+ pItem->m_nTimerID = 0;
+ }
+
+ pItem->m_bStartedIntentionally |= bIntentional;
+
+ UINT uTimeOut = (bIntentional ? g_uTimeOutIntentional : g_uTimeOutNonIntentional);
+ pItem->m_uTimeOut += uTimeOut;
+
+ if (pItem->m_uTimeOut < g_uTimeOutMax)
+ {
+ UINT_PTR uDemotingTimerId = FindDemotingTimerId();
+ pItem->m_nTimerID = uDemotingTimerId;
+ if (uDemotingTimerId)
+ {
+ if (g_pTipbarWnd)
+ g_pTipbarWnd->SetTimer(uDemotingTimerId, uTimeOut);
+ }
+ }
+ else
+ {
+ pItem->m_bDisableDemoting = TRUE;
+ }
+}
+
+UINT_PTR CLangBarItemList::FindDemotingTimerId()
+{
+ UINT_PTR nTimerID = 10000;
+
+ if (empty())
+ return nTimerID;
+
+ for (;;)
+ {
+ size_t iItem = 0;
+
+ while ((*this)[iItem].m_nTimerID != nTimerID)
+ {
+ ++iItem;
+ if (iItem >= size())
+ return nTimerID;
+ }
+
+ ++nTimerID;
+ if (nTimerID >= 10050)
+ return 0;
+ }
+}
+
/***********************************************************************
* CTipbarWnd
*/
void CTipbarWnd::ClearLBItemList()
{
- m_TipbarGUIDArray.clear();
+ m_LangBarItemList.Clear();
if (m_pFocusThread)
OnThreadItemChange(m_pFocusThread->m_dwThreadId);
}
break;
default:
{
- if ((10000 <= wParam) && (wParam <= 10049))
+ if (10000 <= wParam && wParam < 10050)
{
- // FIXME: CLangBarItemList
+ auto *pItem = m_LangBarItemList.GetItemStateFromTimerId(wParam);
+ if (pItem)
+ {
+ auto& clsid = pItem->m_clsid;
+ m_LangBarItemList.SetDemoteLevel(pItem->m_clsid, 2);
+ if (m_pFocusThread)
+ {
+ auto *pThreadItem = m_pFocusThread->GetItem(clsid);
+ if (pThreadItem)
+ pThreadItem->AddRemoveMeToUI(FALSE);
+ }
+ }
}
break;
}
RemoveAllSeparators();
}
+CTipbarItem *CTipbarThread::GetItem(REFCLSID rclsid)
+{
+ for (size_t iItem = 0; iItem < m_UIObjects.size(); ++iItem)
+ {
+ auto *pItem = m_UIObjects[iItem];
+ if (pItem && IsEqualCLSID(pItem->m_ItemInfo.guidItem, rclsid))
+ return pItem;
+ }
+ return NULL;
+}
+
void CTipbarThread::GetTextSize(BSTR bstr, LPSIZE pSize)
{
HWND hWnd = *m_pTipbarWnd->GetWindow();