// Tray.cpp

#include "pch.h"
#include "tray.h"

#define LEFT_MENU	(0)
#define RIGHT_MENU	(1)

/////////////////////////////////////////////////////////////////////////////

CTrayIcon::CTrayIcon(HWND hWnd, HICON hIcon, LPCTSTR pszText, UINT uID) :
	m_iDefaultCmd(-1)
{
    TRACEPROC("CTrayIcon::CTrayIcon", 2)

    TRACEENTER(("(hwnd=%x,hIcon=%x,Text=%s,ID=%x)\n",
                hWnd, hIcon, pszText, uID));

    m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
    m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
    m_msgTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));

    memset(&m_nid, 0, sizeof(m_nid));

    m_nid.cbSize = sizeof(NOTIFYICONDATA);
    m_nid.hWnd = hWnd;
    m_nid.uID = uID;

    m_nid.uFlags = NIF_MESSAGE;
    m_nid.uCallbackMessage = RegisterWindowMessage(TEXT("{D0061156-D460-4230-AF87-9E7658AB987D}"));

    if (hIcon)
    {
	m_nid.uFlags |= NIF_ICON;
	m_nid.hIcon = hIcon;
    }

    if (pszText)
    {
	m_nid.uFlags |= NIF_TIP;
	lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));
    }

    if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
    {
        TABSRVERR(("CTrayIcon::CTrayIcon: Shell_NotifyIcon failed (err=%d)\n",
                   GetLastError()));
    }

    TRACEEXIT(("!\n"));
    return;
}

/////////////////////////////////////////////////////////////////////////////

void CTrayIcon::Delete()
{
    TRACEPROC("CTrayIcon::Delete", 2)

    TRACEENTER(("()\n"));

    if (m_nid.uFlags & NIF_ICON)
    {
	m_nid.uFlags = NIF_ICON;
	if (!Shell_NotifyIcon(NIM_DELETE, &m_nid))
            SetLastError(::GetLastError());

        m_nid.uFlags = 0;

	// Cleanup the icon...
	if (m_nid.hIcon)
	{
            DestroyIcon(m_nid.hIcon);
            m_nid.hIcon = 0;
	}

	// ...and the menus
	HMENU hmLeft = m_hMenu[LEFT_MENU];
	if (m_hMenu[LEFT_MENU])
	{
            DestroyMenu(m_hMenu[LEFT_MENU]);
            m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
	}

	// watch for right & left menus being the same
	if (m_hMenu[RIGHT_MENU] && m_hMenu[RIGHT_MENU] != hmLeft)
	{
            DestroyMenu(m_hMenu[RIGHT_MENU]);
            m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
	}
    }

    TRACEEXIT(("!\n"));
    return;
}

#if 0
/////////////////////////////////////////////////////////////////////////////

HICON CTrayIcon::SetIcon(HICON hIcon)
{
    TRACEPROC("CTrayIcon::SetIcon", 2)
    HICON hOldIcon = m_nid.hIcon;

    TRACEENTER(("(hIcon=%x)\n", hIcon));

    if (hIcon)
    {
        m_nid.hIcon = hIcon;
        m_nid.uFlags |= NIF_ICON;

        if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
            SetLastError(::GetLastError());
    }
    else
    {
        Delete();
    }

    TRACEEXIT(("=%x\n", hOldIcon));
    return hOldIcon;
}

/////////////////////////////////////////////////////////////////////////////

void CTrayIcon::SetText(LPCTSTR pszText)
{
    TRACEPROC("CTrayIcon::SetText", 2)

    TRACEENTER(("(Text=%s)\n", pszText));

    if (pszText)
    {
        m_nid.uFlags |= NIF_TIP;
        lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));

        if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
            SetLastError(::GetLastError());
    }

    TRACEEXIT(("!\n"));
    return;
}
#endif

/////////////////////////////////////////////////////////////////////////////

void CTrayIcon::BalloonToolTip(
    LPCTSTR pszTitle,
    LPCTSTR pszText,
    UINT uTimeout,
    DWORD dwFlags)
{
    TRACEPROC("CTrayIcon::BalloonToolTip", 2)
    UINT uFlags = m_nid.uFlags;

    TRACEENTER(("(Title=%s,Text=%s,Timeout=%d,Flags=%x)\n",
                pszTitle, pszText, uTimeout, dwFlags));

    m_nid.uFlags = NIF_INFO;
    m_nid.uTimeout = uTimeout;
    lstrcpyn(m_nid.szInfo, pszText, ARRAYSIZE(m_nid.szInfo));
    lstrcpyn(m_nid.szInfoTitle, pszTitle, ARRAYSIZE(m_nid.szInfoTitle));
    m_nid.dwInfoFlags = dwFlags;

    if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
    {
        TABSRVERR(("CTrayIcon::BalloonToolTip: Shell_NotifyIcon failed (err=%d)\n",
                   GetLastError()));
    }

    m_nid.uFlags = uFlags;

    TRACEEXIT(("!\n"));
    return;
}

/////////////////////////////////////////////////////////////////////////////

#if 0
static VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    TRACEPROC("TimerProc", 5)

    TRACEENTER(("(hwnd=%x,Msg=%s,EventId=%x,Time=%x)\n",
                hWnd, LookupName(uMsg, WMMsgNames), idEvent, dwTime));

    KillTimer(hWnd, idEvent);
    CTrayIcon* This = reinterpret_cast<CTrayIcon*>(idEvent);

    if (This->m_hSubMenu[LEFT_MENU])
        This->DoMenu(This->m_hSubMenu[LEFT_MENU]);

    TRACEEXIT(("!\n"));
    return;
}
#endif

