Ignore:
Timestamp:
Oct 27, 2009, 2:36:55 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: xsystray: Further coding (established communication channel between the clients and the server, some bug fixes).

Location:
trunk/src/3rdparty/os2/xsystray
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/3rdparty/os2/xsystray/xsystray.c

    r255 r256  
    4040#include <stdio.h>
    4141#include <string.h>
     42#include <stdlib.h>
     43#include <stdarg.h>
    4244
    4345// generic headers
     
    7375#pragma hdrstop                     // VAC++ keeps crashing otherwise
    7476
     77// primitive debug logging to a file
     78#if 1
     79static void __LOG_WORKER(const char *fmt, ...)
     80{
     81    static FILE *f = NULL;
     82    if (f == NULL)
     83    {
     84        f = fopen("c:\\xsystray.dbg", "a");
     85        setbuf(f, NULL);
     86    }
     87    if (f != NULL)
     88    {
     89        va_list vl;
     90        va_start(vl, fmt);
     91        vfprintf(f, fmt, vl);
     92        va_end(vl);
     93    }
     94}
     95#define LOG(m)  do { __LOG_WORKER m; } while(0)
     96#define LOGF(m) do { __LOG_WORKER("%s: ", __FUNCTION__); __LOG_WORKER m; } while(0)
     97#else
     98#define LOG(m)  do {} while (0)
     99#define LOGF(m) do {} while (0)
     100#endif
     101
    75102/* ******************************************************************
    76103 *
     
    79106 ********************************************************************/
    80107
    81 // None currently.
     108/*
     109 *@@ ICONDATA:
     110 *      Per-icon data.
     111 */
     112
     113typedef struct _ICONDATA
     114{
     115    HWND        hwnd;
     116                // associated window
     117    ULONG       ulId;
     118                // icon ID
     119    HPOINTER    hIcon;
     120                // icon handle
     121    ULONG       ulMsgId;
     122                // message ID for notifications
     123    PSZ         pszToolTip;
     124                // icon tooltip (NULL if none)
     125
     126} ICONDATA, *PICONDATA;
     127
     128/*
     129 *@@ SYSTRAYDATA:
     130 *      Global system tray data.
     131 */
     132
     133typedef struct
     134{
     135    PICONDATA   pIcons;
     136                // array of icons currently shown in the system tray
     137                // (left to right)
     138    size_t      cIcons;
     139                // number of icons in the pIcons array
     140    size_t      cIconsMax;
     141                // maximum number of icons pIcons can fit
     142
     143} SYSTRAYDATA, *PSYSTRAYDATA;
     144
     145ULONG QWL_USER_SERVER_DATA = 0;
    82146
    83147/* ******************************************************************
     
    196260 */
    197261
     262static
    198263BOOL WgtControl(PXCENTERWIDGET pWidget,
    199264                MPARAM mp1,
     
    240305 */
    241306
     307static
    242308VOID WgtPaint(HWND hwnd,
    243309              PXCENTERWIDGET pWidget)
     
    274340/*
    275341 *@@ fnwpXSysTray:
    276  *      window procedure for the winlist widget class.
     342 *      window procedure for the Extended system tray widget class.
    277343 *
    278344 *      There are a few rules which widget window procs
     
    311377
    312378        case WM_CREATE:
     379        {
     380            PSYSTRAYDATA pSysTrayData = NULL;
     381
     382            mrc = (MPARAM)TRUE; // being pessimistic gives more compact code
     383
    313384            WinSetWindowPtr(hwnd, QWL_USER, mp1);
    314385            if (    (!(pWidget = (PXCENTERWIDGET)mp1))
     
    316387               )
    317388                // shouldn't happen... stop window creation!!
    318                 mrc = (MPARAM)TRUE;
     389                break;
     390
     391            pSysTrayData = malloc(sizeof(*pSysTrayData));
     392            if (pSysTrayData == NULL)
     393                break;
     394
     395            // initialize the SYSTRAYDATA structure
     396            pSysTrayData->cIconsMax = 4;
     397            pSysTrayData->pIcons = malloc(sizeof(*pSysTrayData->pIcons) *
     398                                          pSysTrayData->cIconsMax);
     399            if (pSysTrayData->pIcons == NULL)
     400            {
     401                free(pSysTrayData);
     402                break;
     403            }
     404            pSysTrayData->cIcons = 0;
     405            pWidget->pUser = pSysTrayData;
     406
     407            // create the "server" window (note that we pass the XCENTERWIDGET
     408            // pointer on to it)
     409            HWND hwndServer =
     410                WinCreateWindow(HWND_DESKTOP, WNDCLASS_WIDGET_XSYSTRAY_SERVER,
     411                                NULL, WS_MINIMIZED,
     412                                0, 0, 0, 0,
     413                                HWND_DESKTOP, HWND_BOTTOM,
     414                                0, mp1, NULL);
     415            if (hwndServer == NULLHANDLE)
     416                break;
     417
     418            mrc = FALSE; // confirm success
     419        }
    319420        break;
    320421
     
    353454
    354455        case WM_DESTROY:
    355             // If we had any user data allocated in WM_CREATE
    356             // or elsewhere, we'd clean this up here.
     456        {
     457            // free all system tray data
     458            PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser;
     459            size_t i;
     460            for (i = 0; i < pSysTrayData->cIcons; ++i)
     461            {
     462                if (pSysTrayData->pIcons[i].pszToolTip)
     463                    free(pSysTrayData->pIcons[i].pszToolTip);
     464            }
     465            free(pSysTrayData->pIcons);
     466            free(pSysTrayData);
     467            pWidget->pUser = NULL;
    357468            // We _MUST_ pass this on, or the default widget proc
    358469            // cannot clean up.
    359470            mrc = pWidget->pfnwpDefWidgetProc(hwnd, msg, mp1, mp2);
     471        }
    360472        break;
    361473
     
    363475            mrc = pWidget->pfnwpDefWidgetProc(hwnd, msg, mp1, mp2);
    364476
     477    } // end switch(msg)
     478
     479    return mrc;
     480}
     481
     482/*
     483 *@@ WgtXSysTrayControl:
     484 *      implementation for WM_XST_CONTROL in fnwpXSysTrayServer.
     485 *
     486 *      Serves as an entry point for all client-side requests to the Extended
     487 *      system tray.
     488 *
     489 *      Note that this message is being sent from another process which is
     490 *      awaiting for an answer, so it must return as far as possible (by
     491 *      rescheduling any potentially long term operation for another cycle).
     492 */
     493
     494static
     495BOOL WgtXSysTrayControl(HWND hwnd, PXCENTERWIDGET pWidget,
     496                        PSYSTRAYCTLDATA pCtlData)
     497{
     498    BOOL brc = FALSE;
     499
     500    switch (pCtlData->ulCommand)
     501    {
     502        case SYSTRAYCMD_GETVERSION:
     503        {
     504            LOGF(("SYSTRAYCMD_GETVERSION\n"));
     505
     506            pCtlData->bAcknowledged = TRUE;
     507            pCtlData->u.version.ulMajor = XSYSTRAY_VERSION_MAJOR;
     508            pCtlData->u.version.ulMajor = XSYSTRAY_VERSION_MINOR;
     509            pCtlData->u.version.ulRevision = XSYSTRAY_VERSION_REVISION;
     510            brc = TRUE;
     511        }
     512        break;
     513
     514        default:
     515            break;
     516    }
     517
     518    return brc;
     519}
     520
     521/*
     522 *@@ fnwpXSysTrayServer:
     523 *      window procedure for the Extended system tray server window class.
     524 *
     525 *      A separate "server" class is necessary because we need a CS_FRAME
     526 *      top-level window for DDE (which we need to support to be backward
     527 *      compatible with the System tray wdget from the SysTray/WPS package) and
     528 *      also to make ourselves discoverable for the client-side implementation
     529 *      of our new extended API (which queries the class of each top-level
     530 *      window to find the system tray server).
     531 */
     532
     533static
     534MRESULT EXPENTRY fnwpXSysTrayServer(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     535{
     536    MRESULT mrc = 0;
     537    // get widget data from QWL_USER_SERVER_DATA (stored there by WM_CREATE)
     538    PXCENTERWIDGET pWidget =
     539        (PXCENTERWIDGET)WinQueryWindowPtr(hwnd, QWL_USER_SERVER_DATA);
     540                    // this ptr is valid after WM_CREATE
     541
     542    switch (msg)
     543    {
     544        case WM_CREATE:
     545            WinSetWindowPtr(hwnd, QWL_USER_SERVER_DATA, mp1);
     546        break;
     547
     548        /*
     549         * WM_XST_CONTROL:
     550         *      This is the message sent to us by the clinet-side implementation
     551         *      of the API to request some function. mp1 points to a
     552         *      SYSTRAYCTLDATA structure.
     553         */
     554
     555        case WM_XST_CONTROL:
     556            mrc = (MRESULT)WgtXSysTrayControl(hwnd, pWidget,
     557                                              (PSYSTRAYCTLDATA)mp1);
     558        break;
     559
     560        default:
     561            mrc = WinDefWindowProc(hwnd, msg, mp1, mp2);
    365562    } // end switch(msg)
    366563
     
    428625                             PSZ pszErrorMsg)       // if 0 is returned, 500 bytes of error msg
    429626{
    430     ULONG   ulrc = 0;
    431 
    432     // register our PM window class
    433     if (!WinRegisterClass(hab,
    434                           WNDCLASS_WIDGET_XSYSTRAY,
    435                           fnwpXSysTray,
    436                           CS_PARENTCLIP | CS_SIZEREDRAW | CS_SYNCPAINT,
    437                           sizeof(PVOID))
     627    ULONG       ulrc = 0;
     628    CLASSINFO   ClassInfo;
     629
     630    LOGF(("hmodPlugin %x\n", hmodPlugin));
     631
     632    do
     633    {
     634        // register our PM window class
     635        if (!WinRegisterClass(hab,
     636                             WNDCLASS_WIDGET_XSYSTRAY,
     637                             fnwpXSysTray,
     638                             CS_PARENTCLIP | CS_SIZEREDRAW | CS_SYNCPAINT,
     639                             sizeof(PVOID))
    438640                                // extra memory to reserve for QWL_USER
    439                          )
    440         // error registering class: report error then
    441         strcpy(pszErrorMsg, "WinRegisterClass failed.");
    442     else
    443     {
     641            )
     642        {
     643            LOG(("WinRegisterClass(%s) failed with %lX",
     644                 WNDCLASS_WIDGET_XSYSTRAY, WinGetLastError(hab)));
     645            break;
     646        }
     647
     648        // get the window data size for the WC_FRAME class (any window class
     649        // that specifies CS_FRAME must have at least this number, otherise
     650        // WinRegisterClass returns 0x1003
     651        if (!WinQueryClassInfo(hab, (PSZ)WC_FRAME, &ClassInfo))
     652            break;
     653        QWL_USER_SERVER_DATA = ClassInfo.cbWindowData;
     654
     655        if (!WinRegisterClass(hab,
     656                              WNDCLASS_WIDGET_XSYSTRAY_SERVER,
     657                              fnwpXSysTrayServer,
     658                              CS_FRAME,
     659                              QWL_USER_SERVER_DATA + sizeof(PVOID))
     660                                // extra memory to reserve for QWL_USER
     661            )
     662        {
     663            // error registering class: report error then
     664            snprintf(pszErrorMsg, 500, "WinRegisterClass(%s) failed with %lX",
     665                     WNDCLASS_WIDGET_XSYSTRAY_SERVER, WinGetLastError(hab));
     666            break;
     667        }
     668
    444669        // no error:
    445670        // return widget classes array
     
    449674        ulrc = sizeof(G_WidgetClasses) / sizeof(G_WidgetClasses[0]);
    450675    }
     676    while (0);
     677
     678    LOGF(("pszErrorMsg %s\n", pszErrorMsg));
     679    LOGF(("ulrc %d\n", ulrc));
    451680
    452681    return ulrc;
     
    489718{
    490719    *pulMajor = 0;
    491     *pulMinor = 1;
    492     *pulRevision = 0;
    493 }
    494 
     720    *pulMinor = 9;
     721    *pulRevision = 9;
     722}
     723
  • trunk/src/3rdparty/os2/xsystray/xsystray.h

    r255 r256  
    1616#ifndef XSYSTRAY_HEADER_INCLUDED
    1717#define XSYSTRAY_HEADER_INCLUDED
     18
     19#define XSYSTRAY_VERSION_MAJOR 0
     20#define XSYSTRAY_VERSION_MINOR 1
     21#define XSYSTRAY_VERSION_REVISION 0
    1822
    1923#define WNDCLASS_WIDGET_XSYSTRAY_SERVER "XWPCenterExtendedSysTrayServer"
     
    3539} SYSTRAYCMD;
    3640
    37 // NOTE: the idea is to fit SYSTRAYMSGDATA into a page (4K) since this is the
     41// NOTE: the idea is to fit SYSTRAYCTLDATA into a page (4K) since this is the
    3842// smallest piece DosAllocSharedMem() allocates anyway.
    3943typedef struct
     
    7377            // set to true by the recipient if it processes the message
    7478
    75 } SYSTRAYMSGDATA, *PSYSTRAYMSGDATA;
     79} SYSTRAYCTLDATA, *PSYSTRAYCTLDATA;
    7680
    7781#endif // XSYSTRAY_HEADER_INCLUDED
  • trunk/src/3rdparty/os2/xsystray/xsystray_api.c

    r255 r256  
    2727
    2828static HWND G_hwndSysTray = NULLHANDLE;
    29 static int G_itlsSysTrayMsgData = -1;
     29static int G_itlsSysTrayCtlData = -1;
    3030
    3131static HWND FindSysTrayWindow()
     
    4646}
    4747
    48 static BOOL SendSysTrayCtlMsg(PSYSTRAYMSGDATA pData)
     48static BOOL SendSysTrayCtlMsg(PSYSTRAYCTLDATA pData)
    4949{
    5050    APIRET arc;
     
    7070            arc = ERROR_INVALID_HANDLE;
    7171            if (WinQueryWindowProcess(G_hwndSysTray, &pid, &tid))
    72                 arc = DosGiveSharedMem(__libc_TLSGet(G_itlsSysTrayMsgData),
     72                arc = DosGiveSharedMem(__libc_TLSGet(G_itlsSysTrayCtlData),
    7373                                       pid, PAG_READ | PAG_WRITE);
    7474            if (arc != NO_ERROR)
     
    8080        mrc = WinSendMsg(G_hwndSysTray, WM_XST_CONTROL, pData, NULL);
    8181        if (mrc == (MRESULT)TRUE && pData->bAcknowledged)
    82             break;
     82            return TRUE;
    8383
    8484        // if we failed to send the message, it may mean that XCenter was restarted
     
    9898}
    9999
    100 static PSYSTRAYMSGDATA GetSysTrayMsgDataPtr()
     100static PSYSTRAYCTLDATA GetSysTrayCtlDataPtr()
    101101{
    102102    APIRET arc;
    103103
    104104    // allocate a thread local storage entry if not done so
    105     if (G_itlsSysTrayMsgData == -1)
     105    if (G_itlsSysTrayCtlData == -1)
    106106    {
    107107        // @todo does XWorkplace have its own TLS? Not? Use
     
    109109        // to the lack of space in that area)
    110110        int itls = __libc_TLSAlloc();
    111         if (!__atomic_cmpxchg32(&G_itlsSysTrayMsgData, itls, -1))
     111        if (!__atomic_cmpxchg32(&G_itlsSysTrayCtlData, itls, -1))
    112112        {
    113113            // another thread has already got an entry, discard our try
     
    116116        }
    117117
    118         if (G_itlsSysTrayMsgData == -1)
     118        if (G_itlsSysTrayCtlData == -1)
    119119            return NULL;
    120120    }
    121121
    122     // allocate a SYSTRAYMSGDATA struct for this thread if not done so
    123     PSYSTRAYMSGDATA pData = __libc_TLSGet(G_itlsSysTrayMsgData);
    124     if (!pData)
    125     {
    126         arc = DosAllocSharedMem((PVOID)&pData, NULL, sizeof(SYSTRAYMSGDATA),
     122    // allocate a SYSTRAYCTLDATA struct for this thread if not done so
     123    PSYSTRAYCTLDATA pData = __libc_TLSGet(G_itlsSysTrayCtlData);
     124    if (!pData)
     125    {
     126        arc = DosAllocSharedMem((PVOID)&pData, NULL, sizeof(SYSTRAYCTLDATA),
    127127                                PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE);
    128128        if (arc != NO_ERROR)
    129129            return NULL;
    130130
    131         __libc_TLSSet(G_itlsSysTrayMsgData, pData);
     131        __libc_TLSSet(G_itlsSysTrayCtlData, pData);
    132132
    133133        // note that we don't ever free the allocated block since our API doesn't
     
    159159                            PULONG pulRevision) // out: revision number
    160160{
    161     PSYSTRAYMSGDATA pData = GetSysTrayMsgDataPtr();
     161    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
    162162    if (!pData)
    163163        return FALSE;
     
    166166    pData->hwndSender = NULLHANDLE;
    167167
    168     BOOL rc = SendSysTrayCtlMsg(pData);
    169     if (rc)
     168    BOOL brc = SendSysTrayCtlMsg(pData);
     169    if (brc)
    170170    {
    171171        if (pulMajor)
     
    177177    }
    178178
    179     return rc;
     179    return brc;
    180180}
    181181
     
    215215                       ULONG ulFlags)   // in: flags (not currently used, must be 0)
    216216{
    217     PSYSTRAYMSGDATA pData = GetSysTrayMsgDataPtr();
     217    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
    218218    if (!pData)
    219219        return FALSE;
     
    240240                          ULONG ulId)   // in: icon ID to remove
    241241{
    242     PSYSTRAYMSGDATA pData = GetSysTrayMsgDataPtr();
     242    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
    243243    if (!pData)
    244244        return FALSE;
     
    272272                              PSZ pszText)  // in: tooltip text
    273273{
    274     PSYSTRAYMSGDATA pData = GetSysTrayMsgDataPtr();
     274    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
    275275    if (!pData)
    276276        return FALSE;
     
    361361ULONG xstGetSysTrayMaxTextLen()
    362362{
    363     return sizeof(((PSYSTRAYMSGDATA)0)->u.tooltip.szText);
    364 }
    365 
     363    return sizeof(((PSYSTRAYCTLDATA)0)->u.tooltip.szText);
     364}
     365
  • trunk/src/3rdparty/os2/xsystray/xsystray_api.h

    r255 r256  
    2121#endif
    2222
    23 // notification code constants for WM_XST_NOTIFY, refer to xstAddSysTrayIcon()
     23// notification code constants for the notification messages sent by the system
     24// tray (refer to xstAddSysTrayIcon() for details)
    2425#define XST_IN_MOUSE    0x0001
    2526
Note: See TracChangeset for help on using the changeset viewer.