Ignore:
Timestamp:
Mar 27, 2001, 6:17:52 PM (24 years ago)
Author:
sandervl
Message:

cursor handling updates

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/user32/winicon.cpp

    r4825 r5385  
    1 /* $Id: winicon.cpp,v 1.19 2000-12-17 15:04:14 sandervl Exp $ */
     1/* $Id: winicon.cpp,v 1.20 2001-03-27 16:17:52 sandervl Exp $ */
    22/*
    33 * Win32 Icon Code for OS/2
     
    1414 *           1998 Turchanov Sergey
    1515 *           1998 Huw D M Davies
     16 * Theory:
     17 *
     18 * http://www.microsoft.com/win32dev/ui/icons.htm
     19 *
     20 * Cursors and icons are stored in a global heap block, with the
     21 * following layout:
     22 *
     23 * CURSORICONINFO info;
     24 * BYTE[]         ANDbits;
     25 * BYTE[]         XORbits;
     26 *
     27 * The bits structures are in the format of a device-dependent bitmap.
     28 *
     29 * This layout is very sub-optimal, as the bitmap bits are stored in
     30 * the X client instead of in the server like other bitmaps; however,
     31 * some programs (notably Paint Brush) expect to be able to manipulate
     32 * the bits directly :-(
     33 *
     34 * FIXME: what are we going to do with animation and color (bpp > 1) cursors ?!
     35 *
     36 **************************************************************************************************
     37 *
     38 * TODO: Scaling of system cursors (store them as resources in user32 instead of using PM pointers)
     39 * TODO: We use the hColorBmp member of the CURSORICONINFO structure to store the PM cursor handle
     40 *       Might mess up PaintBrush (see above)
    1641 *
    1742 * Project Odin Software License can be found in LICENSE.TXT
     
    2752#include <win\virtual.h>
    2853#include "initterm.h"
     54#include "oslibres.h"
     55#include "oslibwin.h"
    2956
    3057#define DBG_LOCALLOG    DBG_winicon
    3158#include "dbglocal.h"
    3259
    33 static WORD ICON_HOTSPOT = 0x4242;
     60
     61/**********************************************************************
     62 * ICONCACHE for cursors/icons loaded with LR_SHARED.
     63 *
     64 * FIXME: This should not be allocated on the system heap, but on a
     65 *        subsystem-global heap (i.e. one for all Win16 processes,
     66 *        and one for each Win32 process).
     67 */
     68typedef struct tagICONCACHE
     69{
     70    struct tagICONCACHE *next;
     71
     72    HMODULE              hModule;
     73    HRSRC                hRsrc;
     74    HRSRC                hGroupRsrc;
     75    HANDLE               handle;
     76    INT                  count;
     77} ICONCACHE;
     78
     79static ICONCACHE *IconAnchor = NULL;
     80static CRITICAL_SECTION IconCrst = CRITICAL_SECTION_INIT;
     81static WORD    ICON_HOTSPOT  = 0x4242;
     82static HCURSOR hActiveCursor = 0;
     83
    3484
    3585static HGLOBAL CURSORICON_CreateFromResource( HINSTANCE hInstance, DWORD dwResGroupId, HGLOBAL hObj, LPBYTE bits,
     
    4393                                                CURSORICONDIR **res, LPBYTE **ptr);
    4494
     95static INT CURSORICON_DelSharedIcon( HANDLE handle );
     96static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle );
     97static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc );
     98static ICONCACHE* CURSORICON_FindCache(HANDLE handle);
     99
    45100/***********************************************************************
    46101 *           CreateIcon    (USER32.75)
     
    63118    info.hInstance = hInstance;
    64119    info.dwResGroupId = -1;
     120    info.hColorBmp = 0;
    65121    return CreateCursorIconIndirect(0, &info, lpANDbits, lpXORbits);
    66122}
     
    126182        info->hInstance     = -1;
    127183        info->dwResGroupId  = -1;
     184        info->hColorBmp     = 0;
     185
    128186        /* Transfer the bitmap bits to the CURSORICONINFO structure */
    129187        GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) );
     
    213271                memcpy(&pInfo->bmiColors[0], (char *)(ciconinfo + 1) + coloroff, colorsize);
    214272        }
    215         //else TODO: color masks (curerntly unused in CreateDIBitmap)
     273        //else TODO: color masks (currently unused in CreateDIBitmap)
    216274
    217275        iconinfo->hbmColor = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT, src, pInfo, DIB_RGB_COLORS);
     
    235293    return TRUE;
    236294}
     295//******************************************************************************
     296//******************************************************************************
     297HCURSOR WIN32API CreateCursor(HINSTANCE hInst, int xHotSpot, int yHotSpot, int nWidth, int nHeight,
     298                              const VOID *lpANDbits, const VOID *lpXORbits)
     299{
     300    CURSORICONINFO info;
     301
     302    dprintf(("CreateCursor %dx%d spot=%d,%d xor=%p and=%p\n",
     303             nWidth, nHeight, xHotSpot, yHotSpot, lpXORbits, lpANDbits));
     304
     305    info.ptHotSpot.x   = xHotSpot;
     306    info.ptHotSpot.y   = yHotSpot;
     307    info.nWidth        = nWidth;
     308    info.nHeight       = nHeight;
     309    info.nWidthBytes   = 0;
     310    info.bPlanes       = 1;
     311    info.bBitsPerPixel = 1;
     312    info.hInstance     = hInst;
     313    info.dwResGroupId  = -1;
     314    info.hColorBmp     = 0;
     315
     316    return CreateCursorIconIndirect( 0, &info, lpANDbits, lpXORbits );
     317}
     318//******************************************************************************
     319//******************************************************************************
     320BOOL WIN32API DestroyCursor( HCURSOR hCursor)
     321{
     322    dprintf(("USER32:  DestroyCursor %x", hCursor));
     323    return CURSORICON_Destroy( hCursor, CID_WIN32 );
     324}
     325//******************************************************************************
     326//******************************************************************************
     327HCURSOR WIN32API GetCursor(void)
     328{
     329    dprintf2(("USER32: GetCursor"));
     330    return hActiveCursor;
     331}
     332//******************************************************************************
     333//******************************************************************************
     334HCURSOR WIN32API SetCursor( HCURSOR hCursor)
     335{
     336  HCURSOR hOldCursor;
     337
     338    dprintf(("USER32: SetCursor %x (prev %x)", hCursor, hActiveCursor));
     339    if (hCursor == hActiveCursor) return hActiveCursor;  /* No change */
     340
     341    hOldCursor = hActiveCursor;
     342    hActiveCursor = hCursor;
     343
     344    CURSORICONINFO *iconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hCursor);
     345    if (!iconinfo) {
     346        dprintf(("ERROR: Invalid cursor!"));
     347        return 0;
     348    }
     349    if(!iconinfo->hColorBmp) {
     350        dprintf(("SetCursor: invalid os/2 pointer handle!!"));
     351    }
     352
     353    if(OSLibWinSetPointer(iconinfo->hColorBmp) == FALSE) {
     354        dprintf(("OSLibWinSetPointer %x returned FALSE!!", iconinfo->hColorBmp));
     355    }
     356    GlobalUnlock(hCursor);
     357
     358    return hOldCursor;
     359}
     360//******************************************************************************
     361//******************************************************************************
     362BOOL WIN32API GetCursorPos( PPOINT lpPoint)
     363{
     364    dprintf2(("USER32: GetCursorPos %x", lpPoint));
     365
     366    if (!lpPoint) return FALSE;
     367
     368    if (OSLibWinQueryPointerPos(lpPoint)) //POINT == POINTL
     369    {
     370        mapScreenPoint((OSLIBPOINT*)lpPoint);
     371        return TRUE;
     372    }
     373    else return FALSE;
     374}
     375//******************************************************************************
     376//******************************************************************************
     377BOOL WIN32API SetCursorPos( int X, int Y)
     378{
     379    dprintf(("USER32: SetCursorPos %d %d", X,Y));
     380    return OSLibWinSetPointerPos(X, mapScreenY(Y));
     381}
     382//******************************************************************************
     383//******************************************************************************
     384/*****************************************************************************
     385 * Name      : BOOL WIN32API SetSystemCursor
     386 * Purpose   : The SetSystemCursor function replaces the contents of the system
     387 *             cursor specified by dwCursorId with the contents of the cursor
     388 *             specified by hCursor, and then destroys hCursor. This function
     389 *             lets an application customize the system cursors.
     390 * Parameters: HCURSOR  hCursor    set specified system cursor to this cursor's
     391 *                                 contents, then destroy this
     392 *             DWORD    dwCursorID system cursor specified by its identifier
     393 * Variables :
     394 * Result    : If the function succeeds, the return value is TRUE.
     395 *             If the function fails, the return value is FALSE. To get extended
     396 *             error information, call GetLastError.
     397 * Remark    :
     398 * Status    : UNTESTED STUB
     399 *
     400 * Author    : Patrick Haller [Thu, 1998/02/26 11:55]
     401 *****************************************************************************/
     402BOOL WIN32API SetSystemCursor(HCURSOR hCursor, DWORD dwCursorId)
     403{
     404  dprintf(("USER32:SetSystemCursor (%08xh,%08x) not supported.\n",
     405         hCursor,
     406         dwCursorId));
     407
     408  return DestroyCursor(hCursor);
     409}
     410//******************************************************************************
     411//******************************************************************************
     412int WIN32API ShowCursor( BOOL bShow)
     413{
     414    dprintf2(("USER32: ShowCursor %d", bShow));
     415    return O32_ShowCursor(bShow);
     416}
     417//******************************************************************************
     418//******************************************************************************
    237419/***********************************************************************
    238  *           CreateCursorIconIndirect    (USER.408)
     420 *           CreateCursorIconIndirect
    239421 */
    240422HGLOBAL WIN32API CreateCursorIconIndirect( HINSTANCE hInstance,
     
    276458    LPBYTE bits;
    277459
     460#ifdef __WIN32OS2__
     461    //TODO: Can system cursors be loaded by name??? (#xxx)
     462    if (fCursor && hInstance == NULL && !HIWORD(name))
     463    {
     464        HCURSOR hCursor = OSLibWinQuerySysPointer((ULONG)name, width, height);
     465        if(hCursor)
     466        {
     467            /* If shared icon, check whether it was already loaded */
     468            if ((loadflags & LR_SHARED)
     469                && (h = CURSORICON_FindSharedIcon( -1, hCursor ) ) != 0 )
     470            {
     471                dprintf(("Found icon/cursor in cache; returned old handle %x", h));
     472                return h;
     473            }
     474
     475            HANDLE hObj = GlobalAlloc( GMEM_MOVEABLE,  sizeof(CURSORICONINFO));
     476            if (!hObj)
     477            {
     478                DebugInt3();
     479                return 0;
     480            }
     481            CURSORICONINFO *info;
     482
     483            info = (CURSORICONINFO *)GlobalLock( hObj );
     484            info->ptHotSpot.x   = 0;
     485            info->ptHotSpot.y   = 0;
     486            info->nWidth        = width;
     487            info->nHeight       = height;
     488            info->nWidthBytes   = width*height/8;
     489            info->bPlanes       = 1;
     490            info->bBitsPerPixel = 1;
     491            info->hColorBmp     = hCursor;
     492            info->hInstance     = -1;
     493            info->dwResGroupId  = -1;
     494
     495            if (loadflags & LR_SHARED )
     496                CURSORICON_AddSharedIcon( -1, hCursor, -1, hObj );
     497
     498            GlobalUnlock( hObj );
     499
     500            return hObj;
     501        }
     502    }
     503#endif
    278504    if ( loadflags & LR_LOADFROMFILE )    /* Load from file */
    279505    {
    280506        LPBYTE *ptr;
     507
    281508        if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr))
    282509            return 0;
     
    288515        h = CURSORICON_CreateFromResource( 0, -1, 0, bits, dirEntry->dwBytesInRes,
    289516                                           !fCursor, 0x00030000, width, height, loadflags);
     517
    290518        HeapFree( GetProcessHeap(), 0, dir );
    291519        HeapFree( GetProcessHeap(), 0, ptr );
     
    339567        }
    340568
     569        /* If shared icon, check whether it was already loaded */
     570        if ((loadflags & LR_SHARED)
     571            && (h = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
     572        {
     573            dprintf(("Found icon/cursor in cache; returned old handle %x", h));
     574            return h;
     575        }
     576
    341577        if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
    342578        bits = (LPBYTE)LockResource( handle );
     
    344580                                           !fCursor, 0x00030000, width, height, loadflags);
    345581        FreeResource( handle );
     582
     583        /* If shared icon, add to icon cache */
     584
     585        if ( h && (loadflags & LR_SHARED) )
     586            CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, h );
    346587
    347588    }
     
    706947    if( !hXorBits || !hAndBits )
    707948    {
    708         dprintf(("\tunable to create an icon bitmap.\n"));
     949        dprintf(("\tunable to create an icon bitmap."));
    709950        return 0;
    710951    }
     
    739980        info->bPlanes       = bmpXor.bmPlanes;
    740981        info->bBitsPerPixel = bmpXor.bmBitsPixel;
    741         info->hColorBmp     = hXorBits;
    742982        info->hInstance     = hInstance;
    743983        info->dwResGroupId  = dwResGroupId;
     984        info->hColorBmp     = 0;
    744985
    745986        /* Transfer the bitmap bits to the CURSORICONINFO structure */
     
    7691010            GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd);
    7701011        }
     1012        if(!bIcon) {
     1013            info->hColorBmp = OSLibWinCreateCursor(info, (char *)(info + 1), (LPBITMAP_W)&bmpAnd, (char *)(info + 1) + sizeAnd, (LPBITMAP_W)&bmpXor);
     1014            dprintf(("Create cursor %x with OS/2 pointer handle %x", hObj, info->hColorBmp));
     1015        }
    7711016        GlobalUnlock( hObj );
    7721017    }
     
    7891034    WORD retv;
    7901035
    791 #if 0
    7921036    /* Check whether destroying active cursor */
    7931037
    7941038    if ( hActiveCursor == handle )
    7951039    {
    796         ERR_(cursor)("Destroying active cursor!\n" );
     1040        dprintf(("WARNING: Destroying active cursor!" ));
    7971041        SetCursor( 0 );
    7981042    }
     1043
    7991044    /* Try shared cursor/icon first */
    800 
    8011045    if ( !(flags & CID_NONSHARED) )
    8021046    {
     
    8081052        /* FIXME: OEM cursors/icons should be recognized */
    8091053    }
     1054    /* Now assume non-shared cursor/icon */
     1055
     1056#ifdef __WIN32OS2__
     1057    CURSORICONINFO *iconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)handle);
     1058    if (!iconinfo) {
     1059        dprintf(("ERROR: Invalid cursor!"));
     1060        return 0;
     1061    }
     1062
     1063    if(iconinfo->hColorBmp) {
     1064        OSLibWinDestroyPointer(iconinfo->hColorBmp);
     1065    }
     1066    GlobalUnlock(handle);
    8101067#endif
    811     /* Now assume non-shared cursor/icon */
    8121068
    8131069    retv = GlobalFree( handle );
     
    8741130        || nFlags & LR_MONOCHROME)
    8751131    {
     1132        ICONCACHE* pIconCache = CURSORICON_FindCache(Handle);
     1133
     1134        /* Not Found in Cache, then do a straight copy
     1135        */
     1136        if(pIconCache == NULL)
     1137        {
     1138#ifdef __WIN32OS2__
     1139            hNew = CURSORICON_Copy(Handle);
     1140#else
     1141            hNew = CURSORICON_Copy(0, Handle);
     1142#endif
     1143            if(nFlags & LR_COPYFROMRESOURCE)
     1144            {
     1145                dprintf(("WARNING: LR_COPYFROMRESOURCE: Failed to load from cache\n"));
     1146            }
     1147        }
     1148        else
     1149        {
    8761150            int iTargetCY = iDesiredCY, iTargetCX = iDesiredCX;
    8771151            LPBYTE pBits;
     
    9681242                                                  bIsIcon, 0x00030000, iTargetCX, iTargetCY, nFlags);
    9691243            FreeResource(hMem);
     1244        }
    9701245    }
    9711246    else
     
    10051280    iColorDiff = 0xFFFFFFFF;
    10061281    for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
    1007         {
     1282    {
    10081283        iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
    10091284        iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
     
    10151290            iTotalDiff = iXDiff + iYDiff;
    10161291        }
    1017         }
     1292    }
    10181293
    10191294    /* Find Best Colors for Best Fit */
    10201295    for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
    1021         {
     1296    {
    10221297        if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
    10231298            abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
     
    10291304#endif
    10301305            if(iColorDiff > iTempColorDiff)
    1031         {
    1032             bestEntry = entry;
     1306            {
     1307                bestEntry = entry;
    10331308                iColorDiff = iTempColorDiff;
    1034         }
     1309            }
    10351310        }
    10361311    }
     
    10491324 */
    10501325static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
    1051                                                   int width, int height, int color)
     1326                                                      int width, int height, int color)
    10521327{
    10531328    int i, maxwidth, maxheight;
     
    11401415//******************************************************************************
    11411416//******************************************************************************
     1417
     1418//ICON cache implementation (Wine code)
     1419
     1420/**********************************************************************
     1421 *      CURSORICON_FindSharedIcon
     1422 */
     1423static HANDLE CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
     1424{
     1425    HANDLE handle = 0;
     1426    ICONCACHE *ptr;
     1427
     1428    EnterCriticalSection( &IconCrst );
     1429
     1430    for ( ptr = IconAnchor; ptr; ptr = ptr->next )
     1431        if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
     1432        {
     1433            ptr->count++;
     1434            handle = ptr->handle;
     1435            break;
     1436        }
     1437
     1438    LeaveCriticalSection( &IconCrst );
     1439
     1440    return handle;
     1441}
     1442
     1443/*************************************************************************
     1444 * CURSORICON_FindCache
     1445 *
     1446 * Given a handle, find the corresponding cache element
     1447 *
     1448 * PARAMS
     1449 *      Handle     [I] handle to an Image
     1450 *
     1451 * RETURNS
     1452 *     Success: The cache entry
     1453 *     Failure: NULL
     1454 *
     1455 */
     1456static ICONCACHE* CURSORICON_FindCache(HANDLE handle)
     1457{
     1458    ICONCACHE *ptr;
     1459    ICONCACHE *pRet=NULL;
     1460    BOOL IsFound = FALSE;
     1461    int count;
     1462
     1463    EnterCriticalSection( &IconCrst );
     1464
     1465    for (count = 0, ptr = IconAnchor; ptr != NULL && !IsFound; ptr = ptr->next, count++ )
     1466    {
     1467        if ( handle == ptr->handle )
     1468        {
     1469            IsFound = TRUE;
     1470            pRet = ptr;
     1471        }
     1472    }
     1473
     1474    LeaveCriticalSection( &IconCrst );
     1475
     1476    return pRet;
     1477}
     1478
     1479/**********************************************************************
     1480 *      CURSORICON_AddSharedIcon
     1481 */
     1482static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HANDLE handle )
     1483{
     1484    ICONCACHE *ptr = (ICONCACHE *)HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
     1485    if ( !ptr ) return;
     1486
     1487    ptr->hModule = hModule;
     1488    ptr->hRsrc   = hRsrc;
     1489    ptr->handle  = handle;
     1490    ptr->hGroupRsrc = hGroupRsrc;
     1491    ptr->count   = 1;
     1492
     1493    EnterCriticalSection( &IconCrst );
     1494    ptr->next    = IconAnchor;
     1495    IconAnchor   = ptr;
     1496    LeaveCriticalSection( &IconCrst );
     1497}
     1498
     1499/**********************************************************************
     1500 *      CURSORICON_DelSharedIcon
     1501 */
     1502static INT CURSORICON_DelSharedIcon( HANDLE handle )
     1503{
     1504    INT count = -1;
     1505    ICONCACHE *ptr;
     1506
     1507    EnterCriticalSection( &IconCrst );
     1508
     1509    for ( ptr = IconAnchor; ptr; ptr = ptr->next )
     1510        if ( ptr->handle == handle )
     1511        {
     1512            if ( ptr->count > 0 ) ptr->count--;
     1513            count = ptr->count;
     1514            break;
     1515        }
     1516
     1517    LeaveCriticalSection( &IconCrst );
     1518
     1519    return count;
     1520}
     1521
     1522/**********************************************************************
     1523 *      CURSORICON_FreeModuleIcons
     1524 */
     1525void CURSORICON_FreeModuleIcons( HMODULE hModule )
     1526{
     1527    ICONCACHE **ptr = &IconAnchor;
     1528
     1529    EnterCriticalSection( &IconCrst );
     1530
     1531    while ( *ptr )
     1532    {
     1533        if ( (*ptr)->hModule == hModule )
     1534        {
     1535            ICONCACHE *freePtr = *ptr;
     1536            *ptr = freePtr->next;
     1537
     1538#ifdef __WIN32OS2__
     1539            CURSORICON_Destroy(freePtr->handle, CID_NONSHARED);
     1540#else
     1541            GlobalFree( freePtr->handle );
     1542#endif
     1543            HeapFree( GetProcessHeap(), 0, freePtr );
     1544            continue;
     1545        }
     1546        ptr = &(*ptr)->next;
     1547    }
     1548
     1549    LeaveCriticalSection( &IconCrst );
     1550}
     1551
Note: See TracChangeset for help on using the changeset viewer.