/////////////////////////////////////////////////////////////////////////////

BOOL CTrayIcon::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
						LRESULT& lResult)
{
    TRACEPROC("CTrayIcon::WndProc", 5)
    BOOL rc = FALSE;

    TRACEENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
                hWnd, LookupName(uMsg, WMMsgNames), wParam, lParam));

    if (uMsg == m_msgTaskbarCreated)
    {
       	lResult = OnTaskbarCreated();
       	rc = TRUE;
    }
    else if (uMsg == m_nid.uCallbackMessage)
    {
    	lResult = OnNotify(lParam);
       	rc = TRUE;
    }
    else if (uMsg == WM_DESTROY)
    {
       	// Our controlling window is being destroyed.  Clean up if we
       	// haven't already, then pass on the WM_DESTROY
       	Delete();
    }

    TRACEEXIT(("=%x\n", rc));
    return rc;
}

/////////////////////////////////////////////////////////////////////////////

LRESULT CTrayIcon::OnNotify(LPARAM lParam)
{
    TRACEPROC("CTrayIcon::OnNotify", 2)
    TRACEENTER(("(lParam=%x)\n", lParam));

    switch (lParam)
    {
        case WM_LBUTTONUP:
	    if (m_iDefaultCmd != -1)
	       	PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
            break;

#if 0
        case WM_LBUTTONDOWN:
	    SetTimer(m_nid.hWnd, (UINT_PTR)this, GetDoubleClickTime(), TimerProc);
	    break;

	case WM_LBUTTONDBLCLK:
	    KillTimer(m_nid.hWnd, (UINT_PTR)this);

	    if (m_iDefaultCmd != -1)
	       	PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
	    break;
#endif

        case WM_RBUTTONUP:
	    if (m_hSubMenu[RIGHT_MENU])
	       	DoMenu(m_hSubMenu[RIGHT_MENU]);
            break;
    }

    TRACEEXIT(("=0\n"));
    return 0;
}

/////////////////////////////////////////////////////////////////////////////

LRESULT CTrayIcon::OnTaskbarCreated()
{
    TRACEPROC("CTrayIcon::OnTaskbarCreated", 2)
    TRACEENTER(("()\n"));

    if (m_nid.hWnd && m_nid.hIcon && (m_nid.uFlags & NIF_ICON))
    {
       	if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
        {
            TABSRVERR(("CTrayIcon::OnTaskbarCreated: Shell_NotifyIcon failed (err=%d)\n",
                       GetLastError()));
        }
    }

    TRACEEXIT(("=0\n"));
    return 0;
}

/////////////////////////////////////////////////////////////////////////////

HMENU CTrayIcon::SetSubMenu(BOOL fLeftMenu, HMENU hMenu, int nPos)
{
    TRACEPROC("CTrayIcon::SetSubMenu", 2)
    int idx = (fLeftMenu) ? LEFT_MENU : RIGHT_MENU;
    HMENU hOldMenu = m_hMenu[idx];

    TRACEENTER(("(fLeftMenu=%d,hMenu=%x,Pos=%d)\n", fLeftMenu, hMenu, nPos));

    m_hMenu[idx] = m_hSubMenu[idx] = hMenu;

    if (hMenu && nPos >= 0)
    {
       	m_hSubMenu[idx] = GetSubMenu(hMenu, nPos);  //NO TYPO
    }

    if (idx == LEFT_MENU)
    {
       	m_iDefaultCmd = -1;

       	if (hMenu && m_hSubMenu[idx])
            m_iDefaultCmd = GetMenuDefaultItem(m_hSubMenu[idx], FALSE, 0);
    }

    TRACEEXIT(("=%x\n", hOldMenu));
    return hOldMenu;
}

/////////////////////////////////////////////////////////////////////////////

void CTrayIcon::DoMenu(HMENU hMenu)
{
    TRACEPROC("CTrayIcon::DoMenu", 2)
    POINT pt;
    UINT iCmd;
    TCHAR tszMenuText[128];

    TRACEENTER(("(hMenu=%x)\n", hMenu));
    GetCursorPos(&pt);

    SetForegroundWindow(m_nid.hWnd);		// necessary?

    LoadString(ghMod,
               gdwfTabSrv & TSF_SUPERTIP_OPENED?
                    IDS_HIDE_SUPERTIP: IDS_SHOW_SUPERTIP,
               tszMenuText,
               ARRAYSIZE(tszMenuText));
    ModifyMenu(hMenu,
               IDM_OPEN,
               MF_BYCOMMAND | MF_STRING,
               IDM_OPEN,
               tszMenuText);

    LoadString(ghMod,
               gdwfTabSrv & TSF_PORTRAIT_MODE?
                    IDS_SCREEN_LANDSCAPE: IDS_SCREEN_PORTRAIT,
               tszMenuText,
               ARRAYSIZE(tszMenuText));
    ModifyMenu(hMenu,
               IDM_TOGGLE_ROTATION,
               MF_BYCOMMAND | MF_STRING,
               IDM_TOGGLE_ROTATION,
               tszMenuText);

    iCmd = TrackPopupMenu(hMenu, /* TPM_RETURNCMD | */ TPM_NONOTIFY | TPM_RIGHTBUTTON,
	                  pt.x, pt.y, 0, m_nid.hWnd, NULL);

    PostMessage(m_nid.hWnd, WM_NULL, 0, 0); // MS doucmented work-around for taskbar menu
					    // problem with TrackPopupMenu - still needed?

    //PostMessage(m_nid.hWnd, WM_COMMAND, iCmd, 0);

    TRACEEXIT(("!\n"));
    return;
}