blob: 380eb56f640cff864320f6c4bf676f9a2951ebab [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.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#if OSL_DEBUG_LEVEL > 1
#include <stdio.h>
#endif
#include <tools/debug.hxx>
#include <vcl/keycodes.hxx>
#include <tools/prex.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>
#include <tools/postx.h>
#include <unx/salunx.h>
#include <unx/salstd.hxx>
#include <unx/saldata.hxx>
#include <unx/salinst.h>
#include <unx/saldisp.hxx>
#include <unx/salframe.h>
#include <unx/salobj.h>
#include <salwtype.hxx>
// =======================================================================
// SalInstance member to create and destroy a SalObject
SalObject* X11SalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow )
{
return X11SalObject::CreateObject( pParent, pWindowData, bShow );
}
X11SalObject* X11SalObject::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow )
{
int error_base, event_base;
X11SalObject* pObject = new X11SalObject();
SystemChildData* pObjData = const_cast<SystemChildData*>(pObject->GetSystemData());
if ( ! XShapeQueryExtension( (Display*)pObjData->pDisplay,
&event_base, &error_base ) )
{
delete pObject;
return NULL;
}
pObject->mpParent = pParent;
SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
const SystemEnvData* pEnv = pParent->GetSystemData();
Display* pDisp = pSalDisp->GetDisplay();
XLIB_Window aObjectParent = (XLIB_Window)pEnv->aWindow;
// find out on which screen that window is
XWindowAttributes aParentAttr;
XGetWindowAttributes( pDisp, aObjectParent, &aParentAttr );
int nScreen = XScreenNumberOfScreen( aParentAttr.screen );
Visual* pVisual = (pWindowData && pWindowData->pVisual) ?
(Visual*)pWindowData->pVisual :
pSalDisp->GetVisual( nScreen ).GetVisual();
// get visual info
VisualID aVisID = XVisualIDFromVisual( pVisual );
XVisualInfo aTemplate;
aTemplate.visualid = aVisID;
int nVisuals = 0;
XVisualInfo* pInfos = XGetVisualInfo( pDisp, VisualIDMask, &aTemplate, &nVisuals );
// only one VisualInfo structure can match the visual id
DBG_ASSERT( nVisuals == 1, "match count for visual id is not 1" );
unsigned int nDepth = pInfos->depth;
XFree( pInfos );
XSetWindowAttributes aAttribs;
aAttribs.event_mask = StructureNotifyMask
| ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
| EnterWindowMask
| LeaveWindowMask
| FocusChangeMask
| ExposureMask
;
pObject->maPrimary =
XCreateSimpleWindow( pDisp,
aObjectParent,
0, 0,
1, 1, 0,
pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
pSalDisp->GetColormap( nScreen ).GetWhitePixel()
);
if( aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() )
{
pObject->maSecondary =
XCreateSimpleWindow( pDisp,
pObject->maPrimary,
0, 0,
1, 1, 0,
pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
pSalDisp->GetColormap( nScreen ).GetWhitePixel()
);
}
else
{
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "visual id of vcl %x, of visual %x\n",
static_cast<unsigned int> (pSalDisp->GetVisual( nScreen ).GetVisualId()),
static_cast<unsigned int> (aVisID) );
#endif
pSalDisp->GetXLib()->PushXErrorLevel( true );
// create colormap for visual - there might not be one
pObject->maColormap = aAttribs.colormap = XCreateColormap(
pDisp,
pSalDisp->GetRootWindow( nScreen ),
pVisual,
AllocNone );
pObject->maSecondary =
XCreateWindow( pDisp,
pSalDisp->GetRootWindow( nScreen ),
0, 0,
1, 1, 0,
nDepth, InputOutput,
pVisual,
CWEventMask|CWColormap, &aAttribs );
XSync( pDisp, False );
sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
pSalDisp->GetXLib()->PopXErrorLevel();
if( bWasXError )
{
pObject->maSecondary = None;
delete pObject;
return NULL;
}
XReparentWindow( pDisp, pObject->maSecondary, pObject->maPrimary, 0, 0 );
}
pSalDisp->GetXLib()->PushXErrorLevel( true );
if( bShow ) {
XMapWindow( pDisp, pObject->maSecondary );
XMapWindow( pDisp, pObject->maPrimary );
}
pObjData->pDisplay = pDisp;
pObjData->aWindow = pObject->maSecondary;
pObjData->pWidget = NULL;
pObjData->pVisual = pVisual;
pObjData->nDepth = nDepth;
pObjData->aColormap = aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() ?
pSalDisp->GetColormap( nScreen ).GetXColormap() : None;
pObjData->pAppContext = NULL;
XSync(pDisp, False);
sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
pSalDisp->GetXLib()->PopXErrorLevel();
if( bWasXError )
{
delete pObject;
return NULL;
}
return pObject;
}
void X11SalInstance::DestroyObject( SalObject* pObject )
{
delete pObject;
}
// ======================================================================
// SalClipRegion is a member of SalObject
// definition of SalClipRegion my be found in unx/inc/salobj.h
SalClipRegion::SalClipRegion()
{
ClipRectangleList = NULL;
numClipRectangles = 0;
maxClipRectangles = 0;
nClipRegionType = SAL_OBJECT_CLIP_INCLUDERECTS;
}
SalClipRegion::~SalClipRegion()
{
if ( ClipRectangleList )
delete [] ClipRectangleList;
}
void
SalClipRegion::BeginSetClipRegion( sal_uLong nRects )
{
if (ClipRectangleList)
delete [] ClipRectangleList;
ClipRectangleList = new XRectangle[nRects];
numClipRectangles = 0;
maxClipRectangles = nRects;
}
void
SalClipRegion::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
if ( nWidth && nHeight && (numClipRectangles < maxClipRectangles) )
{
XRectangle *aRect = ClipRectangleList + numClipRectangles;
aRect->x = (short) nX;
aRect->y = (short) nY;
aRect->width = (unsigned short) nWidth;
aRect->height= (unsigned short) nHeight;
numClipRectangles++;
}
}
// =======================================================================
// SalObject Implementation
X11SalObject::X11SalObject()
{
maSystemChildData.nSize = sizeof( SystemChildData );
maSystemChildData.pDisplay = GetX11SalData()->GetDisplay()->GetDisplay();
maSystemChildData.aWindow = None;
maSystemChildData.pSalFrame = 0;
maSystemChildData.pWidget = 0;
maSystemChildData.pVisual = 0;
maSystemChildData.nDepth = 0;
maSystemChildData.aColormap = 0;
maSystemChildData.pAppContext = NULL;
maSystemChildData.aShellWindow = 0;
maSystemChildData.pShellWidget = NULL;
maPrimary = 0;
maSecondary = 0;
maColormap = 0;
std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
rObjects.push_back( this );
}
X11SalObject::~X11SalObject()
{
std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
rObjects.remove( this );
SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
pSalDisp->GetXLib()->PushXErrorLevel( true );
if ( maSecondary )
XDestroyWindow( (Display*)maSystemChildData.pDisplay, maSecondary );
if ( maPrimary )
XDestroyWindow( (Display*)maSystemChildData.pDisplay, maPrimary );
if ( maColormap )
XFreeColormap((Display*)maSystemChildData.pDisplay, maColormap);
XSync( (Display*)maSystemChildData.pDisplay, False );
pSalDisp->GetXLib()->PopXErrorLevel();
}
void
X11SalObject::ResetClipRegion()
{
maClipRegion.ResetClipRegion();
const int dest_kind = ShapeBounding;
const int op = ShapeSet;
const int ordering = YSorted;
XWindowAttributes win_attrib;
XRectangle win_size;
XLIB_Window aShapeWindow = maPrimary;
XGetWindowAttributes ( (Display*)maSystemChildData.pDisplay,
aShapeWindow,
&win_attrib );
win_size.x = 0;
win_size.y = 0;
win_size.width = win_attrib.width;
win_size.height = win_attrib.height;
XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
aShapeWindow,
dest_kind,
0, 0, // x_off, y_off
&win_size, // list of rectangles
1, // number of rectangles
op, ordering );
}
void
X11SalObject::BeginSetClipRegion( sal_uLong nRectCount )
{
maClipRegion.BeginSetClipRegion ( nRectCount );
}
void
X11SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
{
maClipRegion.UnionClipRegion ( nX, nY, nWidth, nHeight );
}
void
X11SalObject::EndSetClipRegion()
{
XRectangle *pRectangles = maClipRegion.EndSetClipRegion ();
const int nType = maClipRegion.GetClipRegionType();
const int nRectangles = maClipRegion.GetRectangleCount();
const int dest_kind = ShapeBounding;
const int ordering = YSorted;
int op;
switch ( nType )
{
case SAL_OBJECT_CLIP_INCLUDERECTS :
op = ShapeSet;
break;
case SAL_OBJECT_CLIP_EXCLUDERECTS :
op = ShapeSubtract;
break;
case SAL_OBJECT_CLIP_ABSOLUTE :
op = ShapeSet;
break;
default :
op = ShapeUnion;
}
XLIB_Window aShapeWindow = maPrimary;
XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
aShapeWindow,
dest_kind,
0, 0, // x_off, y_off
pRectangles,
nRectangles,
op, ordering );
}
sal_uInt16
X11SalObject::GetClipRegionType()
{
return maClipRegion.GetClipRegionType();
}
// -----------------------------------------------------------------------
void
X11SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
{
if ( maPrimary && maSecondary && nWidth && nHeight )
{
XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
maPrimary,
nX, nY, nWidth, nHeight );
XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
maSecondary,
0, 0, nWidth, nHeight );
}
}
void
X11SalObject::Show( sal_Bool bVisible )
{
if ( ! maSystemChildData.aWindow )
return;
if ( bVisible ) {
XMapWindow( (Display*)maSystemChildData.pDisplay,
maSecondary );
XMapWindow( (Display*)maSystemChildData.pDisplay,
maPrimary );
} else {
XUnmapWindow( (Display*)maSystemChildData.pDisplay,
maPrimary );
XUnmapWindow( (Display*)maSystemChildData.pDisplay,
maSecondary );
}
mbVisible = bVisible;
}
// -----------------------------------------------------------------------
void X11SalObject::Enable( sal_Bool )
{
}
// -----------------------------------------------------------------------
void X11SalObject::GrabFocus()
{
if( mbVisible )
XSetInputFocus( (Display*)maSystemChildData.pDisplay,
maSystemChildData.aWindow,
RevertToNone,
CurrentTime );
}
// -----------------------------------------------------------------------
void X11SalObject::SetBackground()
{
}
// -----------------------------------------------------------------------
void X11SalObject::SetBackground( SalColor )
{
}
// -----------------------------------------------------------------------
const SystemChildData* X11SalObject::GetSystemData() const
{
return &maSystemChildData;
}
static sal_uInt16 sal_GetCode( int state )
{
sal_uInt16 nCode = 0;
if( state & Button1Mask )
nCode |= MOUSE_LEFT;
if( state & Button2Mask )
nCode |= MOUSE_MIDDLE;
if( state & Button3Mask )
nCode |= MOUSE_RIGHT;
if( state & ShiftMask )
nCode |= KEY_SHIFT;
if( state & ControlMask )
nCode |= KEY_MOD1;
if( state & Mod1Mask )
nCode |= KEY_MOD2;
if( state & Mod3Mask )
nCode |= KEY_MOD3;
return nCode;
}
long X11SalObject::Dispatch( XEvent* pEvent )
{
std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
for( std::list< SalObject* >::iterator it = rObjects.begin(); it != rObjects.end(); ++it )
{
X11SalObject* pObject = static_cast<X11SalObject*>(*it);
if( pEvent->xany.window == pObject->maPrimary ||
pEvent->xany.window == pObject->maSecondary )
{
if( pObject->IsMouseTransparent() && (
pEvent->type == ButtonPress ||
pEvent->type == ButtonRelease ||
pEvent->type == EnterNotify ||
pEvent->type == LeaveNotify ||
pEvent->type == MotionNotify
)
)
{
SalMouseEvent aEvt;
const SystemEnvData* pParentData = pObject->mpParent->GetSystemData();
int dest_x, dest_y;
XLIB_Window aChild = None;
XTranslateCoordinates( pEvent->xbutton.display,
pEvent->xbutton.root,
pParentData->aWindow,
pEvent->xbutton.x_root,
pEvent->xbutton.y_root,
&dest_x, &dest_y,
&aChild );
aEvt.mnX = dest_x;
aEvt.mnY = dest_y;
aEvt.mnTime = pEvent->xbutton.time;
aEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
aEvt.mnButton = 0;
sal_uInt16 nEvent = 0;
if( pEvent->type == ButtonPress ||
pEvent->type == ButtonRelease )
{
switch( pEvent->xbutton.button )
{
case Button1: aEvt.mnButton = MOUSE_LEFT;break;
case Button2: aEvt.mnButton = MOUSE_MIDDLE;break;
case Button3: aEvt.mnButton = MOUSE_RIGHT;break;
}
nEvent = (pEvent->type == ButtonPress) ?
SALEVENT_MOUSEBUTTONDOWN :
SALEVENT_MOUSEBUTTONUP;
}
else if( pEvent->type == EnterNotify )
nEvent = SALEVENT_MOUSELEAVE;
else
nEvent = SALEVENT_MOUSEMOVE;
pObject->mpParent->CallCallback( nEvent, &aEvt );
}
else
{
switch( pEvent->type )
{
case UnmapNotify:
pObject->mbVisible = sal_False;
return 1;
case MapNotify:
pObject->mbVisible = sal_True;
return 1;
case ButtonPress:
pObject->CallCallback( SALOBJ_EVENT_TOTOP, NULL );
return 1;
case FocusIn:
pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, NULL );
return 1;
case FocusOut:
pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, NULL );
return 1;
default: break;
}
}
return 0;
}
}
return 0;
}
// -----------------------------------------------------------------------
void X11SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
{
}