/* * OS/2 System Tray support. * A better implementaiton using the xsystray XCenter/eCenter widget API. * * Author: Dmitriy Kuminov */ #define INCL_PM #define INCL_DOS #define INCL_DOSERRORS #include // Odin32 OS/2 api wrappers #include #include // declare function pointers for dynamic linking to xsystray DLL #define XSTAPI_FPTRS_STATIC #include "xsystray.h" #include "systray_os2.h" #include "dbglog.h" #define WM_XST_MYNOTIFY (WM_USER + 1000) static ULONG WM_XST_CREATED = 0; static ULONG WM_TASKBARCREATED_W = 0; static HWND hwndProxy = NULLHANDLE; static ULONG hwndProxyRefs = 0; static PFNWP OldProxyWndProc = NULL; static MRESULT EXPENTRY ProxyWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { switch (msg) { case WM_XST_MYNOTIFY: { USHORT usIconID = SHORT1FROMMP(mp1); USHORT usNotifyCode = SHORT2FROMMP(mp1); SystrayItem *ptrayItem = SYSTRAY_FindItem(usIconID); if (!ptrayItem) return (MRESULT)FALSE; switch (usNotifyCode) { case XST_IN_MOUSE: { PXSTMOUSEMSG pmmsg = (PXSTMOUSEMSG)mp2; ULONG winMsg = 0; switch (pmmsg->ulMouseMsg) { case WM_BUTTON1DBLCLK: winMsg = WM_LBUTTONDBLCLK_W; break; case WM_BUTTON2DBLCLK: winMsg = WM_RBUTTONDBLCLK_W; break; case WM_BUTTON3DBLCLK: winMsg = WM_MBUTTONDBLCLK_W; break; case WM_BUTTON1UP: winMsg = WM_LBUTTONUP_W; break; case WM_BUTTON2UP: winMsg = WM_RBUTTONUP_W; break; case WM_BUTTON3UP: winMsg = WM_MBUTTONUP_W; break; case WM_BUTTON1DOWN: winMsg = WM_LBUTTONDOWN_W; break; case WM_BUTTON2DOWN: winMsg = WM_RBUTTONDOWN_W; break; case WM_BUTTON3DOWN: winMsg = WM_MBUTTONDOWN_W; break; default: break; } if (winMsg) { PostMessageA(ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.uCallbackMessage, (WPARAM)ptrayItem->notifyIcon.uID, (LPARAM)winMsg); return (MRESULT)TRUE; } break; } case XST_IN_CONTEXT: { PostMessageA(ptrayItem->notifyIcon.hWnd, ptrayItem->notifyIcon.uCallbackMessage, (WPARAM)ptrayItem->notifyIcon.uID, (LPARAM)WM_CONTEXTMENU_W); return (MRESULT)TRUE; } default: break; } return (MRESULT)FALSE; } default: { if (msg == WM_XST_CREATED) { // xCenter was restarted, no icons are shown; remove all items // and broadcast TaskbarCreated to let applications recreate them SYSTRAY_PruneAllItems(); dprintf(("SHELL32: SYSTRAY: Broadcasting \"TaskbarCreated\" (%x)", WM_TASKBARCREATED_W)); PostMessageA(HWND_BROADCAST_W, WM_TASKBARCREATED_W, (WPARAM)0, (LPARAM)0); return (MRESULT)TRUE; } break; } } return WinDefWindowProc(hWnd, msg, mp1, mp2); } static BOOL SYSTRAY_Ex_ItemInit(SystrayItem *ptrayItem) { if (hwndProxyRefs == 0) { if (!WinRegisterClass(NULLHANDLE, "OdinXSysTrayProxy", ProxyWndProc, 0, 0)) { dprintf(("SHELL32: SYSTRAY: WinRegisterClass() failed with %x", WinGetLastError(0))); return FALSE; } hwndProxy = WinCreateWindow(HWND_DESKTOP, "OdinXSysTrayProxy", NULL, 0, 0, 0, 0, 0, NULLHANDLE, HWND_BOTTOM, 0, NULL, NULL); if (hwndProxy == NULLHANDLE) { dprintf(("SHELL32: SYSTRAY: WinCreateWindow() failed with %x", WinGetLastError(0))); return FALSE; } } ++ hwndProxyRefs; return TRUE; } static void SYSTRAY_Ex_ItemTerm(SystrayItem *ptrayItem) { xstRemoveSysTrayIcon(hwndProxy, ptrayItem->uIdx); if (-- hwndProxyRefs == 0) { WinDestroyWindow(hwndProxy); hwndProxy = NULLHANDLE; } } static void SYSTRAY_Ex_ItemUpdate(SystrayItem *ptrayItem, ULONG uFlags) { if (uFlags == 0 || (uFlags & (NIF_ICON | NIF_TIP) == NIF_ICON | NIF_TIP)) { // uFlags = 0 means it's the first time so add the icon. The other case // is true when a bunch of the parameters is changed at once so use // xstAdd... too to save a few IPC calls. xstAddSysTrayIcon(hwndProxy, ptrayItem->uIdx, ptrayItem->notifyIcon.hIcon, ptrayItem->notifyIcon.szTip, WM_XST_MYNOTIFY, XST_IN_MOUSE | XST_IN_CONTEXT); return; } if (uFlags & NIF_ICON) { xstReplaceSysTrayIcon(hwndProxy, ptrayItem->uIdx, ptrayItem->notifyIcon.hIcon); } if (uFlags & NIF_TIP) { xstSetSysTrayIconToolTip(hwndProxy, ptrayItem->uIdx, ptrayItem->notifyIcon.szTip); } } BOOL SYSTRAY_Ex_Init(void) { static BOOL tried = FALSE; if (!tried) { char err[CCHMAXPATH]; HMODULE hmod; tried = TRUE; // link to the xsystray DLL at runtime if (DosLoadModule(err, sizeof(err), "XSYSTRAY", &hmod) != NO_ERROR) return FALSE; #define R(f) if (DosQueryProcAddr(hmod, 0, #f, (PFN*)&f) != NO_ERROR) return FALSE R(xstQuerySysTrayVersion); R(xstAddSysTrayIcon); R(xstReplaceSysTrayIcon); R(xstRemoveSysTrayIcon); R(xstSetSysTrayIconToolTip); R(xstQuerySysTrayIconRect); R(xstGetSysTrayCreatedMsgId); R(xstGetSysTrayMaxTextLen); #undef R } // check if xsystray is there if (!xstQuerySysTrayVersion(NULL, NULL, NULL)) return FALSE; // initialize some constants WM_XST_CREATED = xstGetSysTrayCreatedMsgId(); WM_TASKBARCREATED_W = RegisterWindowMessageA("TaskbarCreated"); SYSTRAY_ItemInit = SYSTRAY_Ex_ItemInit; SYSTRAY_ItemTerm = SYSTRAY_Ex_ItemTerm; SYSTRAY_ItemUpdate = SYSTRAY_Ex_ItemUpdate; return TRUE; }