- Timestamp:
- Nov 2, 2009, 3:10:29 AM (16 years ago)
- Location:
- trunk/src/3rdparty/os2/xsystray
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/3rdparty/os2/xsystray/xsystray.c
r270 r273 111 111 */ 112 112 113 typedef struct _ICONDATA113 typedef struct 114 114 { 115 115 HWND hwnd; 116 116 // associated window 117 U LONG ulId;117 USHORT usId; 118 118 // icon ID 119 119 HPOINTER hIcon; … … 123 123 PSZ pszToolTip; 124 124 // icon tooltip (NULL if none) 125 BOOL bMemoryPoolGiven; 126 // TRUE if SYSTRAYDATA::pvMemoryPool is already given to 127 // the process hwnd belongs to 125 128 126 129 } ICONDATA, *PICONDATA; … … 147 150 size_t cIconsMax; 148 151 // maximum number of icons pIcons can fit 152 PVOID pvMemoryPool; 153 // memory pool for NOTIFYDATA structures 149 154 150 155 } SYSTRAYDATA, *PSYSTRAYDATA; … … 154 159 // space for the newly added icon 155 160 156 static ULONG QWL_USER_SERVER_DATA = 0; 157 // offset to the PXCENTERWIDGET pointer in the widget data array 161 #define SERVER_MEMORYPOOL_SIZE 65536 162 // taking NOTIFYDATA size into account (<=32 B), this is enough for at 163 // least 2048 simultaneous notification messages, which (even taking 164 // slowly responsing clients into account) sounds sane since in most 165 // cases the structure is freed once it reaches the target event queue 166 // and before a message created as a copy of it is sent to the target 167 // window procedure 158 168 159 169 #define TID_CHECKALIVE 1 … … 161 171 #define TID_CHECKALIVE_TIMEOUT 2000 // ms 162 172 // how often to perform alive checks 173 174 static ULONG WM_XST_CREATED = 0; 175 // identity of the WM_XST_CREATED message taken from the atom table 176 static ULONG WM_XST_NOTIFY = 0; 177 // identity of the WM_XST_NOTIFY message taken from the atom table 178 179 static ULONG QWL_USER_SERVER_DATA = 0; 180 // offset to the PXCENTERWIDGET pointer in the widget data array 163 181 164 182 static … … 299 317 { 300 318 pData->hwnd = NULLHANDLE; 301 pData->u lId = 0;319 pData->usId = 0; 302 320 if (pData->hIcon != NULLHANDLE) 303 321 { … … 323 341 PICONDATA FindIconData(PSYSTRAYDATA pSysTrayData, 324 342 HWND hwnd, // in: associated window handle 325 U LONG ulId,// in: icon ID343 USHORT usId, // in: icon ID 326 344 size_t *pIdx) // out: index of the icon in the icon array 327 345 // (optional, may be NULL) … … 331 349 { 332 350 if (pSysTrayData->pIcons[i].hwnd == hwnd && 333 pSysTrayData->pIcons[i].u lId == ulId)351 pSysTrayData->pIcons[i].usId == usId) 334 352 { 335 353 if (pIdx) … … 342 360 *pIdx = i; 343 361 return NULL; 362 } 363 364 /* 365 *@@ AllocNotifyDataPtr: 366 * Allocates a SYSTRAYCTLDATA struct in the pool of shared memory on belalf 367 * of the client window identified by pIconData->hwnd. 368 * 369 * If there is no free space in the pool, it returns NULL. On success, 370 * fills in msg and mp1 fields of the returned structure using the 371 * information provided in pIconData. 372 * 373 * Note that the allocated structure is supposed to be freed using 374 * FreeNotifyDataPtr by the client-side API implementation in another 375 * process. 376 */ 377 static 378 PNOTIFYDATA AllocNotifyDataPtr(PVOID pvMemoryPool, // in: memory pool base address 379 PICONDATA pIconData) // in: icon data 380 { 381 // NOTE: we cannot use DosSubAllocMem() and friends since we want to be able 382 // to free blocks allocated to clients which death we detect but we cannot 383 // be sure about the layout of memory DosSub API uses. Therefore, we provide 384 // our own sub-allocation scheme which is rather simple because we need to 385 // allocate equally sized blocks (each is NOTIFYDATA struct). The memory 386 // pool is laid out as follows: MEMPOOLHDR followed by a number of 387 // MEMPOOLBLK. 388 389 APIRET arc; 390 PID pid; 391 TID tid; 392 PMEMPOOLHDR pHdr; 393 ULONG ulMax, ulNeedsCommit, ulNext, ulCurr; 394 PNOTIFYDATA pData; 395 396 LOGF(("pvMemoryPool %p\n", pvMemoryPool)); 397 LOGF(("hwnd %p\n", pIconData->hwnd)); 398 399 if (!pIconData->bMemoryPoolGiven) 400 { 401 LOGF(("Giving memory pool to %lx\n", pIconData->hwnd)); 402 403 arc = ERROR_INVALID_HANDLE; 404 if (WinQueryWindowProcess(pIconData->hwnd, &pid, &tid)) 405 arc = DosGiveSharedMem(pvMemoryPool, pid, PAG_READ | PAG_WRITE); 406 if (arc != NO_ERROR) 407 return NULL; 408 409 pIconData->bMemoryPoolGiven = TRUE; 410 } 411 412 pHdr = (PMEMPOOLHDR)pvMemoryPool; 413 414 // maximum address that is still enough for a block 415 ulMax = pHdr->ulBeyond - sizeof(MEMPOOLBLK); 416 417 ulNeedsCommit = pHdr->ulNeedsCommit; 418 ulNext = pHdr->ulNext; 419 ulCurr = ulNext; 420 421 LOGF(("ulNeedsCommit %p\n", ulNeedsCommit)); 422 LOGF(("ulNext %p\n", ulNext)); 423 424 do 425 { 426 if (ulCurr >= ulNeedsCommit) 427 { 428 // commit more memory; it's OK two or more threads will do the same 429 DosSetMem((PVOID)ulNeedsCommit, 4096, 430 PAG_COMMIT | PAG_READ | PAG_WRITE); 431 // advance the address (only if nobody has already done so -- they 432 // could already commit more than we did) 433 __atomic_cmpxchg32((uint32_t *)&pHdr->ulNeedsCommit, 434 ulNeedsCommit + 4096, ulNeedsCommit); 435 } 436 437 if (__atomic_cmpxchg32((uint32_t *)ulCurr, pIconData->hwnd, NULLHANDLE)) 438 break; 439 440 ulCurr += sizeof(MEMPOOLBLK); 441 if (ulCurr > ulMax) 442 // start over 443 ulCurr = ((ULONG)pvMemoryPool) + sizeof(MEMPOOLHDR); 444 445 if (ulCurr == ulNext) 446 return NULL; // no free blocks! 447 } 448 while (1); 449 450 LOGF(("ulCurr %p\n", ulCurr)); 451 452 // advance to the next possibly free block 453 ulCurr += sizeof(MEMPOOLBLK); 454 if (ulCurr > ulMax) 455 // start over 456 ulCurr = ((ULONG)pvMemoryPool) + sizeof(MEMPOOLHDR); 457 458 // store the new next address until someone else has already done that 459 __atomic_cmpxchg32((uint32_t *)&pHdr->ulNext, ulCurr, ulNext); 460 461 pData = &((PMEMPOOLBLK)ulCurr)->NotifyData; 462 memset(pData, sizeof(*pData), 0); 463 464 pData->msg = pIconData->ulMsgId; 465 pData->mp1 = MPFROMSHORT(pIconData->usId); 466 467 return pData; 468 } 469 470 /* 471 *@@ PostNotifyMsg: 472 * Posts WM_XST_NOTIFY to the given client window. Frees pNotifyData if 473 * posting fails. 474 */ 475 476 VOID PostNotifyMsg(PSYSTRAYDATA pSysTrayData, HWND hwnd, 477 PNOTIFYDATA *pNotifyData) 478 { 479 if (!WinPostMsg(hwnd, WM_XST_NOTIFY, pNotifyData, pSysTrayData->pvMemoryPool)) 480 FreeNotifyDataPtr(pSysTrayData->pvMemoryPool, hwnd, pNotifyData); 344 481 } 345 482 … … 404 541 { 405 542 PSIZEL pszl = (PSIZEL)mp2; 406 LONG pad2 = pSysTrayData->lIconPad * 2; 407 pszl->cx = (pSysTrayData->lIconWidth + pad2) * pSysTrayData->cIcons; // desired width 408 pszl->cy = pSysTrayData->lIconHeight + pad2; // desired minimum height 543 LONG pad = pSysTrayData->lIconPad; 544 size_t cnt = pSysTrayData->cIcons; 545 // desired width 546 if (cnt) 547 pszl->cx = pad + (pSysTrayData->lIconWidth + pad) * cnt; 548 else 549 pszl->cx = 0; 550 // desired minimum height 551 pszl->cy = pSysTrayData->lIconHeight + pad * 2; 409 552 brc = TRUE; 410 553 } … … 421 564 * implementation for WM_PAINT in fnwpXSysTray. 422 565 * 423 * This really does nothing, except painting a 424 * 3D rectangle and printing a question mark. 566 * Draws all the icons. If the widget's center is located to the left from 567 * the XCenter's center, icons go left to right. Otherwise, they go right 568 * to left. 569 */ 570 /* 571 +---------------------------+ p = lIconPad 572 | p | w = lIconWidth 573 | +-------+ +-------+ | h = lIconHeight 574 | p | w | p | w | p | 575 | | h| | h| | 576 | | | | | | If "Frame around statics" is on in XCenter 577 | +-------+ +-------+ | properties, then a 1 px 3D frame is drawn 578 | p | within the pad area. So, lIconPad must 579 +---------------------------+ be at least 2 px. 425 580 */ 426 581 … … 438 593 RECTL rcl; 439 594 BOOL bLeftToRight; 440 LONG x, y, l TotalWidth;595 LONG x, y, lIconStep; 441 596 size_t i; 442 597 … … 481 636 // always center the icon vertically (we may be given more height than 482 637 // we requested) 483 y = (swp.cy - pSysTrayData->lIcon Width) / 2;638 y = (swp.cy - pSysTrayData->lIconHeight) / 2; 484 639 485 640 if (bLeftToRight) … … 488 643 x = swp.cx - pSysTrayData->lIconPad - pSysTrayData->lIconWidth; 489 644 490 l TotalWidth = pSysTrayData->lIconWidth + pSysTrayData->lIconPad * 2;645 lIconStep = pSysTrayData->lIconWidth + pSysTrayData->lIconPad; 491 646 492 647 // where to start from? 493 648 if (bLeftToRight) 494 649 { 495 i = rclPaint.xLeft / l TotalWidth;496 x = pSysTrayData->lIconPad + i * l TotalWidth;650 i = rclPaint.xLeft / lIconStep; 651 x = pSysTrayData->lIconPad + i * lIconStep; 497 652 } 498 653 else 499 654 { 500 i = (swp.cx - rclPaint.xRight) / lTotalWidth; 501 x = swp.cx - (i + 1) * lTotalWidth + pSysTrayData->lIconPad; 655 i = (swp.cx - rclPaint.xRight) / lIconStep; 656 x = swp.cx - (i + 1) * lIconStep; 657 // negate the step, for convenience 658 lIconStep = -lIconStep; 502 659 } 503 660 504 661 // draw as many icons as we can / need 505 for ( i = 0; i < pSysTrayData->cIcons; ++i)662 for (; i < pSysTrayData->cIcons; ++i) 506 663 { 507 664 if (x >= rclPaint.xRight) … … 509 666 510 667 DrawPointer(hps, x, y, pSysTrayData->pIcons[i].hIcon, DP_MINI); 511 if (bLeftToRight) 512 x += lTotalWidth; 513 else 514 x -= lTotalWidth; 668 x += lIconStep; 515 669 } 516 670 517 671 WinEndPaint(hps); 518 672 } 673 } 674 675 /* 676 *@@ WgtMouse: 677 * implementation for WM_BUTTONxyyy in fnwpXSysTray. 678 * 679 * Posts a notification to the window associated with the icon and returns 680 * TRUE if this mouse message is within the icon bounds. Otherwise returns 681 * FALSE. 682 * 683 * Refer to WgtPaint for more details about the widget geometry. 684 */ 685 686 static 687 BOOL WgtMouse(HWND hwnd, ULONG msg, MRESULT mp1, MRESULT mp2, 688 PXCENTERWIDGET pWidget) 689 { 690 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 691 692 POINTL ptl; 693 SWP swp; 694 RECTL rcl; 695 BOOL bLeftToRight; 696 LONG y, lIconStep; 697 size_t i; 698 699 PICONDATA pIconData; 700 PNOTIFYDATA pNotifyData; 701 702 ptl.x = ((PPOINTS)&mp1)->x; 703 ptl.y = ((PPOINTS)&mp1)->y; 704 705 LOGF(("msg %x ptl %ld,%ld\n", msg, ptl.x, ptl.y)); 706 707 WinQueryWindowPos(hwnd, &swp); 708 WinQueryWindowRect(pWidget->pGlobals->hwndClient, &rcl); 709 710 y = (swp.cy - pSysTrayData->lIconHeight) / 2; 711 if (ptl.y < y || ptl.y >= y + pSysTrayData->lIconHeight) 712 return FALSE; // hit pad space 713 714 // detect the direction 715 bLeftToRight = swp.x + swp.cx / 2 < (rcl.xRight / 2); 716 717 lIconStep = pSysTrayData->lIconWidth + pSysTrayData->lIconPad; 718 719 // which icon is that? 720 if (bLeftToRight) 721 { 722 i = ptl.x / lIconStep; 723 if (ptl.x % lIconStep < pSysTrayData->lIconPad) 724 return FALSE; // hit pad space 725 } 726 else 727 { 728 i = (swp.cx - ptl.x - 1) / lIconStep; 729 if ((swp.cx - ptl.x - 1) % lIconStep < pSysTrayData->lIconPad) 730 return FALSE; // hit pad space 731 } 732 if (i >= pSysTrayData->cIcons) 733 return FALSE; // hit pad space 734 735 pIconData = &pSysTrayData->pIcons[i]; 736 737 LOGF(("hwnd %x\n", pIconData->hwnd)); 738 LOGF(("usId %d\n", pIconData->usId)); 739 LOGF(("hIcon %x\n", pIconData->hIcon)); 740 741 // make the coordinates global 742 WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptl, 1); 743 744 // allocate a NOTIFYDATA struct 745 pNotifyData = AllocNotifyDataPtr(pSysTrayData->pvMemoryPool, pIconData); 746 if (!pNotifyData) 747 return FALSE; 748 749 switch (msg) 750 { 751 case WM_HSCROLL: 752 case WM_VSCROLL: 753 pNotifyData->mp1 += XST_IN_WHEEL << 16; 754 pNotifyData->u.WheelMsg.ulWheelMsg = msg; 755 pNotifyData->u.WheelMsg.ptsPointerPos.x = ptl.x; 756 pNotifyData->u.WheelMsg.ptsPointerPos.y = ptl.y; 757 pNotifyData->u.WheelMsg.usCmd = SHORT2FROMMP(mp2); 758 pNotifyData->mp2 = &pNotifyData->u.WheelMsg; 759 break; 760 761 case WM_CONTEXTMENU: 762 pNotifyData->mp1 += XST_IN_CONTEXT << 16; 763 pNotifyData->u.ContextMsg.ptsPointerPos.x = ptl.x; 764 pNotifyData->u.ContextMsg.ptsPointerPos.y = ptl.y; 765 pNotifyData->u.ContextMsg.fPointer = TRUE; 766 pNotifyData->mp2 = &pNotifyData->u.ContextMsg; 767 break; 768 769 default: 770 pNotifyData->mp1 += XST_IN_MOUSE << 16; 771 pNotifyData->u.MouseMsg.ulMouseMsg = msg; 772 pNotifyData->u.MouseMsg.ptsPointerPos.x = ptl.x; 773 pNotifyData->u.MouseMsg.ptsPointerPos.y = ptl.y; 774 pNotifyData->u.MouseMsg.fsHitTestRes = SHORT1FROMMP(mp2); 775 pNotifyData->u.MouseMsg.fsFlags = SHORT2FROMMP(mp2); 776 pNotifyData->mp2 = &pNotifyData->u.MouseMsg; 777 break; 778 } 779 780 PostNotifyMsg(pSysTrayData, hwnd, pNotifyData); 781 782 return TRUE; 783 } 784 785 static 786 VOID FreeSysTrayData(PSYSTRAYDATA pSysTrayData) 787 { 788 // destroy the server 789 if (pSysTrayData->hwndServer != NULLHANDLE) 790 { 791 WinDestroyWindow(pSysTrayData->hwndServer); 792 pSysTrayData->hwndServer = NULLHANDLE; 793 } 794 795 // free all system tray data 796 if (pSysTrayData->pvMemoryPool) 797 { 798 DosFreeMem(pSysTrayData->pvMemoryPool); 799 } 800 if (pSysTrayData->pIcons) 801 { 802 size_t i; 803 for (i = 0; i < pSysTrayData->cIcons; ++i) 804 FreeIconData(&pSysTrayData->pIcons[i]); 805 pSysTrayData->cIcons = 0; 806 free(pSysTrayData->pIcons); 807 pSysTrayData->pIcons = NULL; 808 } 809 810 free(pSysTrayData); 519 811 } 520 812 … … 562 854 563 855 PSYSTRAYDATA pSysTrayData = NULL; 856 APIRET arc; 564 857 565 858 WinSetWindowPtr(hwnd, QWL_USER, mp1); … … 575 868 576 869 // initialize the SYSTRAYDATA structure 870 memset(pSysTrayData, sizeof(*pSysTrayData), 0); 577 871 pSysTrayData->lIconWidth = WinQuerySysValue(HWND_DESKTOP, SV_CXICON) / 2; 578 872 pSysTrayData->lIconHeight = WinQuerySysValue(HWND_DESKTOP, SV_CYICON) / 2; … … 583 877 if (pSysTrayData->pIcons == NULL) 584 878 { 585 free(pSysTrayData);879 FreeSysTrayData(pSysTrayData); 586 880 return (MRESULT)TRUE; 587 881 } 588 882 pSysTrayData->cIcons = 0; 883 884 // Allocate the memory pool for NOTIFYDATA structs (we don't 885 // PAG_COMMIT all memory, AllocNotifyDataPtr() will do so as needed) 886 arc = DosAllocSharedMem((PVOID)&pSysTrayData->pvMemoryPool, NULL, 887 SERVER_MEMORYPOOL_SIZE, 888 PAG_READ | PAG_WRITE | OBJ_GIVEABLE); 889 if (arc == NO_ERROR) 890 { 891 PMEMPOOLHDR pHdr = (PMEMPOOLHDR)pSysTrayData->pvMemoryPool; 892 arc = DosSetMem(pSysTrayData->pvMemoryPool, 4096, 893 PAG_COMMIT | PAG_READ | PAG_WRITE); 894 if (arc == NO_ERROR) 895 { 896 pHdr->ulBeyond = (ULONG)pSysTrayData->pvMemoryPool + 897 SERVER_MEMORYPOOL_SIZE; 898 pHdr->ulNeedsCommit = (ULONG)pSysTrayData->pvMemoryPool + 899 4096; 900 pHdr->ulNext = (ULONG)pSysTrayData->pvMemoryPool + 901 sizeof(MEMPOOLHDR); 902 } 903 } 904 if (arc != NO_ERROR) 905 { 906 FreeSysTrayData(pSysTrayData); 907 return (MRESULT)TRUE; 908 } 589 909 590 910 // create the "server" window (note that we pass the XCENTERWIDGET … … 598 918 if (pSysTrayData->hwndServer == NULLHANDLE) 599 919 { 600 free(pSysTrayData->pIcons); 601 free(pSysTrayData); 920 FreeSysTrayData(pSysTrayData); 602 921 return (MRESULT)TRUE; 603 922 } … … 606 925 607 926 // inform all interested parties that we are fired up 608 // (NOTE: keep in sync with xstGetSysTrayCreatedMsgId()) 609 WinBroadcastMsg(HWND_DESKTOP, 610 WinAddAtom(WinQuerySystemAtomTable(), 611 "ExtendedSysTray.WM_XST_CREATED"), 612 NULL, NULL, 613 BMSG_POST); 927 WinBroadcastMsg(HWND_DESKTOP, WM_XST_CREATED, 928 NULL, NULL, BMSG_POST); 614 929 615 930 return FALSE; // confirm success … … 628 943 629 944 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 630 size_t i; 631 632 // destroy the server 633 WinDestroyWindow(pSysTrayData->hwndServer); 634 pSysTrayData->hwndServer = NULLHANDLE; 635 636 // free all system tray data 637 for (i = 0; i < pSysTrayData->cIcons; ++i) 638 FreeIconData(&pSysTrayData->pIcons[i]); 639 pSysTrayData->cIcons = 0; 640 free(pSysTrayData->pIcons); 641 pSysTrayData->pIcons = NULL; 642 643 // make sure we remove the check alive timer 644 WgtXSysTrayUpdateAfterIconAddRemove(pWidget); 645 646 free(pSysTrayData); 945 946 // stop the check alive timer 947 WinStopTimer(pWidget->habWidget, pSysTrayData->hwndServer, 948 TID_CHECKALIVE); 949 950 FreeSysTrayData(pSysTrayData); 647 951 pWidget->pUser = NULL; 648 952 … … 680 984 break; */ 681 985 986 /* 987 * All mouse click and wheel events: 988 * Note that we hide WM_CONTEXTMENU from XCenter when it is within 989 * the icon bounds as it's a responsibility of the application 990 * owning the icon to show it. 991 */ 992 993 case WM_BUTTON1UP: 994 case WM_BUTTON1DOWN: 995 case WM_BUTTON1CLICK: 996 case WM_BUTTON1DBLCLK: 997 case WM_BUTTON2UP: 998 case WM_BUTTON2DOWN: 999 case WM_BUTTON2CLICK: 1000 case WM_BUTTON2DBLCLK: 1001 case WM_BUTTON3UP: 1002 case WM_BUTTON3DOWN: 1003 case WM_BUTTON3CLICK: 1004 case WM_BUTTON3DBLCLK: 1005 case WM_CONTEXTMENU: 1006 case WM_VSCROLL: 1007 case WM_HSCROLL: 1008 { 1009 if (WgtMouse(hwnd, msg, mp1, mp2, pWidget)) 1010 return (MRESULT)TRUE; 1011 // we didn't hit the icon, pass it on to XCenter 1012 } 1013 break; 1014 682 1015 default: 683 1016 break; … … 713 1046 } 714 1047 715 if (pSysTrayData->pIcons != NULL) 716 { 717 // ask XCenter to take our new size into account (this will also 718 // invalidate us). If pIcons is NULL it means that we are in WM_DESTROY, 719 // in which case XCenter will do everything for us 720 WinPostMsg(pWidget->pGlobals->hwndClient, 721 XCM_REFORMAT, 722 (MPARAM)XFMF_GETWIDGETSIZES, 723 0); 724 } 1048 // ask XCenter to take our new size into account (this will also 1049 // invalidate us) 1050 WinPostMsg(pWidget->pGlobals->hwndClient, 1051 XCM_REFORMAT, 1052 (MPARAM)XFMF_GETWIDGETSIZES, 1053 0); 725 1054 } 726 1055 … … 767 1096 LOGF(("SYSTRAYCMD_ADDICON\n")); 768 1097 LOGF((" hwnd %x\n", pCtlData->hwndSender)); 769 LOGF((" u lId %ld\n", pCtlData->u.icon.ulId));1098 LOGF((" usId %d\n", pCtlData->u.icon.usId)); 770 1099 LOGF((" hIcon %x\n", pCtlData->u.icon.hIcon)); 771 1100 … … 785 1114 786 1115 pData = FindIconData(pSysTrayData, pCtlData->hwndSender, 787 pCtlData->u.icon.u lId, &i);1116 pCtlData->u.icon.usId, &i); 788 1117 if (pData) 789 1118 { … … 825 1154 826 1155 pData = &pSysTrayData->pIcons[i]; 1156 memset(pData, sizeof(*pData), 0); 1157 827 1158 pData->hwnd = pCtlData->hwndSender; 828 pData->u lId = pCtlData->u.icon.ulId;1159 pData->usId = pCtlData->u.icon.usId; 829 1160 pData->hIcon = hIcon; 830 1161 pData->ulMsgId = pCtlData->u.icon.ulMsgId; … … 844 1175 LOGF(("SYSTRAYCMD_REMOVEICON\n")); 845 1176 LOGF((" hwnd %x\n", pCtlData->hwndSender)); 846 LOGF((" u lId %ld\n", pCtlData->u.icon.ulId));1177 LOGF((" usId %d\n", pCtlData->u.icon.usId)); 847 1178 848 1179 pCtlData->bAcknowledged = TRUE; 849 1180 850 1181 pData = FindIconData(pSysTrayData, pCtlData->hwndSender, 851 pCtlData->u.icon.u lId, &i);1182 pCtlData->u.icon.usId, &i); 852 1183 if (pData) 853 1184 { … … 893 1224 { 894 1225 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 1226 PMEMPOOLHDR pMemPoolHdr = (PMEMPOOLHDR)pSysTrayData->pvMemoryPool; 1227 PMEMPOOLBLK pMemPoolBlk; 1228 ULONG ulMemPoolMax; 895 1229 896 1230 if (usTimerId == TID_CHECKALIVE) … … 904 1238 if (!WinIsWindow(pWidget->habWidget, pSysTrayData->pIcons[i].hwnd)) 905 1239 { 1240 PICONDATA pData = &pSysTrayData->pIcons[i]; 1241 906 1242 LOGF(("Removing icon of dead window!\n")); 907 LOGF((" hwnd %x\n", pSysTrayData->pIcons[i].hwnd)); 908 LOGF((" ulId %ld\n", pSysTrayData->pIcons[i].ulId)); 909 LOGF((" hIcon %x\n", pSysTrayData->pIcons[i].hIcon)); 1243 LOGF((" hwnd %x\n", pData->hwnd)); 1244 LOGF((" usId %ld\n", pData->usId)); 1245 LOGF((" hIcon %x\n", pData->hIcon)); 1246 1247 // free memory blocks from the pool allocated for this client 1248 ulMemPoolMax = pMemPoolHdr->ulBeyond; 1249 if (ulMemPoolMax > pMemPoolHdr->ulNeedsCommit) 1250 ulMemPoolMax = pMemPoolHdr->ulNeedsCommit; 1251 ulMemPoolMax -= sizeof(MEMPOOLBLK); 1252 1253 pMemPoolBlk = pMemPoolHdr->aBlocks; 1254 while ((ULONG)pMemPoolBlk <= ulMemPoolMax) 1255 { 1256 if (pMemPoolBlk->hwnd == pData->hwnd) 1257 { 1258 LOGF((" freeing memory block %p\n", pMemPoolBlk)); 1259 __atomic_cmpxchg32((uint32_t *)&pMemPoolBlk->hwnd, 1260 NULLHANDLE, hwnd); 1261 } 1262 ++pMemPoolBlk; 1263 } 910 1264 911 1265 bAnyDead = TRUE; 912 FreeIconData( &pSysTrayData->pIcons[i]);913 // hwnd is NULLHANDLE here1266 FreeIconData(pData); 1267 // pData->hwnd is NULLHANDLE here 914 1268 } 915 1269 } … … 1128 1482 } 1129 1483 1484 if (WM_XST_CREATED == 0) 1485 WM_XST_CREATED = WinAddAtom(WinQuerySystemAtomTable(), 1486 WM_XST_CREATED_ATOM); 1487 if (WM_XST_NOTIFY == 0) 1488 WM_XST_NOTIFY = WinAddAtom(WinQuerySystemAtomTable(), 1489 WM_XST_NOTIFY_ATOM); 1490 1130 1491 // no error: 1131 1492 // return widget classes array -
trunk/src/3rdparty/os2/xsystray/xsystray.h
r272 r273 17 17 #define XSYSTRAY_HEADER_INCLUDED 18 18 19 #include "xsystray_api.h" 20 21 #include <sys/builtin.h> // atomics 22 19 23 #define XSYSTRAY_VERSION_MAJOR 0 20 24 #define XSYSTRAY_VERSION_MINOR 1 … … 26 30 #define INTCLASS_WIDGET_XSYSTRAY "ExtendedSysTray" 27 31 #define HUMANSTR_WIDGET_XSYSTRAY "Extended system tray" 32 33 #define WM_XST_CREATED_ATOM "ExtendedSysTray.WM_XST_CREATED" 34 #define WM_XST_NOTIFY_ATOM "ExtendedSysTray.WM_XST_NOTIFY" 28 35 29 36 #define WM_XST_CONTROL (WM_USER + 0) … … 38 45 SYSTRAYCMD_HIDEBALLOON, 39 46 } SYSTRAYCMD; 47 48 /* 49 *@@ SYSTRAYCTLDATA: 50 * Structure holding information accompanying WM_XST_CONTROL messages sent 51 * to the system tray server by clients (windows associated with system 52 * tray icons). 53 * 54 * NOTE: When you change the size of this structure, you may also need to 55 * change CLIENT_MEMORYPOOL_SIZE value (see the comments there for 56 * details). 57 */ 40 58 41 59 typedef struct … … 58 76 struct 59 77 { 60 U LONG ulId;78 USHORT usId; 61 79 HPOINTER hIcon; 62 80 ULONG ulMsgId; … … 66 84 struct 67 85 { 68 U LONG ulId;86 USHORT usId; 69 87 CHAR szText[512]; 70 88 } tooltip; … … 77 95 } SYSTRAYCTLDATA, *PSYSTRAYCTLDATA; 78 96 97 /* 98 *@@ NOTIFYDATA: 99 * Structure holding information acompanying notification messages 100 * posted to clients (windows associated with system tray icons) about 101 * icon events. This structure unions all public notification code 102 * dependent structures defined in xsystray_api.h (starting with XST*). 103 * 104 * All messages posted to the client have an ID corresponding to the 105 * WM_XST_NOTIFY_ATOM in the system atom table. The client-side API 106 * implementation intercepts these messages (using HK_INPUT), composes a 107 * new message given the information in NOTIFYDATA, frees the NOTIFYDATA 108 * pointer using FreeNotifyDataPtr() and then sends the composed message to 109 * the appropriate window. 110 * 111 * The layout of the XST_NOTIFY message is as follows: 112 * 113 * param1 114 * PNOTIFYDATA pNotifyData pointer to the NOTIFYDATA structure 115 * 116 * param2 117 * PVOID pvMemoryPool server memory pool (for the 118 * FreeNotifyDataPtr() call) 119 * 120 * NOTE: When you change the size of this structure, you may also need to 121 * change SERVER_MEMORYPOOL_SIZE value in xsystray.c (see the comments 122 * there for details). 123 */ 124 125 typedef struct 126 { 127 ULONG msg; 128 // ID of the message that is to be sent to the target window 129 MPARAM mp1; 130 // message parameter (usually: USHORT usIconId, USHORT usNotifyCode) 131 MPARAM mp2; 132 // message parameter (usually, a pointer to a struct from the union) 133 union 134 { 135 XSTMOUSEMSG MouseMsg; 136 XSTCONTEXTMSG ContextMsg; 137 XSTWHEELMSG WheelMsg; 138 } u; 139 140 } NOTIFYDATA, *PNOTIFYDATA; 141 142 // Header of the server-side memory pool 143 typedef struct 144 { 145 volatile HWND hwnd; // owner of the block or NULLHANDLE if free 146 NOTIFYDATA NotifyData; // data 147 148 } MEMPOOLBLK, *PMEMPOOLBLK; 149 150 // allocation unit in the server-side memory pool 151 typedef struct 152 { 153 ULONG ulBeyond; // address of the first byte beyond the memory pool 154 155 volatile ULONG ulNeedsCommit; // address of the first decommitted byte 156 volatile ULONG ulNext; // address of next possibly free block 157 158 MEMPOOLBLK aBlocks[0]; // fake array for easier addressing 159 160 } MEMPOOLHDR, *PMEMPOOLHDR; 161 162 /* 163 *@@ FreeNotifyDataPtr: 164 * Frees the NOTIFYDATA structure allocated by AllocNotifyDataPtr(). 165 * 166 * See AllocNotifyDataPtr() for more details about allocating these 167 * structures.dd 168 */ 169 170 inline 171 VOID FreeNotifyDataPtr(PVOID pvMemoryPool, // in: memory pool base address 172 HWND hwndOwner, // in: owner of the struct to free 173 PNOTIFYDATA pData) // in: address of the struct to free 174 { 175 PMEMPOOLHDR pHdr = (PMEMPOOLHDR)pvMemoryPool; 176 PMEMPOOLBLK pBlk = (PMEMPOOLBLK)((ULONG)pData - sizeof(HWND)); 177 178 ULONG ulNext = pHdr->ulNext; 179 180 __atomic_cmpxchg32((uint32_t *)&pBlk->hwnd, NULLHANDLE, hwndOwner); 181 182 // if the next possible free block is greater than we just freed, 183 // set it to us (to minimize the amount of committed pages) 184 if (ulNext > (ULONG)pBlk) 185 __atomic_cmpxchg32((uint32_t *)&pHdr->ulNext, (ULONG)pBlk, ulNext); 186 } 187 79 188 #endif // XSYSTRAY_HEADER_INCLUDED 80 189 -
trunk/src/3rdparty/os2/xsystray/xsystray_api.c
r272 r273 28 28 #include <sys/builtin.h> // atomics 29 29 30 static HWND G_hwndSysTray = NULLHANDLE; 31 // window handle of the system tray server 32 33 static PVOID G_pvMemoryPool = NULL; 34 // memory pool for SYSTRAYCTLDATA structs used by WM_XST_CONTROL 35 // messages. Note that once allocated, this memory is never freed: 36 // it is intentional since the memory is assumed to be always in 37 // need and that the system will free it when the application 38 // terminates 39 40 #define MEMORYPOOL_SIZE 65536 41 // taking SYSTRAYCTLDATA size into account, this is enough for at least 42 // 64 threads sending WM_XST_CONTROL simultaneously, which sounds sane 30 static 31 volatile HWND G_hwndSysTray = NULLHANDLE; 32 // window handle of the system tray server 33 34 static 35 volatile PVOID G_pvMemoryPool = NULL; 36 // shared memory pool for SYSTRAYCTLDATA structs used by 37 // WM_XST_CONTROL messages. Note that once allocated, this memory 38 // is never freed: it is intentional since the memory is assumed 39 // to be always in need and that the system will free it when the 40 // application terminates 41 42 #define CLIENT_MEMORYPOOL_SIZE 65536 43 // taking SYSTRAYCTLDATA size into account (<=1024 B), this is enough 44 // for at least 64 threads sending WM_XST_CONTROL simultaneously, which 45 // sounds sane 43 46 44 47 // @todo to be on the safe side with casting in __atomic_cmpxchg32() we need … … 116 119 } 117 120 118 // This function allocates a SYSTRAYCTLDATA struct in the pool of shared memory. 119 // If there is no free space in the pool, it returns NULL. The allocated memory 120 // must be freed by FreeSysTrayCtlDataPtr() when not needed. 121 /* 122 *@@ AllocSysTrayCtlDataPtr: 123 * Allocates a SYSTRAYCTLDATA struct in the pool of shared memory. 124 * 125 * If there is no free space in the pool, it returns NULL. The allocated 126 * memory must be freed by FreeSysTrayCtlDataPtr() when not needed. 127 */ 128 121 129 static PSYSTRAYCTLDATA AllocSysTrayCtlDataPtr() 122 130 { … … 128 136 { 129 137 // Note: we don't PAG_COMMIT, DosSubAllocMem will do so when needed 130 arc = DosAllocSharedMem((PVOID)&pvPool, NULL, MEMORYPOOL_SIZE,138 arc = DosAllocSharedMem((PVOID)&pvPool, NULL, CLIENT_MEMORYPOOL_SIZE, 131 139 PAG_READ | PAG_WRITE | OBJ_GIVEABLE); 132 140 if (arc == NO_ERROR) 133 141 arc = DosSubSetMem(pvPool, 134 142 DOSSUB_INIT | DOSSUB_SPARSE_OBJ, 135 MEMORYPOOL_SIZE);143 CLIENT_MEMORYPOOL_SIZE); 136 144 if (!__atomic_cmpxchg32((uint32_t *)&G_pvMemoryPool, 137 145 (uint32_t)pvPool, (uint32_t)NULL)) … … 149 157 } 150 158 151 arc = DosSubAllocMem(G_pvMemoryPool, (PVOID)&pData, sizeof( SYSTRAYCTLDATA));159 arc = DosSubAllocMem(G_pvMemoryPool, (PVOID)&pData, sizeof(*pData)); 152 160 if (arc != NO_ERROR) 153 161 return NULL; … … 158 166 static VOID FreeSysTrayCtlDataPtr(PSYSTRAYCTLDATA pData) 159 167 { 160 DosSubFreeMem(G_pvMemoryPool, pData, sizeof( SYSTRAYCTLDATA));168 DosSubFreeMem(G_pvMemoryPool, pData, sizeof(*pData)); 161 169 } 162 170 … … 220 228 * 221 229 * param1 222 * USHORT usI D icon ID223 * USHORT us Codenotify code, one of XST_IN_ constants230 * USHORT usIconID icon ID 231 * USHORT usNotifyCode notify code, one of XST_IN_ constants 224 232 * 225 233 * param2 226 * PVOID pData notify code specific data (see below)234 * PVOID pData notify code specific data (see below) 227 235 * 228 236 * The following notify codes are currently recognized: … … 232 240 * messages are recognized. param2 is a pointer to the XSTMOUSEMSG 233 241 * structure containing full mouse message details. 242 * 243 * XST_IN_CONTEXT: 244 * Context menu event in the icon area. param2 is a pointer to the 245 * XSTCONTEXTMSG structure containing full message details. 246 * 247 * XST_IN_WHEEL: 248 * Mouse wheel event in the icon area. param2 is a pointer to the 249 * XSTWHEELTMSG structure containing full message details. 234 250 */ 235 251 236 252 BOOL xstAddSysTrayIcon(HWND hwnd, // in: window handle associated with the icon 237 U LONG ulId,// in: icon ID to add253 USHORT usId, // in: icon ID to add 238 254 HPOINTER hIcon, // in: icon handle 239 255 ULONG ulMsgId, // in: message ID for notifications … … 252 268 pData->ulCommand = SYSTRAYCMD_ADDICON; 253 269 pData->hwndSender = hwnd; 254 pData->u.icon.u lId = ulId;270 pData->u.icon.usId = usId; 255 271 pData->u.icon.hIcon = hIcon; 256 272 pData->u.icon.ulMsgId = ulMsgId; … … 278 294 279 295 BOOL xstRemoveSysTrayIcon(HWND hwnd, // in: window handle associated with the icon 280 U LONG ulId)// in: icon ID to remove296 USHORT usId) // in: icon ID to remove 281 297 { 282 298 BOOL brc; … … 287 303 pData->ulCommand = SYSTRAYCMD_REMOVEICON; 288 304 pData->hwndSender = hwnd; 289 pData->u.icon.u lId = ulId;305 pData->u.icon.usId = usId; 290 306 291 307 brc = SendSysTrayCtlMsg(pData); … … 314 330 315 331 BOOL xstSetSysTrayIconToolTip(HWND hwnd, // in: window handle associated with the icon 316 U LONG ulId,// in: icon ID to set the tooltip for332 USHORT usId, // in: icon ID to set the tooltip for 317 333 PSZ pszText) // in: tooltip text 318 334 { … … 324 340 pData->ulCommand = SYSTRAYCMD_SETTOOLTIP; 325 341 pData->hwndSender = hwnd; 326 pData->u.tooltip.u lId = ulId;342 pData->u.tooltip.usId = usId; 327 343 328 344 if (pszText == NULL) … … 343 359 } 344 360 345 BOOL xstShowSysTrayIconBalloon(HWND hwnd, U LONG ulId, PSZ pszTitle, PSZ pszText,361 BOOL xstShowSysTrayIconBalloon(HWND hwnd, USHORT usId, PSZ pszTitle, PSZ pszText, 346 362 ULONG ulFlags, ULONG ulTimeout) 347 363 { … … 350 366 } 351 367 352 BOOL xstHideSysTrayIconBalloon(HWND hwnd, U LONG ulId)368 BOOL xstHideSysTrayIconBalloon(HWND hwnd, USHORT usId) 353 369 { 354 370 // @todo implement … … 364 380 * Returns TRUE on success and FALSE otherwise. 365 381 */ 366 BOOL xstQuerySysTrayIconRect(HWND hwnd, U LONG ulId, PRECTL prclRect)382 BOOL xstQuerySysTrayIconRect(HWND hwnd, USHORT usId, PRECTL prclRect) 367 383 { 368 384 // @todo implement … … 384 400 ULONG xstGetSysTrayCreatedMsgId() 385 401 { 386 // NOTE: keep in sync with fnwpXSysTray()::WM_CREATED387 388 402 static ULONG WM_XST_CREATED = 0; 389 403 if (WM_XST_CREATED == 0) 390 404 WM_XST_CREATED = WinAddAtom(WinQuerySystemAtomTable(), 391 "ExtendedSysTray.WM_XST_CREATED");405 WM_XST_CREATED_ATOM); 392 406 return WM_XST_CREATED; 393 407 } -
trunk/src/3rdparty/os2/xsystray/xsystray_api.h
r256 r273 24 24 // tray (refer to xstAddSysTrayIcon() for details) 25 25 #define XST_IN_MOUSE 0x0001 26 #define XST_IN_CONTEXT 0x0002 27 #define XST_IN_WHEEL 0x0003 26 28 27 29 // structure for XST_IN_MOUSE … … 29 31 { 30 32 ULONG ulMouseMsg; 33 // mouse message (one of WM_BUTTONxyyy) 31 34 POINTS ptsPointerPos; 35 // global pointer position at the time of the mouse event 32 36 USHORT fsHitTestRes; 37 // hit-test result (see WM_BUTTONxyyy description in PM) 33 38 USHORT fsFlags; 39 // keyboard control codes (see WM_BUTTONxyyy description in PM) 34 40 35 41 } XSTMOUSEMSG, *PXSTMOUSEMSG; 36 42 43 // structure for XST_IN_CONTEXT 44 typedef struct 45 { 46 POINTS ptsPointerPos; 47 // global pointer position at the time of the mouse event 48 USHORT fPointer; 49 // input device flag (see WM_CONTEXTMENU description in PM) 50 51 } XSTCONTEXTMSG, *PXSTCONTEXTMSG; 52 53 // structure for XST_IN_WHEEL 54 typedef struct 55 { 56 ULONG ulWheelMsg; 57 // mouse message (one of WM_HSCROLL or WM_VSCROLL) 58 POINTS ptsPointerPos; 59 // global pointer position at the time of the mouse event 60 USHORT usCmd; 61 // command (see WM_HSCROLL/WM_VSCROLL description in PM) 62 63 } XSTWHEELMSG, *PXSTWHEELMSG; 64 37 65 BOOL xstQuerySysTrayVersion(PULONG pulMajor, PULONG pulMinor, PULONG pulRevision); 38 BOOL xstAddSysTrayIcon(HWND hwnd, U LONG ulId, HPOINTER hIcon, ULONG ulMsgId,66 BOOL xstAddSysTrayIcon(HWND hwnd, USHORT usId, HPOINTER hIcon, ULONG ulMsgId, 39 67 ULONG ulFlags); 40 BOOL xstRemoveSysTrayIcon(HWND hwnd, U LONG ulId);41 BOOL xstSetSysTrayIconToolTip(HWND hwnd, U LONG ulId, PSZ pszText);42 BOOL xstShowSysTrayIconBalloon(HWND hwnd, U LONG ulId, PSZ pszTitle, PSZ pszText,68 BOOL xstRemoveSysTrayIcon(HWND hwnd, USHORT usId); 69 BOOL xstSetSysTrayIconToolTip(HWND hwnd, USHORT usId, PSZ pszText); 70 BOOL xstShowSysTrayIconBalloon(HWND hwnd, USHORT usId, PSZ pszTitle, PSZ pszText, 43 71 ULONG ulFlags, ULONG ulTimeout); 44 BOOL xstHideSysTrayIconBalloon(HWND hwnd, U LONG ulId);72 BOOL xstHideSysTrayIconBalloon(HWND hwnd, USHORT usId); 45 73 46 BOOL xstQuerySysTrayIconRect(HWND hwnd, U LONG ulId, PRECTL prclRect);74 BOOL xstQuerySysTrayIconRect(HWND hwnd, USHORT usId, PRECTL prclRect); 47 75 48 76 ULONG xstGetSysTrayCreatedMsgId();
Note:
See TracChangeset
for help on using the changeset viewer.