Changeset 265
- Timestamp:
- Oct 29, 2009, 2:13:16 AM (16 years ago)
- Location:
- trunk/src/3rdparty/os2/xsystray
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/3rdparty/os2/xsystray/xsystray.c
r256 r265 76 76 77 77 // primitive debug logging to a file 78 #if 178 #if 0 79 79 static void __LOG_WORKER(const char *fmt, ...) 80 80 { … … 133 133 typedef struct 134 134 { 135 LONG lIconWidth; 136 // system icon width in px 137 LONG lIconHeight; 138 // system icon height in px 139 LONG lIconPad; 140 // padding around each icon in px 135 141 PICONDATA pIcons; 136 142 // array of icons currently shown in the system tray 137 // (left to right)138 143 size_t cIcons; 139 144 // number of icons in the pIcons array … … 143 148 } SYSTRAYDATA, *PSYSTRAYDATA; 144 149 145 ULONG QWL_USER_SERVER_DATA = 0; 150 static ULONG QWL_USER_SERVER_DATA = 0; 151 // offset to the PXCENTERWIDGET pointer in the widget data array 152 153 #define TID_CHECKALIVE 1 154 // check alive timer 155 #define TID_CHECKALIVE_TIMEOUT 1000 // ms 156 // how often to check if windows associated with icons are still alive 146 157 147 158 /* ****************************************************************** … … 240 251 /* ****************************************************************** 241 252 * 253 * Helper methods 254 * 255 ********************************************************************/ 256 257 VOID FreeIconData(PICONDATA pData) 258 { 259 pData->hwnd = NULLHANDLE; 260 pData->ulId = 0; 261 if (pData->hIcon != NULLHANDLE) 262 { 263 WinDestroyPointer(pData->hIcon); 264 pData->hIcon = NULLHANDLE; 265 266 } 267 pData->ulMsgId = 0; 268 if (pData->pszToolTip) 269 { 270 free(pData->pszToolTip); 271 pData->pszToolTip = NULL; 272 } 273 } 274 275 /* ****************************************************************** 276 * 242 277 * PM window class implementation 243 278 * … … 265 300 MPARAM mp2) 266 301 { 302 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 267 303 BOOL brc = FALSE; 268 304 … … 285 321 { 286 322 PSIZEL pszl = (PSIZEL)mp2; 287 pszl->cx = 30; // desired width 288 pszl->cy = 20; // desired minimum height 323 LONG pad2 = pSysTrayData->lIconPad * 2; 324 pszl->cx = (pSysTrayData->lIconWidth + pad2) * pSysTrayData->cIcons; // desired width 325 pszl->cy = pSysTrayData->lIconHeight + pad2; // desired minimum height 289 326 brc = TRUE; 290 327 } … … 297 334 } 298 335 336 static 337 BOOL DrawPointer(HPS hps, LONG lx, LONG ly, HPOINTER hptrPointer, BOOL bMini) 338 { 339 return WinDrawPointer(hps, lx, ly, hptrPointer, bMini ? DP_MINI : DP_NORMAL); 340 // @todo: 341 // 1) for icons w/o real alpha, draw them manually by correctly selecting 342 // the normal or mini HBITMAP (WinDrawPointer fails to do so); 343 // 2) for icons with real alpha, do manual alpha blending 344 } 345 299 346 /* 300 347 *@@ WgtPaint: … … 309 356 PXCENTERWIDGET pWidget) 310 357 { 358 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 311 359 HPS hps; 312 if ((hps = WinBeginPaint(hwnd, NULLHANDLE, NULL))) 313 { 314 RECTL rclWin; 360 RECTL rclPaint; 361 362 if ((hps = WinBeginPaint(hwnd, NULLHANDLE, &rclPaint))) 363 { 364 SWP swp; 365 RECTL rcl; 366 BOOL bLeftToRight; 367 LONG x, lTotalWidth; 368 size_t i; 369 370 WinQueryWindowPos(hwnd, &swp); 371 WinQueryWindowRect(pWidget->pGlobals->hwndClient, &rcl); 372 373 // correct the paint area 374 // @todo find out why it exceeds the window bounds 375 if (rclPaint.xLeft < 0) 376 rclPaint.xLeft = 0; 377 if (rclPaint.xRight > swp.cx) 378 rclPaint.xRight = swp.cx; 379 if (rclPaint.yBottom < 0) 380 rclPaint.yBottom = 0; 381 if (rclPaint.yTop > swp.cy) 382 rclPaint.yTop = swp.cy; 383 384 LOGF(("rclPaint %d,%d-%d,%d\n", 385 rclPaint.xLeft, rclPaint.xRight, rclPaint.yBottom, rclPaint.yTop)); 315 386 316 387 // switch HPS to RGB mode 317 388 GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL); 318 389 319 // now paint 320 WinQueryWindowRect(hwnd, 321 &rclWin); // exclusive 322 323 WinFillRect(hps, 324 &rclWin, // exclusive 390 // draw icons left to right if our center is closer to the left edge 391 // of XCenter and right to left otherwise 392 bLeftToRight = swp.x + swp.cx / 2 < (rcl.xRight / 2); 393 394 WinFillRect(hps, &rclPaint, 325 395 WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0)); 326 396 327 // print question mark 328 WinDrawText(hps, 329 1, 330 "?", 331 &rclWin, // exclusive 332 WinQuerySysColor(HWND_DESKTOP, SYSCLR_WINDOWSTATICTEXT, 0), 333 WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0), 334 DT_CENTER | DT_VCENTER); 397 if (bLeftToRight) 398 x = pSysTrayData->lIconPad; 399 else 400 x = swp.cx - pSysTrayData->lIconPad - pSysTrayData->lIconWidth; 401 402 lTotalWidth = pSysTrayData->lIconWidth + pSysTrayData->lIconPad * 2; 403 404 // where to start from? 405 if (bLeftToRight) 406 { 407 i = rclPaint.xLeft / lTotalWidth; 408 x = pSysTrayData->lIconPad + i * lTotalWidth; 409 } 410 else 411 { 412 i = (swp.cx - rclPaint.xRight) / lTotalWidth; 413 x = swp.cx - (i + 1) * lTotalWidth + pSysTrayData->lIconPad; 414 } 415 416 // draw as many icons as we can / need 417 for (i = 0; i < pSysTrayData->cIcons; ++i) 418 { 419 if (x >= rclPaint.xRight) 420 break; 421 422 DrawPointer(hps, x, pSysTrayData->lIconPad, 423 pSysTrayData->pIcons[i].hIcon, DP_MINI); 424 if (bLeftToRight) 425 x += lTotalWidth; 426 else 427 x -= lTotalWidth; 428 } 335 429 336 430 WinEndPaint(hps); … … 394 488 395 489 // initialize the SYSTRAYDATA structure 490 pSysTrayData->lIconWidth = WinQuerySysValue(HWND_DESKTOP, SV_CXICON) / 2; 491 pSysTrayData->lIconHeight = WinQuerySysValue(HWND_DESKTOP, SV_CYICON) / 2; 492 pSysTrayData->lIconPad = pSysTrayData->lIconHeight / 8; 396 493 pSysTrayData->cIconsMax = 4; 397 494 pSysTrayData->pIcons = malloc(sizeof(*pSysTrayData->pIcons) * … … 459 556 size_t i; 460 557 for (i = 0; i < pSysTrayData->cIcons; ++i) 461 { 462 if (pSysTrayData->pIcons[i].pszToolTip) 463 free(pSysTrayData->pIcons[i].pszToolTip); 464 } 558 FreeIconData(&pSysTrayData->pIcons[i]); 465 559 free(pSysTrayData->pIcons); 466 560 free(pSysTrayData); … … 484 578 * implementation for WM_XST_CONTROL in fnwpXSysTrayServer. 485 579 * 486 * Serves as an entry point for all client-side requests to the Extended487 * system tray.580 * Serves as an entry point for all client-side API requests to the 581 * Extended system tray. 488 582 * 489 583 * Note that this message is being sent from another process which is … … 497 591 { 498 592 BOOL brc = FALSE; 593 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 499 594 500 595 switch (pCtlData->ulCommand) … … 512 607 break; 513 608 609 case SYSTRAYCMD_ADDICON: 610 { 611 POINTERINFO Info; 612 HPOINTER hIcon = NULLHANDLE; 613 614 LOGF(("SYSTRAYCMD_ADDICON\n")); 615 LOGF(("hIcon %x\n", pCtlData->u.icon.hIcon)); 616 617 pCtlData->bAcknowledged = TRUE; 618 619 // make a private copy of the provided icon (it will get lost after 620 // we return from this message) 621 brc = WinQueryPointerInfo(pCtlData->u.icon.hIcon, &Info); 622 if (!brc) 623 break; 624 hIcon = WinCreatePointerIndirect(HWND_DESKTOP, &Info); 625 if (hIcon == NULLHANDLE) 626 { 627 brc = FALSE; 628 break; 629 } 630 631 // @todo just testing.... 632 if (pSysTrayData->pIcons[0].hIcon != NULLHANDLE) 633 WinDestroyPointer(pSysTrayData->pIcons[0].hIcon); 634 pSysTrayData->cIcons = 1; 635 pSysTrayData->pIcons[0].hwnd = pCtlData->hwndSender; 636 pSysTrayData->pIcons[0].ulId = pCtlData->u.icon.ulId; 637 pSysTrayData->pIcons[0].hIcon = hIcon; 638 pSysTrayData->pIcons[0].ulMsgId = pCtlData->u.icon.ulMsgId; 639 640 // ask XCenter to take our new size into account 641 // (this will also invalidate us) 642 WinPostMsg(pWidget->pGlobals->hwndClient, 643 XCM_REFORMAT, 644 (MPARAM)XFMF_GETWIDGETSIZES, 645 0); 646 647 if (pSysTrayData->cIcons == 1) 648 { 649 // start a timer to perform "is window alive" checks 650 WinStartTimer(pWidget->habWidget, hwnd, 651 TID_CHECKALIVE, 652 TID_CHECKALIVE_TIMEOUT); 653 } 654 655 brc = TRUE; 656 } 657 514 658 default: 515 659 break; 516 660 } 517 661 662 LOGF(("return %d (WinGetLastError is %x)\n", 663 brc, WinGetLastError(pWidget->habWidget))); 664 518 665 return brc; 666 } 667 668 /* 669 *@@ WgtXSysTrayTimer: 670 * implementation for WM_TIMER in fnwpXSysTrayServer. 671 */ 672 673 static 674 VOID WgtXSysTrayTimer(HWND hwnd, PXCENTERWIDGET pWidget, 675 USHORT usTimerId) 676 { 677 PSYSTRAYDATA pSysTrayData = (PSYSTRAYDATA)pWidget->pUser; 678 679 if (usTimerId == TID_CHECKALIVE) 680 { 681 // check if windows associated with the icons are still alive 682 // and remove those icons whose windows are invalid 683 BOOL bAnyDead = FALSE; 684 size_t i; 685 for (i = 0; i < pSysTrayData->cIcons; ++i) 686 { 687 if (!WinIsWindow(pWidget->habWidget, pSysTrayData->pIcons[i].hwnd)) 688 { 689 bAnyDead = TRUE; 690 FreeIconData(&pSysTrayData->pIcons[i]); 691 // hwnd is NULLHANDLE here 692 } 693 } 694 695 if (bAnyDead) 696 { 697 // compact the icon array 698 i = 0; 699 while (i < pSysTrayData->cIcons) 700 { 701 if (pSysTrayData->pIcons[i].hwnd == NULLHANDLE) 702 { 703 --pSysTrayData->cIcons; 704 if (pSysTrayData->cIcons > 0) 705 { 706 memcpy(&pSysTrayData->pIcons[i], 707 &pSysTrayData->pIcons[i + 1], 708 sizeof(*pSysTrayData->pIcons) * (pSysTrayData->cIcons - i)); 709 } 710 } 711 else 712 ++i; 713 } 714 715 if (pSysTrayData->cIcons == 0) 716 { 717 // stop the check alive timer 718 WinStopTimer(pWidget->habWidget, hwnd, 719 TID_CHECKALIVE); 720 } 721 722 // ask XCenter to take our new size into account 723 // (this will also invalidate us) 724 WinPostMsg(pWidget->pGlobals->hwndClient, 725 XCM_REFORMAT, 726 (MPARAM)XFMF_GETWIDGETSIZES, 727 0); 728 } 729 } 519 730 } 520 731 … … 556 767 mrc = (MRESULT)WgtXSysTrayControl(hwnd, pWidget, 557 768 (PSYSTRAYCTLDATA)mp1); 769 break; 770 771 /* 772 * WM_TIMER: 773 * timer event. 774 */ 775 776 case WM_TIMER: 777 WgtXSysTrayTimer(hwnd, pWidget, SHORT1FROMMP(mp1)); 558 778 break; 559 779 -
trunk/src/3rdparty/os2/xsystray/xsystray_api.c
r256 r265 15 15 16 16 #define INCL_DOSERRORS 17 #define INCL_DOSPROCESS 17 18 #define INCL_WINWINDOWMGR 18 19 #define INCL_WINATOM 20 #define INCL_WINPOINTERS 19 21 #include <os2.h> 20 22 … … 98 100 } 99 101 102 // This function returns a per-thread SYSTRAYCTLDATA pointer. We communicate 103 // to the server thread using WinSendMsg() which allows us to reuse a single 104 // memory block for all calls (WinSendMsg() doesn't return until the server is 105 // done with processing the message). 100 106 static PSYSTRAYCTLDATA GetSysTrayCtlDataPtr() 101 107 { … … 105 111 if (G_itlsSysTrayCtlData == -1) 106 112 { 107 // @todo does XWorkplace have its own TLS? Not? Use108 // DosAllocThreadLocalMemory() directly then (though it's not nice due109 // to the lack ofspace in that area)113 // @todo does XWorkplace have its own TLS? Or is it built with GCC? Not? 114 // Use DosAllocThreadLocalMemory() directly then (though it's not nice 115 // due to the too limited amount of memory space in that area) 110 116 int itls = __libc_TLSAlloc(); 111 117 if (!__atomic_cmpxchg32(&G_itlsSysTrayCtlData, itls, -1)) … … 159 165 PULONG pulRevision) // out: revision number 160 166 { 167 BOOL brc; 161 168 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr(); 162 169 if (!pData) … … 166 173 pData->hwndSender = NULLHANDLE; 167 174 168 BOOLbrc = SendSysTrayCtlMsg(pData);175 brc = SendSysTrayCtlMsg(pData); 169 176 if (brc) 170 177 { … … 215 222 ULONG ulFlags) // in: flags (not currently used, must be 0) 216 223 { 224 BOOL brc; 225 PPIB ppib; 217 226 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr(); 218 227 if (!pData) 228 return FALSE; 229 230 // give all processes temporary access to hIcon 231 brc = WinSetPointerOwner(hIcon, 0, FALSE); 232 if (!brc) 219 233 return FALSE; 220 234 … … 225 239 pData->u.icon.ulMsgId = ulMsgId; 226 240 227 return SendSysTrayCtlMsg(pData); 241 brc = SendSysTrayCtlMsg(pData); 242 243 // revoke temporary access to hIcon 244 DosGetInfoBlocks(NULL, &ppib); 245 WinSetPointerOwner(hIcon, ppib->pib_ulpid, TRUE); 246 247 return brc; 228 248 } 229 249
Note:
See TracChangeset
for help on using the changeset viewer.