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 debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); 202 203 switch( nMsg ) 204 { 205 case WM_ERASEBACKGROUND: 206 // Wegen PlugIn's loeschen wir erstmal den Hintergrund 207 /* 208 nRet = (MRESULT)FALSE; 209 bDef = FALSE; 210 */ 211 break; 212 case WM_PAINT: 213 { 214 HPS hPS; 215 RECTL aRect; 216 hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); 217 WinEndPaint( hPS ); 218 bDef = FALSE; 219 } 220 break; 221 } 222 223 if ( bDef ) 224 nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); 225 return nRet; 226 } 227 228 // ----------------------------------------------------------------------- 229 230 MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg, 231 MPARAM nMP1, MPARAM nMP2 ) 232 { 233 MRESULT nRet = 0; 234 int bDef = TRUE; 235 236 debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg); 237 238 switch( nMsg ) 239 { 240 case WM_MOUSEMOVE: 241 case WM_BUTTON1DOWN: 242 case WM_BUTTON2DOWN: 243 case WM_BUTTON3DOWN: 244 case WM_BUTTON1DBLCLK: 245 case WM_BUTTON2DBLCLK: 246 case WM_BUTTON3DBLCLK: 247 case WM_BUTTON1UP: 248 case WM_BUTTON2UP: 249 case WM_BUTTON3UP: 250 { 251 // Alle Events an den Frame weiterreichen, da diese Bereiche 252 // dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten 253 // entsprechend umgerechnet werden 254 HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster 255 hWndParent = WinQueryWindow( hWndParent, QW_PARENT ); 256 short nX = (short)SHORT1FROMMP( nMP1 ); 257 short nY = (short)SHORT2FROMMP( nMP1 ); 258 POINTL aPos; 259 aPos.x = nX; 260 aPos.y = nY; 261 WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 ); 262 nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y ); 263 bDef = FALSE; 264 nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 ); 265 } 266 break; 267 268 case WM_HITTEST: 269 // Damit im disablten Zustand die MouseKlicks immer noch 270 // an den Frame geschickt werden 271 // Dieser Code reicht leider nicht aus, deshalb wir unter 272 // OS2 immer das Child-Fenster disablen, im Gegensatz 273 // zu Windows, wo immer der Parent disablte wird, da 274 // sich das Fenster evtl. anders Darstellen koennte, 275 // wenn es disablte wird. Da dieser Fall uns bisher 276 // nicht bekannt ist, ignorieren wir das. 277 nRet = HT_NORMAL; 278 bDef = FALSE; 279 break; 280 281 case WM_ERASEBACKGROUND: 282 nRet = (MRESULT)FALSE; 283 bDef = FALSE; 284 break; 285 case WM_PAINT: 286 { 287 HPS hPS; 288 RECTL aRect; 289 hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect ); 290 WinEndPaint( hPS ); 291 bDef = FALSE; 292 } 293 break; 294 } 295 296 if ( bDef ) 297 nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 ); 298 return nRet; 299 } 300 301 // ======================================================================= 302 303 void ImplDestroyAllClipWindows( HWND hWndLast ) 304 { 305 if ( hWndLast == HWND_TOP ) 306 return; 307 308 HWND hWndPrev; 309 while ( hWndLast ) 310 { 311 hWndPrev = WinQueryWindow( hWndLast, QW_PREV ); 312 WinDestroyWindow( hWndLast ); 313 hWndLast = hWndPrev; 314 } 315 } 316 317 // ======================================================================= 318 319 SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent ) 320 { 321 SalData* pSalData = GetSalData(); 322 323 if ( !pSalData->mbObjClassInit ) 324 { 325 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME, 326 (PFNWP)SalSysObjWndProc, CS_MOVENOTIFY, 327 SAL_OBJECT_WNDEXTRA ) ) 328 { 329 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME, 330 (PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) ) 331 { 332 if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME, 333 (PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) ) 334 pSalData->mbObjClassInit = TRUE; 335 } 336 } 337 } 338 339 if ( pSalData->mbObjClassInit ) 340 { 341 Os2SalObject* pObject = new Os2SalObject; 342 HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "", 343 0, 344 0, 0, 0, 0, 345 pParent->mhWndClient, HWND_TOP, 346 0, NULL, (void*)pObject ); 347 HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "", 348 WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE, 349 0, 0, 0, 0, 350 hWnd, HWND_TOP, 351 0, NULL, NULL ); 352 353 if ( !hWndChild ) 354 { 355 if ( hWnd ) 356 WinDestroyWindow( hWnd ); 357 delete pObject; 358 return NULL; 359 } 360 361 if ( hWnd ) 362 { 363 debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild); 364 debug_printf("ImplSalCreateObject hWnd %x\n", hWnd); 365 pObject->mhWnd = hWnd; 366 pObject->mhWndChild = hWndChild; 367 pObject->maSysData.hWnd = hWndChild; 368 return pObject; 369 } 370 } 371 372 return NULL; 373 } 374 375 // ======================================================================= 376 377 long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* ) 378 { 379 return 0; 380 } 381 382 // ======================================================================= 383 384 Os2SalObject::Os2SalObject() 385 { 386 SalData* pSalData = GetSalData(); 387 388 mhLastClipWnd = HWND_TOP; 389 390 mhWnd = 0; 391 mhWndChild = 0; 392 mhLastFocusWnd = 0; 393 maSysData.nSize = sizeof( SystemEnvData ); 394 mnHeight = 0; 395 mpInst = NULL; 396 mpProc = ImplSalObjCallbackDummy; 397 398 // Hook installieren, wenn es das erste Os2SalObject ist 399 if ( !pSalData->mpFirstObject ) 400 { 401 WinSetHook( pSalData->mhAB, pSalData->mhMQ, 402 HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); 403 } 404 405 // Insert object in objectlist 406 mpNextObject = pSalData->mpFirstObject; 407 pSalData->mpFirstObject = this; 408 } 409 410 // ----------------------------------------------------------------------- 411 412 Os2SalObject::~Os2SalObject() 413 { 414 SalData* pSalData = GetSalData(); 415 416 // remove frame from framelist 417 if ( this == pSalData->mpFirstObject ) 418 { 419 pSalData->mpFirstObject = mpNextObject; 420 421 // Wenn letztes Os2SalObject, dann Hook wieder entfernen 422 if ( !pSalData->mpFirstObject ) 423 { 424 WinReleaseHook( pSalData->mhAB, pSalData->mhMQ, 425 HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 ); 426 } 427 } 428 else 429 { 430 Os2SalObject* pTempObject = pSalData->mpFirstObject; 431 while ( pTempObject->mpNextObject != this ) 432 pTempObject = pTempObject->mpNextObject; 433 434 pTempObject->mpNextObject = mpNextObject; 435 } 436 437 // Cache-Daten zerstoeren 438 ImplDestroyAllClipWindows( mhLastClipWnd ); 439 440 if ( mhWndChild ) 441 WinDestroyWindow( mhWndChild ); 442 if ( mhWnd ) 443 WinDestroyWindow( mhWnd ); 444 } 445 446 // ----------------------------------------------------------------------- 447 448 void Os2SalObject::ResetClipRegion() 449 { 450 ImplDestroyAllClipWindows( mhLastClipWnd ); 451 mhLastClipWnd = HWND_TOP; 452 } 453 454 // ----------------------------------------------------------------------- 455 456 USHORT Os2SalObject::GetClipRegionType() 457 { 458 return SAL_OBJECT_CLIP_EXCLUDERECTS; 459 } 460 461 // ----------------------------------------------------------------------- 462 463 void Os2SalObject::BeginSetClipRegion( ULONG nRectCount ) 464 { 465 mhOldLastClipWnd = mhLastClipWnd; 466 } 467 468 // ----------------------------------------------------------------------- 469 470 void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 471 { 472 HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "", 473 WS_VISIBLE, 474 nX, mnHeight-(nY+nHeight), nWidth, nHeight, 475 mhWnd, mhLastClipWnd, 476 0, NULL, NULL ); 477 debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd); 478 mhLastClipWnd = hClipWnd; 479 } 480 481 // ----------------------------------------------------------------------- 482 483 void Os2SalObject::EndSetClipRegion() 484 { 485 ImplDestroyAllClipWindows( mhOldLastClipWnd ); 486 } 487 488 // ----------------------------------------------------------------------- 489 490 void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) 491 { 492 ULONG nStyle = 0; 493 sal_Bool bVisible = WinIsWindowVisible( mhWnd ); 494 if ( bVisible ) 495 { 496 WinShowWindow( mhWnd, FALSE ); 497 nStyle |= SWP_SHOW; 498 } 499 SWP aParentSWP; 500 WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP ); 501 WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight, 502 SWP_MOVE | SWP_SIZE | nStyle ); 503 } 504 505 // ----------------------------------------------------------------------- 506 507 void Os2SalObject::Show( sal_Bool bVisible ) 508 { 509 WinShowWindow( mhWnd, bVisible ); 510 } 511 512 // ----------------------------------------------------------------------- 513 514 void Os2SalObject::Enable( sal_Bool bEnable ) 515 { 516 // Im Gegensatz zu Windows disablen wir das Childfenster, 517 // da ansonsten unser Clippen nicht mehr funktioniert, da 518 // wir keine Events mehr bekommen. Dadurch kann sich evtl. 519 // das Fenster anders darstellen, was wir eigentlich nicht 520 // wollen. Aber da uns bisher kein Fall bekannt ist, 521 // ignorieren wir dies. Ansonsten muss ein Fenster dazwischen 522 // gezogen werden oder getestet werden, wie wir die 523 // Maustransparenz erreichen, wenn mhWnd 524 // disablte wird. 525 WinEnableWindow( mhWndChild, bEnable ); 526 } 527 528 // ----------------------------------------------------------------------- 529 530 void Os2SalObject::GrabFocus() 531 { 532 if ( mhLastFocusWnd && 533 WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) && 534 ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) ) 535 WinSetFocus( HWND_DESKTOP, mhLastFocusWnd ); 536 else 537 WinSetFocus( HWND_DESKTOP, mhWndChild ); 538 } 539 540 // ----------------------------------------------------------------------- 541 542 void Os2SalObject::SetBackground() 543 { 544 } 545 546 // ----------------------------------------------------------------------- 547 548 void Os2SalObject::SetBackground( SalColor nSalColor ) 549 { 550 } 551 552 // ----------------------------------------------------------------------- 553 554 const SystemChildData* Os2SalObject::GetSystemData() const 555 { 556 return &maSysData; 557 } 558 559 // ----------------------------------------------------------------------- 560 #if 0 561 void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc ) 562 { 563 mpInst = pInst; 564 if ( pProc ) 565 mpProc = pProc; 566 else 567 mpProc = ImplSalObjCallbackDummy; 568 } 569 #endif 570 571 // ----------------------------------------------------------------------- 572 573 void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ ) 574 { 575 } 576 577