blob: 207416e33dc5c6e736b233f7f315567140c10bf3 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include <svpm.h>
#include <string.h>
#include <tools/debug.hxx>
#include <tools/svwin.h>
#include "vcl/svapp.hxx"
#include "os2/saldata.hxx"
#include "os2/salinst.h"
#include "os2/salframe.h"
#include "os2/salobj.h"
// =======================================================================
static sal_Bool ImplIsSysWindowOrChild( HWND hWndParent, HWND hWndChild )
{
if ( hWndParent == hWndChild )
return TRUE;
HWND hTempWnd = WinQueryWindow( hWndChild, QW_PARENT );
while ( hTempWnd )
{
if ( hTempWnd == hWndParent )
return TRUE;
hTempWnd = WinQueryWindow( hTempWnd, QW_PARENT );
}
return FALSE;
}
// -----------------------------------------------------------------------
static Os2SalObject* ImplFindOs2SalObject( HWND hWndChild )
{
SalData* pSalData = GetSalData();
Os2SalObject* pObject = pSalData->mpFirstObject;
while ( pObject )
{
if ( ImplIsSysWindowOrChild( pObject->mhWndChild, hWndChild ) )
return pObject;
pObject = pObject->mpNextObject;
}
return NULL;
}
// =======================================================================
sal_Bool EXPENTRY SalSysMsgProc( HAB /* hAB */, QMSG* pMsg, ULONG /* fs */ )
{
if ( (pMsg->msg == WM_BUTTON1DOWN) ||
(pMsg->msg == WM_BUTTON2DOWN) ||
(pMsg->msg == WM_BUTTON3DOWN) )
{
SalData* pSalData = GetSalData();
Os2SalObject* pObject = ImplFindOs2SalObject( pMsg->hwnd );
if ( pObject )
WinPostMsg( pObject->mhWnd, SALOBJ_MSG_TOTOP, 0, 0 );
}
// Focus fangen wir hier nicht ab, da wir erstmal davon ausgehen,
// das unser Os2SalObject-Fenster immer eine WM_FOCUSCHANGE-Message
// bekommt.
return FALSE;
}
// -----------------------------------------------------------------------
MRESULT EXPENTRY SalSysObjWndProc( HWND hWnd, ULONG nMsg,
MPARAM nMP1, MPARAM nMP2 )
{
Os2SalObject* pSysObj;
MRESULT nRet = 0;
int bDef = TRUE;
#if OSL_DEBUG_LEVEL>0
debug_printf( "SalSysObjWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
#endif
switch( nMsg )
{
case WM_ERASEBACKGROUND:
nRet = (MRESULT)FALSE;
bDef = FALSE;
break;
case WM_PAINT:
{
HPS hPS;
RECTL aRect;
hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
WinEndPaint( hPS );
bDef = FALSE;
}
bDef = FALSE;
break;
case WM_BUTTON1DOWN:
case WM_BUTTON2DOWN:
case WM_BUTTON3DOWN:
case SALOBJ_MSG_TOTOP:
if ( ImplSalYieldMutexTryToAcquire() )
{
pSysObj = GetSalObjWindowPtr( hWnd );
pSysObj->mpProc( pSysObj->mpInst, pSysObj,
SALOBJ_EVENT_TOTOP, 0 );
ImplSalYieldMutexRelease();
}
else
WinPostMsg( hWnd, SALOBJ_MSG_TOTOP, 0, 0 );
break;
case WM_FOCUSCHANGE:
case SALOBJ_MSG_POSTFOCUS:
if ( ImplSalYieldMutexTryToAcquire() )
{
pSysObj = GetSalObjWindowPtr( hWnd );
if ( SHORT1FROMMP( nMP2 ) )
{
pSysObj->mhLastFocusWnd = WinQueryFocus( HWND_DESKTOP );
pSysObj->mpProc( pSysObj->mpInst, pSysObj,
SALOBJ_EVENT_GETFOCUS, 0 );
}
else
{
HWND hWndFocus = HWNDFROMMP( nMP1 );
if ( !hWndFocus || !ImplIsSysWindowOrChild( hWnd, hWndFocus ) )
{
pSysObj->mpProc( pSysObj->mpInst, pSysObj,
SALOBJ_EVENT_LOSEFOCUS, 0 );
}
}
ImplSalYieldMutexRelease();
}
else
WinPostMsg( hWnd, SALOBJ_MSG_POSTFOCUS, nMP1, nMP2 );
break;
case WM_SIZE:
{
pSysObj = GetSalObjWindowPtr( hWnd );
pSysObj->mnHeight = (short)SHORT2FROMMP( nMP2 );
WinSetWindowPos( pSysObj->mhWndChild, 0,
0, 0,
(short)SHORT1FROMMP( nMP2 ), (short)SHORT2FROMMP( nMP2 ),
SWP_SIZE | SWP_MOVE );
bDef = FALSE;
}
break;
case WM_CREATE:
{
// Window-Instanz am Windowhandle speichern
CREATESTRUCT* pStruct = (CREATESTRUCT*)nMP2;
pSysObj = (Os2SalObject*)pStruct->pPresParams;
SetSalObjWindowPtr( hWnd, pSysObj );
bDef = FALSE;
}
break;
}
if ( bDef )
nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
return nRet;
}
// -----------------------------------------------------------------------
MRESULT EXPENTRY SalSysObjChildWndProc( HWND hWnd, ULONG nMsg,
MPARAM nMP1, MPARAM nMP2 )
{
MRESULT nRet = 0;
int bDef = TRUE;
#if OSL_DEBUG_LEVEL>0
debug_printf( "SalSysObjChildWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
#endif
switch( nMsg )
{
case WM_ERASEBACKGROUND:
// Wegen PlugIn's loeschen wir erstmal den Hintergrund
/*
nRet = (MRESULT)FALSE;
bDef = FALSE;
*/
break;
case WM_PAINT:
{
HPS hPS;
RECTL aRect;
hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
WinEndPaint( hPS );
bDef = FALSE;
}
break;
}
if ( bDef )
nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
return nRet;
}
// -----------------------------------------------------------------------
MRESULT EXPENTRY SalSysObjClipWndProc( HWND hWnd, ULONG nMsg,
MPARAM nMP1, MPARAM nMP2 )
{
MRESULT nRet = 0;
int bDef = TRUE;
#if OSL_DEBUG_LEVEL>0
debug_printf( "SalSysObjClipWndProc hWnd 0x%x nMsg %d\n", hWnd, nMsg);
#endif
switch( nMsg )
{
case WM_MOUSEMOVE:
case WM_BUTTON1DOWN:
case WM_BUTTON2DOWN:
case WM_BUTTON3DOWN:
case WM_BUTTON1DBLCLK:
case WM_BUTTON2DBLCLK:
case WM_BUTTON3DBLCLK:
case WM_BUTTON1UP:
case WM_BUTTON2UP:
case WM_BUTTON3UP:
{
// Alle Events an den Frame weiterreichen, da diese Bereiche
// dem Frame gehoeren. Dazu muessen die Mouse-Koordinaaten
// entsprechend umgerechnet werden
HWND hWndParent = WinQueryWindow( hWnd, QW_PARENT ); // ergibt SysChild-Fenster
hWndParent = WinQueryWindow( hWndParent, QW_PARENT );
short nX = (short)SHORT1FROMMP( nMP1 );
short nY = (short)SHORT2FROMMP( nMP1 );
POINTL aPos;
aPos.x = nX;
aPos.y = nY;
WinMapWindowPoints( hWnd, hWndParent, &aPos, 1 );
nMP1 = MPFROM2SHORT( (short)aPos.x, (short)aPos.y );
bDef = FALSE;
nRet = WinSendMsg( hWndParent, nMsg, nMP1, nMP2 );
}
break;
case WM_HITTEST:
// Damit im disablten Zustand die MouseKlicks immer noch
// an den Frame geschickt werden
// Dieser Code reicht leider nicht aus, deshalb wir unter
// OS2 immer das Child-Fenster disablen, im Gegensatz
// zu Windows, wo immer der Parent disablte wird, da
// sich das Fenster evtl. anders Darstellen koennte,
// wenn es disablte wird. Da dieser Fall uns bisher
// nicht bekannt ist, ignorieren wir das.
nRet = HT_NORMAL;
bDef = FALSE;
break;
case WM_ERASEBACKGROUND:
nRet = (MRESULT)FALSE;
bDef = FALSE;
break;
case WM_PAINT:
{
HPS hPS;
RECTL aRect;
hPS = WinBeginPaint( hWnd, NULLHANDLE, &aRect );
WinEndPaint( hPS );
bDef = FALSE;
}
break;
}
if ( bDef )
nRet = WinDefWindowProc( hWnd, nMsg, nMP1, nMP2 );
return nRet;
}
// =======================================================================
void ImplDestroyAllClipWindows( HWND hWndLast )
{
if ( hWndLast == HWND_TOP )
return;
HWND hWndPrev;
while ( hWndLast )
{
hWndPrev = WinQueryWindow( hWndLast, QW_PREV );
WinDestroyWindow( hWndLast );
hWndLast = hWndPrev;
}
}
// =======================================================================
SalObject* ImplSalCreateObject( Os2SalInstance* pInst, Os2SalFrame* pParent )
{
SalData* pSalData = GetSalData();
if ( !pSalData->mbObjClassInit )
{
if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLASSNAME,
(PFNWP)SalSysObjWndProc, CS_MOVENOTIFY,
SAL_OBJECT_WNDEXTRA ) )
{
if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CLIPCLASSNAME,
(PFNWP)SalSysObjClipWndProc, CS_HITTEST | CS_MOVENOTIFY, 0 ) )
{
if ( WinRegisterClass( pSalData->mhAB, (PSZ)SAL_OBJECT_CHILDCLASSNAME,
(PFNWP)SalSysObjChildWndProc, CS_HITTEST | CS_MOVENOTIFY, 32 ) )
pSalData->mbObjClassInit = TRUE;
}
}
}
if ( pSalData->mbObjClassInit )
{
Os2SalObject* pObject = new Os2SalObject;
HWND hWnd = WinCreateWindow( pParent->mhWndClient, SAL_OBJECT_CLASSNAME, "",
0,
0, 0, 0, 0,
pParent->mhWndClient, HWND_TOP,
0, NULL, (void*)pObject );
HWND hWndChild = WinCreateWindow( hWnd, SAL_OBJECT_CHILDCLASSNAME, "",
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
0, 0, 0, 0,
hWnd, HWND_TOP,
0, NULL, NULL );
if ( !hWndChild )
{
if ( hWnd )
WinDestroyWindow( hWnd );
delete pObject;
return NULL;
}
if ( hWnd )
{
#if OSL_DEBUG_LEVEL>0
debug_printf("ImplSalCreateObject hWndChild %x\n", hWndChild);
debug_printf("ImplSalCreateObject hWnd %x\n", hWnd);
#endif
pObject->mhWnd = hWnd;
pObject->mhWndChild = hWndChild;
pObject->maSysData.hWnd = hWndChild;
return pObject;
}
}
return NULL;
}
// =======================================================================
long ImplSalObjCallbackDummy( void*, SalObject*, USHORT, const void* )
{
return 0;
}
// =======================================================================
Os2SalObject::Os2SalObject()
{
SalData* pSalData = GetSalData();
mhLastClipWnd = HWND_TOP;
mhWnd = 0;
mhWndChild = 0;
mhLastFocusWnd = 0;
maSysData.nSize = sizeof( SystemEnvData );
mnHeight = 0;
mpInst = NULL;
mpProc = ImplSalObjCallbackDummy;
// Hook installieren, wenn es das erste Os2SalObject ist
if ( !pSalData->mpFirstObject )
{
WinSetHook( pSalData->mhAB, pSalData->mhMQ,
HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
}
// Insert object in objectlist
mpNextObject = pSalData->mpFirstObject;
pSalData->mpFirstObject = this;
}
// -----------------------------------------------------------------------
Os2SalObject::~Os2SalObject()
{
SalData* pSalData = GetSalData();
// remove frame from framelist
if ( this == pSalData->mpFirstObject )
{
pSalData->mpFirstObject = mpNextObject;
// Wenn letztes Os2SalObject, dann Hook wieder entfernen
if ( !pSalData->mpFirstObject )
{
WinReleaseHook( pSalData->mhAB, pSalData->mhMQ,
HK_INPUT, (PFN)SalSysMsgProc, (HMODULE)0 );
}
}
else
{
Os2SalObject* pTempObject = pSalData->mpFirstObject;
while ( pTempObject->mpNextObject != this )
pTempObject = pTempObject->mpNextObject;
pTempObject->mpNextObject = mpNextObject;
}
// Cache-Daten zerstoeren
ImplDestroyAllClipWindows( mhLastClipWnd );
if ( mhWndChild )
WinDestroyWindow( mhWndChild );
if ( mhWnd )
WinDestroyWindow( mhWnd );
}
// -----------------------------------------------------------------------
void Os2SalObject::ResetClipRegion()
{
ImplDestroyAllClipWindows( mhLastClipWnd );
mhLastClipWnd = HWND_TOP;
}
// -----------------------------------------------------------------------
USHORT Os2SalObject::GetClipRegionType()
{
return SAL_OBJECT_CLIP_EXCLUDERECTS;
}
// -----------------------------------------------------------------------
void Os2SalObject::BeginSetClipRegion( ULONG nRectCount )
{
mhOldLastClipWnd = mhLastClipWnd;
}
// -----------------------------------------------------------------------
void Os2SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
HWND hClipWnd = WinCreateWindow( mhWnd, SAL_OBJECT_CLIPCLASSNAME, "",
WS_VISIBLE,
nX, mnHeight-(nY+nHeight), nWidth, nHeight,
mhWnd, mhLastClipWnd,
0, NULL, NULL );
#if OSL_DEBUG_LEVEL>0
debug_printf("Os2SalObject::UnionClipRegion hClipWnd %x\n", hClipWnd);
#endif
mhLastClipWnd = hClipWnd;
}
// -----------------------------------------------------------------------
void Os2SalObject::EndSetClipRegion()
{
ImplDestroyAllClipWindows( mhOldLastClipWnd );
}
// -----------------------------------------------------------------------
void Os2SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
ULONG nStyle = 0;
sal_Bool bVisible = WinIsWindowVisible( mhWnd );
if ( bVisible )
{
WinShowWindow( mhWnd, FALSE );
nStyle |= SWP_SHOW;
}
SWP aParentSWP;
WinQueryWindowPos( WinQueryWindow( mhWnd, QW_PARENT ), &aParentSWP );
WinSetWindowPos( mhWnd, 0, nX, aParentSWP.cy-(nY+nHeight), nWidth, nHeight,
SWP_MOVE | SWP_SIZE | nStyle );
}
// -----------------------------------------------------------------------
void Os2SalObject::Show( sal_Bool bVisible )
{
WinShowWindow( mhWnd, bVisible );
}
// -----------------------------------------------------------------------
void Os2SalObject::Enable( sal_Bool bEnable )
{
// Im Gegensatz zu Windows disablen wir das Childfenster,
// da ansonsten unser Clippen nicht mehr funktioniert, da
// wir keine Events mehr bekommen. Dadurch kann sich evtl.
// das Fenster anders darstellen, was wir eigentlich nicht
// wollen. Aber da uns bisher kein Fall bekannt ist,
// ignorieren wir dies. Ansonsten muss ein Fenster dazwischen
// gezogen werden oder getestet werden, wie wir die
// Maustransparenz erreichen, wenn mhWnd
// disablte wird.
WinEnableWindow( mhWndChild, bEnable );
}
// -----------------------------------------------------------------------
void Os2SalObject::GrabFocus()
{
if ( mhLastFocusWnd &&
WinIsWindow( GetSalData()->mhAB, mhLastFocusWnd ) &&
ImplIsSysWindowOrChild( mhWndChild, mhLastFocusWnd ) )
WinSetFocus( HWND_DESKTOP, mhLastFocusWnd );
else
WinSetFocus( HWND_DESKTOP, mhWndChild );
}
// -----------------------------------------------------------------------
void Os2SalObject::SetBackground()
{
}
// -----------------------------------------------------------------------
void Os2SalObject::SetBackground( SalColor nSalColor )
{
}
// -----------------------------------------------------------------------
const SystemChildData* Os2SalObject::GetSystemData() const
{
return &maSysData;
}
// -----------------------------------------------------------------------
#if 0
void Os2SalObject::SetCallback( void* pInst, SALOBJECTPROC pProc )
{
mpInst = pInst;
if ( pProc )
mpProc = pProc;
else
mpProc = ImplSalObjCallbackDummy;
}
#endif
// -----------------------------------------------------------------------
void Os2SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
{
}