summaryrefslogtreecommitdiff
path: root/vcl/unx/generic/window/salobj.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/generic/window/salobj.cxx')
-rw-r--r--vcl/unx/generic/window/salobj.cxx569
1 files changed, 569 insertions, 0 deletions
diff --git a/vcl/unx/generic/window/salobj.cxx b/vcl/unx/generic/window/salobj.cxx
new file mode 100644
index 000000000000..0164d27ba185
--- /dev/null
+++ b/vcl/unx/generic/window/salobj.cxx
@@ -0,0 +1,569 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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()->HasXErrorOccurred();
+ 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()->HasXErrorOccurred();
+ 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*/ )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */