Changeset 272 for trunk/src/3rdparty/os2/xsystray/xsystray_api.c
- Timestamp:
- Oct 31, 2009, 2:00:20 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/3rdparty/os2/xsystray/xsystray_api.c
r270 r272 17 17 #define INCL_DOSPROCESS 18 18 #define INCL_WINWINDOWMGR 19 19 20 #define INCL_WINATOM 20 21 #define INCL_WINPOINTERS … … 26 27 #include <string.h> 27 28 #include <sys/builtin.h> // atomics 28 #include <InnotekLIBC/thread.h> // TLS29 29 30 30 static HWND G_hwndSysTray = NULLHANDLE; 31 static int G_itlsSysTrayCtlData = -1; 32 33 static HWND FindSysTrayWindow() 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 43 44 // @todo to be on the safe side with casting in __atomic_cmpxchg32() we need 45 // compile-time assertions like this: 46 // AssertCompile(sizeof(uint32_t) == sizeof(HWND)); 47 // AssertCompile(sizeof(uint32_t) == sizeof(PVOID)); 48 49 static HWND FindSysTrayServerWindow() 34 50 { 35 51 char buf[sizeof(WNDCLASS_WIDGET_XSYSTRAY_SERVER) + 1]; … … 62 78 { 63 79 bTriedFind = TRUE; 64 HWND hwnd = FindSysTray Window();80 HWND hwnd = FindSysTrayWindow(); 65 81 __atomic_cmpxchg32((uint32_t *)&G_hwndSysTray, hwnd, NULLHANDLE); 66 82 if (G_hwndSysTray == NULLHANDLE) … … 72 88 arc = ERROR_INVALID_HANDLE; 73 89 if (WinQueryWindowProcess(G_hwndSysTray, &pid, &tid)) 74 arc = DosGiveSharedMem( __libc_TLSGet(G_itlsSysTrayCtlData),90 arc = DosGiveSharedMem(, 75 91 pid, PAG_READ | PAG_WRITE); 76 92 if (arc != NO_ERROR) … … 100 116 } 101 117 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). 106 static PSYSTRAYCTLDATA GetSysTrayCtlDataPtr() 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 static PSYSTRAYCTLDATA AllocSysTrayCtlDataPtr() 107 122 { 108 123 APIRET arc; 109 110 // allocate a thread local storage entry if not done so 111 if (G_itlsSysTrayCtlData == -1) 112 { 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) 116 int itls = __libc_TLSAlloc(); 117 if (!__atomic_cmpxchg32(&G_itlsSysTrayCtlData, itls, -1)) 124 PVOID pvPool; 125 PSYSTRAYCTLDATA pData; 126 127 if (!G_pvMemoryPool) 128 { 129 // Note: we don't PAG_COMMIT, DosSubAllocMem will do so when needed 130 arc = DosAllocSharedMem((PVOID)&pvPool, NULL, MEMORYPOOL_SIZE, 131 PAG_READ | PAG_WRITE | OBJ_GIVEABLE); 132 if (arc == NO_ERROR) 133 arc = DosSubSetMem(pvPool, 134 DOSSUB_INIT | DOSSUB_SPARSE_OBJ, 135 MEMORYPOOL_SIZE); 136 if (!__atomic_cmpxchg32((uint32_t *)&G_pvMemoryPool, 137 (uint32_t)pvPool, (uint32_t)NULL)) 118 138 { 119 139 // another thread has already got an entry, discard our try 120 if ( itls != -1)121 __libc_TLSFree(itls);140 if () 141 ); 122 142 } 123 124 if (G_itlsSysTrayCtlData == -1) 125 return NULL; 126 } 127 128 // allocate a SYSTRAYCTLDATA struct for this thread if not done so 129 PSYSTRAYCTLDATA pData = __libc_TLSGet(G_itlsSysTrayCtlData); 130 if (!pData) 131 { 132 arc = DosAllocSharedMem((PVOID)&pData, NULL, sizeof(SYSTRAYCTLDATA), 133 PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE); 134 if (arc != NO_ERROR) 135 return NULL; 136 137 __libc_TLSSet(G_itlsSysTrayCtlData, pData); 138 139 // note that we don't ever free the allocated block since our API doesn't 140 // have a concept of initialization/termination and therefore it's fine 141 // if the memory stays allocated until application termination 142 } 143 else 144 { 145 // we could fail to allocate while being the first... give up 146 if (arc != NO_ERROR) 147 return NULL; 148 } 149 } 150 151 arc = DosSubAllocMem(G_pvMemoryPool, (PVOID)&pData, sizeof(SYSTRAYCTLDATA)); 152 if (arc != NO_ERROR) 153 return NULL; 143 154 144 155 return pData; 156 157 158 159 160 145 161 } 146 162 … … 166 182 { 167 183 BOOL brc; 168 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();184 PSYSTRAYCTLDATA pData = SysTrayCtlDataPtr(); 169 185 if (!pData) 170 186 return FALSE; … … 184 200 } 185 201 202 203 186 204 return brc; 187 205 } … … 224 242 BOOL brc; 225 243 PPIB ppib; 226 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();244 PSYSTRAYCTLDATA pData = SysTrayCtlDataPtr(); 227 245 if (!pData) 228 246 return FALSE; … … 230 248 // give all processes temporary access to hIcon 231 249 brc = WinSetPointerOwner(hIcon, 0, FALSE); 232 if (!brc) 233 return FALSE; 234 235 pData->ulCommand = SYSTRAYCMD_ADDICON; 236 pData->hwndSender = hwnd; 237 pData->u.icon.ulId = ulId; 238 pData->u.icon.hIcon = hIcon; 239 pData->u.icon.ulMsgId = ulMsgId; 240 241 brc = SendSysTrayCtlMsg(pData); 242 243 // revoke temporary access to hIcon 244 DosGetInfoBlocks(NULL, &ppib); 245 WinSetPointerOwner(hIcon, ppib->pib_ulpid, TRUE); 250 if (brc) 251 { 252 pData->ulCommand = SYSTRAYCMD_ADDICON; 253 pData->hwndSender = hwnd; 254 pData->u.icon.ulId = ulId; 255 pData->u.icon.hIcon = hIcon; 256 pData->u.icon.ulMsgId = ulMsgId; 257 258 brc = SendSysTrayCtlMsg(pData); 259 260 // revoke temporary access to hIcon 261 DosGetInfoBlocks(NULL, &ppib); 262 WinSetPointerOwner(hIcon, ppib->pib_ulpid, TRUE); 263 } 264 265 FreeSysTrayCtlDataPtr(pData); 246 266 247 267 return brc; … … 260 280 ULONG ulId) // in: icon ID to remove 261 281 { 262 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr(); 282 BOOL brc; 283 PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr(); 263 284 if (!pData) 264 285 return FALSE; … … 268 289 pData->u.icon.ulId = ulId; 269 290 270 return SendSysTrayCtlMsg(pData); 291 brc = SendSysTrayCtlMsg(pData); 292 293 FreeSysTrayCtlDataPtr(pData); 294 295 return brc; 271 296 } 272 297 … … 292 317 PSZ pszText) // in: tooltip text 293 318 { 294 PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr(); 319 BOOL brc; 320 PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr(); 295 321 if (!pData) 296 322 return FALSE; … … 310 336 } 311 337 312 return SendSysTrayCtlMsg(pData); 338 brc = SendSysTrayCtlMsg(pData); 339 340 FreeSysTrayCtlDataPtr(pData); 341 342 return brc; 313 343 } 314 344
Note:
See TracChangeset
for help on using the changeset viewer.