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