1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include <svpm.h> 25 26 #include <string.h> 27 28 #include <tools/debug.hxx> 29 #include <tools/svwin.h> 30 31 #include "vcl/svapp.hxx" 32 33 #include "os2/saldata.hxx" 34 #include "os2/salinst.h" 35 #include "os2/salframe.h" 36 #include "os2/salobj.h" 37 38 // ======================================================================= 39 40 static sal_Bool ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild ) 41 { 42 if ( hWndParent == hWndChild ) 43 return TRUE; 44 45 HWND hTempWnd = WinQueryWindow( hWndChild, QW_PARENT ); 46 while ( hTempWnd ) 47 { 48 if ( hTempWnd == hWndParent ) 49 return TRUE; 50 hTempWnd = WinQueryWindow( hTempWnd, QW_PARENT ); 51 } 52 53 return FALSE; 54 } 55 56 // ----------------------------------------------------------------------- 57 58 static Os2SalObject* ImplFindOs2SalObject( HWND hWndChild ) 59 { 60 SalData* pSalData = GetSalData(); 61 Os2SalObject* pObject = pSalData->mpFirstObject; 62 while ( pObject ) 63 { 64 if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) ) 65 return pObject; 66 67 pObject = pObject->mpNextObject; 68 } 69 70 return NULL; 71 } 72 73 // ======================================================================= 74 75 sal_Bool EXPENTRY SalSysMsgProc( HAB /* hAB */, QMSG* pMsg, ULONG /* fs */ ) 76 { 77 if ( (pMsg->msg == WM_BUTTON1DOWN) || 78 (pMsg->msg == WM_BUTTON2DOWN) || 79 (pMsg->msg == WM_BUTTON3DOWN) ) 80 { 81 SalData* pSalData = GetSalData(); 82 Os2SalObject* pObject = ImplFindOs2SalObject( pMsg->hwnd ); 83 if ( pObject ) 84 WinPostMsg( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 ); 85 } 86 87 // Focus fangen wir hier nicht ab, da wir erstmal davon ausgehen, 88 // das unser Os2SalObject-Fenster immer eine WM_FOCUSCHANGE-Message 89 // bekommt. 90 91 return FALSE; 92 } 93 94 // ----------------------------------------------------------------------- 95 96 MRESULT EXPENTRY SalSysObjWndProc( HWND hWnd, ULONG nMsg, 97 MPARAM nMP1, MPARAM nMP2 ) 98 { 99 Os2SalObject* pSysObj; 100 MRESULT nRet = 0; 101 int bDef = TRUE; 102 103 #if OSL_DEBUG_LEVEL>0 104 debug_printf( "SalSysObjWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); 105 #endif 106 107 switch( nMsg ) 108 { 109 case WM_ERASEBACKGROUND: 110 nRet = (MRESULT)FALSE; 111 bDef = FALSE; 112 break; 113 case WM_PAINT: 114 { 115 HPS hPS; 116 RECTL aRect; 117 hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); 118 WinEndPaint( hPS ); 119 bDef = FALSE; 120 } 121 bDef = FALSE; 122 break; 123 124 case WM_BUTTON1DOWN: 125 case WM_BUTTON2DOWN: 126 case WM_BUTTON3DOWN: 127 case SALOBJ_MSG_TOTOP: 128 if ( ImplSalYieldMutexTryToAcquire() ) 129 { 130 pSysObj = GetSalObjWindowPtr( hWnd ); 131 pSysObj->mpProc( pSysObj->mpInst, pSysObj, 132 SALOBJ_EVENT_TOTOP, 0 ); 133 ImplSalYieldMutexRelease(); 134 } 135 else 136 WinPostMsg( hWnd, SALOBJ_MSG_TOTOP, 0, 0 ); 137 break; 138 139 case WM_FOCUSCHANGE: 140 case SALOBJ_MSG_POSTFOCUS: 141 if ( ImplSalYieldMutexTryToAcquire() ) 142 { 143 pSysObj = GetSalObjWindowPtr( hWnd ); 144 if ( SHORT1FROMMP( nMP2 ) ) 145 { 146 pSysObj->mhLastFocusWnd = WinQueryFocus( HWND_DESKTOP ); 147 pSysObj->mpProc( pSysObj->mpInst, pSysObj, 148 SALOBJ_EVENT_GETFOCUS, 0 ); 149 } 150 else 151 { 152 HWND hWndFocus = HWNDFROMMP( nMP1 ); 153 if ( !hWndFocus || !ImplIsSysWindowOrChild( hWnd, hWndFocus ) ) 154 { 155 pSysObj->mpProc( pSysObj->mpInst, pSysObj, 156 SALOBJ_EVENT_LOSEFOCUS, 0 ); 157 } 158 } 159 ImplSalYieldMutexRelease(); 160 } 161 else 162 WinPostMsg( hWnd, SALOBJ_MSG_POSTFOCUS, nMP1, nMP2 ); 163 break; 164 165 case WM_SIZE: 166 { 167 pSysObj = GetSalObjWindowPtr( hWnd ); 168 pSysObj->mnHeight = (short)SHORT2FROMMP( nMP2 ); 169 WinSetWindowPos( pSysObj->mhWndChild, 0, 170 0, 0, 171 (short)SHORT1FROMMP( nMP2 ), (short)SHORT2FROMMP( nMP2 ), 172 SWP_SIZE | SWP_MOVE ); 173 bDef = FALSE; 174 } 175 break; 176 177 case WM_CREATE: 178 { 179 // Window-Instanz am Windowhandle speichern 180 CREATESTRUCT* pStruct = (CREATESTRUCT*)nMP2; 181 pSysObj = (Os2SalObject*)pStruct->pPresParams; 182 SetSalObjWindowPtr( hWnd, pSysObj ); 183 bDef = FALSE; 184 } 185 break; 186 } 187 188 if ( bDef ) 189 nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); 190 return nRet; 191 } 192 193 // ----------------------------------------------------------------------- 194 195 MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg, 196 MPARAM nMP1, MPARAM nMP2 ) 197 { 198 MRESULT nRet = 0; 199 int bDef = TRUE; 200 201 #if OSL_DEBUG_LEVEL>0 202 debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); 203 #endif 204 205 switch( nMsg ) 206 { 207 case WM_ERASEBACKGROUND: 208 // Wegen PlugIn's loeschen wir erstmal den Hintergrund 209 /* 210 nRet = (MRESULT)FALSE; 211 bDef = FALSE; 212 */ 213 break; 214 case WM_PAINT: 215 { 216 HPS hPS; 217 RECTL aRect; 218 hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); 219 WinEndPaint( hPS ); 220 bDef = FALSE; 221 } 222 break; 223 } 224 225 if ( bDef ) 226 nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); 227 return nRet; 228 } 229 230 // ----------------------------------------------------------------------- 231 232 MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg, 233 MPARAM nMP1, MPARAM nMP2 ) 234 { 235 MRESULT nRet = 0; 236 int bDef = TRUE; 237 238 #if OSL_DEBUG_LEVEL>0 239 debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); 240 #endif 241 242 switch( nMsg ) 243 { 244 case WM_MOUSEMOVE: 245 case WM_BUTTON1DOWN: 246 case WM_BUTTON2DOWN: 247 case WM_BUTTON3DOWN: 248 case WM_BUTTON1DBLCLK: 249 case WM_BUTTON2DBLCLK: 250 case WM_BUTTON3DBLCLK: 251 case WM_BUTTON1UP: 252 case WM_BUTTON2UP: 253 case WM_BUTTON3UP: 254 { 255 // Alle Events an den Frame weiterreichen, da diese Bereiche 256 // dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten 257 // entsprechend umgerechnet werden 258 HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster 259 hWndParent = WinQueryWindow( hWndParent, QW_PARENT ); 260 short nX = (short)SHORT1FROMMP( nMP1 ); 261 short nY = (short)SHORT2FROMMP( nMP1 ); 262 POINTL aPos; 263 aPos.x = nX; 264 aPos.y = nY; 265 WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 ); 266 nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y ); 267 bDef = FALSE; 268 nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 ); 269 } 270 break; 271 272 case WM_HITTEST: 273 // Damit im disablten Zustand die MouseKlicks immer noch 274 // an den Frame geschickt werden 275 // Dieser Code reicht leider nicht aus, deshalb wir unter 276 // OS2 immer das Child-Fenster disablen, im Gegensatz 277 // zu Windows, wo immer der Parent disablte wird, da 278 // sich das Fenster evtl. anders Darstellen koennte, 279 // wenn es disablte wird. Da dieser Fall uns bisher 280 // nicht bekannt ist, ignorieren wir das. 281 nRet = HT_NORMAL; 282 bDef = FALSE; 283 break; 284 285 case WM_ERASEBACKGROUND: 286 nRet = (MRESULT)FALSE; 287 bDef = FALSE; 288 break; 289 case WM_PAINT: 290 { 291 HPS hPS; 292 RECTL aRect; 293 hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); 294 WinEndPaint( hPS ); 295 bDef = FALSE; 296 } 297 break; 298 } 299 300 if ( bDef ) 301 nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); 302 return nRet; 303 } 304 305 // ======================================================================= 306 307 void ImplDestroyAllClipWindows( HWND hWndLast ) 308 { 309 if ( hWndLast == HWND_TOP ) 310 return; 311 312 HWND hWndPrev; 313 while ( hWndLast ) 314 { 315 hWndPrev = WinQueryWindow( hWndLast, QW_PREV ); 316 WinDestroyWindow( hWndLast ); 317 hWndLast = hWndPrev; 318 } 319 } 320 321 // ======================================================================= 322 323 SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent ) 324 { 325 SalData* pSalData = GetSalData(); 326 327 if ( !pSalData->mbObjClassInit ) 328 { 329 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME, 330 (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY, 331 SAL_OBJECT_WNDEXTRA ) ) 332 { 333 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME, 334 (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) ) 335 { 336 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME, 337 (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) ) 338 pSalData->mbObjClassInit = TRUE; 339 } 340 } 341 } 342 343 if ( pSalData->mbObjClassInit ) 344 { 345 Os2SalObject* pObject = new Os2SalObject; 346 HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "", 347 0, 348 0, 0, 0, 0, 349 pParent->mhWndClient, HWND_TOP, 350 0, NULL, (void*)pObject ); 351 HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "", 352 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, 353 0, 0, 0, 0, 354 hWnd, HWND_TOP, 355 0, NULL, NULL ); 356 357 if ( !hWndChild ) 358 { 359 if ( hWnd ) 360 WinDestroyWindow( hWnd ); 361 delete pObject; 362 return NULL; 363 } 364 365 if ( hWnd ) 366 { 367 #if OSL_DEBUG_LEVEL>0 368 debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild); 369 debug_printf("ImplSalCreateObject hWnd %x\n", hWnd); 370 #endif 371 pObject->mhWnd = hWnd; 372 pObject->mhWndChild = hWndChild; 373 pObject->maSysData.hWnd = hWndChild; 374 return pObject; 375 } 376 } 377 378 return NULL; 379 } 380 381 // ======================================================================= 382 383 long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* ) 384 { 385 return 0; 386 } 387 388 // ======================================================================= 389 390 Os2SalObject::Os2SalObject() 391 { 392 SalData* pSalData = GetSalData(); 393 394 mhLastClipWnd = HWND_TOP; 395 396 mhWnd = 0; 397 mhWndChild = 0; 398 mhLastFocusWnd = 0; 399 maSysData.nSize = sizeof( SystemEnvData ); 400 mnHeight = 0; 401 mpInst = NULL; 402 mpProc = ImplSalObjCallbackDummy; 403 404 // Hook installieren, wenn es das erste Os2SalObject ist 405 if ( !pSalData->mpFirstObject ) 406 { 407 WinSetHook( pSalData->mhAB, pSalData->mhMQ, 408 HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); 409 } 410 411 // Insert object in objectlist 412 mpNextObject = pSalData->mpFirstObject; 413 pSalData->mpFirstObject = this; 414 } 415 416 // ----------------------------------------------------------------------- 417 418 Os2SalObject::~Os2SalObject() 419 { 420 SalData* pSalData = GetSalData(); 421 422 // remove frame from framelist 423 if ( this == pSalData->mpFirstObject ) 424 { 425 pSalData->mpFirstObject = mpNextObject; 426 427 // Wenn letztes Os2SalObject, dann Hook wieder entfernen 428 if ( !pSalData->mpFirstObject ) 429 { 430 WinReleaseHook( pSalData->mhAB, pSalData->mhMQ, 431 HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); 432 } 433 } 434 else 435 { 436 Os2SalObject* pTempObject = pSalData->mpFirstObject; 437 while ( pTempObject->mpNextObject != this ) 438 pTempObject = pTempObject->mpNextObject; 439 440 pTempObject->mpNextObject = mpNextObject; 441 } 442 443 // Cache-Daten zerstoeren 444 ImplDestroyAllClipWindows( mhLastClipWnd ); 445 446 if ( mhWndChild ) 447 WinDestroyWindow( mhWndChild ); 448 if ( mhWnd ) 449 WinDestroyWindow( mhWnd ); 450 } 451 452 // ----------------------------------------------------------------------- 453 454 void Os2SalObject::ResetClipRegion() 455 { 456 ImplDestroyAllClipWindows( mhLastClipWnd ); 457 mhLastClipWnd = HWND_TOP; 458 } 459 460 // ----------------------------------------------------------------------- 461 462 USHORT Os2SalObject::GetClipRegionType() 463 { 464 return SAL_OBJECT_CLIP_EXCLUDERECTS; 465 } 466 467 // ----------------------------------------------------------------------- 468 469 void Os2SalObject::BeginSetClipRegion( ULONG nRectCount ) 470 { 471 mhOldLastClipWnd = mhLastClipWnd; 472 } 473 474 // ----------------------------------------------------------------------- 475 476 void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 477 { 478 HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "", 479 WS_VISIBLE, 480 nX, mnHeight-(nY+nHeight), nWidth, nHeight, 481 mhWnd, mhLastClipWnd, 482 0, NULL, NULL ); 483 #if OSL_DEBUG_LEVEL>0 484 debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd); 485 #endif 486 mhLastClipWnd = hClipWnd; 487 } 488 489 // ----------------------------------------------------------------------- 490 491 void Os2SalObject::EndSetClipRegion() 492 { 493 ImplDestroyAllClipWindows( mhOldLastClipWnd ); 494 } 495 496 // ----------------------------------------------------------------------- 497 498 void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) 499 { 500 ULONG nStyle = 0; 501 sal_Bool bVisible = WinIsWindowVisible( mhWnd ); 502 if ( bVisible ) 503 { 504 WinShowWindow( mhWnd, FALSE ); 505 nStyle |= SWP_SHOW; 506 } 507 SWP aParentSWP; 508 WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP ); 509 WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight, 510 SWP_MOVE | SWP_SIZE | nStyle ); 511 } 512 513 // ----------------------------------------------------------------------- 514 515 void Os2SalObject::Show( sal_Bool bVisible ) 516 { 517 WinShowWindow( mhWnd, bVisible ); 518 } 519 520 // ----------------------------------------------------------------------- 521 522 void Os2SalObject::Enable( sal_Bool bEnable ) 523 { 524 // Im Gegensatz zu Windows disablen wir das Childfenster, 525 // da ansonsten unser Clippen nicht mehr funktioniert, da 526 // wir keine Events mehr bekommen. Dadurch kann sich evtl. 527 // das Fenster anders darstellen, was wir eigentlich nicht 528 // wollen. Aber da uns bisher kein Fall bekannt ist, 529 // ignorieren wir dies. Ansonsten muss ein Fenster dazwischen 530 // gezogen werden oder getestet werden, wie wir die 531 // Maustransparenz erreichen, wenn mhWnd 532 // disablte wird. 533 WinEnableWindow( mhWndChild, bEnable ); 534 } 535 536 // ----------------------------------------------------------------------- 537 538 void Os2SalObject::GrabFocus() 539 { 540 if ( mhLastFocusWnd && 541 WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) && 542 ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) ) 543 WinSetFocus( HWND_DESKTOP, mhLastFocusWnd ); 544 else 545 WinSetFocus( HWND_DESKTOP, mhWndChild ); 546 } 547 548 // ----------------------------------------------------------------------- 549 550 void Os2SalObject::SetBackground() 551 { 552 } 553 554 // ----------------------------------------------------------------------- 555 556 void Os2SalObject::SetBackground( SalColor nSalColor ) 557 { 558 } 559 560 // ----------------------------------------------------------------------- 561 562 const SystemChildData* Os2SalObject::GetSystemData() const 563 { 564 return &maSysData; 565 } 566 567 // ----------------------------------------------------------------------- 568 #if 0 569 void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc ) 570 { 571 mpInst = pInst; 572 if ( pProc ) 573 mpProc = pProc; 574 else 575 mpProc = ImplSalObjCallbackDummy; 576 } 577 #endif 578 579 // ----------------------------------------------------------------------- 580 581 void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ ) 582 { 583 } 584 585