diff options
Diffstat (limited to 'vcl/unx/source/window')
-rw-r--r-- | vcl/unx/source/window/FWS.cxx | 280 | ||||
-rw-r--r-- | vcl/unx/source/window/FWS.hxx | 64 | ||||
-rw-r--r-- | vcl/unx/source/window/makefile.mk | 59 | ||||
-rw-r--r-- | vcl/unx/source/window/salframe.cxx | 4518 | ||||
-rw-r--r-- | vcl/unx/source/window/salobj.cxx | 568 |
5 files changed, 5489 insertions, 0 deletions
diff --git a/vcl/unx/source/window/FWS.cxx b/vcl/unx/source/window/FWS.cxx new file mode 100644 index 000000000000..4683864fd116 --- /dev/null +++ b/vcl/unx/source/window/FWS.cxx @@ -0,0 +1,280 @@ +/************************************************************************* + * + * 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" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include "FWS.hxx" + +static Atom fwsIconAtom; + +static Atom FWS_CLIENT; +static Atom FWS_COMM_WINDOW; +static Atom FWS_PROTOCOLS; +static Atom FWS_STACK_UNDER; +static Atom FWS_PARK_ICONS; +static Atom FWS_PASS_ALL_INPUT; +static Atom FWS_PASSES_INPUT; +static Atom FWS_HANDLES_FOCUS; + +static Atom FWS_REGISTER_WINDOW; +static Atom FWS_STATE_CHANGE; +static Atom FWS_UNSEEN_STATE; +static Atom FWS_NORMAL_STATE; +static Atom WM_PROTOCOLS; +static Atom WM_CHANGE_STATE; + +static Bool fwsStackUnder; +static Bool fwsParkIcons; +static Bool fwsPassesInput; +static Bool fwsHandlesFocus; + +static Window fwsCommWindow; + +/*************************************<->*********************************** + * + * WMSupportsFWS() - + * + * Initialize our atoms and determine if the current window manager is + * providing FWS extension support. + * + *************************************<->***********************************/ + +Bool +WMSupportsFWS (Display *display, int screen) +{ + unsigned int i; + Atom protocol; + Atom propType; + int propFormat; + unsigned long propItems; + unsigned long propBytesAfter; + unsigned char *propData; + char propName[64]; + + FWS_CLIENT = XInternAtom(display, "_SUN_FWS_CLIENT", False); + FWS_COMM_WINDOW = XInternAtom(display, "_SUN_FWS_COMM_WINDOW", False); + FWS_PROTOCOLS = XInternAtom(display, "_SUN_FWS_PROTOCOLS", False); + FWS_STACK_UNDER = XInternAtom(display, "_SUN_FWS_STACK_UNDER", False); + FWS_PARK_ICONS = XInternAtom(display, "_SUN_FWS_PARK_ICONS", False); + FWS_PASS_ALL_INPUT = XInternAtom(display, "_SUN_FWS_PASS_ALL_INPUT", False); + FWS_PASSES_INPUT = XInternAtom(display, "_SUN_FWS_PASSES_INPUT", False); + FWS_HANDLES_FOCUS = XInternAtom(display, "_SUN_FWS_HANDLES_FOCUS", False); + FWS_REGISTER_WINDOW= XInternAtom(display, "_SUN_FWS_REGISTER_WINDOW",False); + FWS_STATE_CHANGE = XInternAtom(display, "_SUN_FWS_STATE_CHANGE", False); + FWS_UNSEEN_STATE = XInternAtom(display, "_SUN_FWS_UNSEEN_STATE", False); + FWS_NORMAL_STATE = XInternAtom(display, "_SUN_FWS_NORMAL_STATE", False); + WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", False); + WM_CHANGE_STATE = XInternAtom(display, "WM_CHANGE_STATE", False); + + snprintf (propName, sizeof(propName), "_SUN_FWS_NEXT_ICON_%d", screen); + fwsIconAtom = XInternAtom(display, propName, False); + + if (XGetWindowProperty (display, DefaultRootWindow (display), + FWS_COMM_WINDOW, 0, 1, + False, AnyPropertyType, &propType, + &propFormat, &propItems, + &propBytesAfter, &propData) != Success) + return False; + + if (propFormat != 32 || + propItems != 1 || + propBytesAfter != 0) + { + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Bad FWS_COMM_WINDOW property on root window.\n"); + #endif + XFree (propData); + return False; + } + + fwsCommWindow = *(Window *) propData; + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Using fwsCommWindow = 0x%lx.\n", fwsCommWindow); + #endif + XFree (propData); + + + if (XGetWindowProperty (display, DefaultRootWindow (display), + FWS_PROTOCOLS, 0, 10, + False, AnyPropertyType, &propType, + &propFormat, &propItems, + &propBytesAfter, &propData) != Success) + { + return False; + } + + if (propFormat != 32 || + propBytesAfter != 0) + { + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Bad FWS_PROTOCOLS property on root window.\n"); + #endif + XFree (propData); + return False; + } + + for (i = 0; i < propItems; ++i) + { + protocol = ((Atom *) propData)[i]; + if (protocol == FWS_STACK_UNDER) + { + fwsStackUnder = True; + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Using fwsStackUnder.\n"); + #endif + } + else + if (protocol == FWS_PARK_ICONS) + { + fwsParkIcons = True; + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Using fwsParkIcons.\n"); + #endif + } + else + if (protocol == FWS_PASSES_INPUT) + { + fwsPassesInput = True; + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Using fwsPassesInput.\n"); + #endif + } + else + if (protocol == FWS_HANDLES_FOCUS) + { + fwsHandlesFocus = True; + #if OSL_DEBUG_LEVEL > 1 + fprintf (stderr, "Using fwsHandlesFocus.\n"); + #endif + } + } + + XFree (propData); + return True; +} + +/*************************************<->*********************************** + * + * newHandler() - + * + * Handle X errors (temporarily) to record the occurance of BadWindow + * errors without crashing. Used to detect the FWS_COMM_WINDOW root window + * property containing an old or obsolete window id. + * + *************************************<->***********************************/ + +extern "C" { + +static Bool badWindowFound; +static int (* oldHandler) (Display *, XErrorEvent *); + +static int +newHandler (Display *display, XErrorEvent *xerror) +{ + if (xerror->error_code != BadWindow) + (*oldHandler)(display, xerror); + else + badWindowFound = True; + + return 0; +} + +} + +/*************************************<->*********************************** + * + * RegisterFwsWindow() - + * + * Send a client message to the FWS_COMM_WINDOW indicating the existance + * of a new FWS client window. Be careful to avoid BadWindow errors on + * the XSendEvent in case the FWS_COMM_WINDOW root window property had + * old/obsolete junk in it. + * + *************************************<->***********************************/ + +Bool +RegisterFwsWindow (Display *display, Window window) +{ + XClientMessageEvent msg; + + msg.type = ClientMessage; + msg.window = fwsCommWindow; + msg.message_type = FWS_REGISTER_WINDOW; + msg.format = 32; + msg.data.l[0] = window; + + XSync (display, False); + badWindowFound = False; + oldHandler = XSetErrorHandler (newHandler); + + XSendEvent (display, fwsCommWindow, False, NoEventMask, + (XEvent *) &msg); + XSync (display, False); + + XSetErrorHandler (oldHandler); + #if OSL_DEBUG_LEVEL > 1 + if (badWindowFound) + fprintf (stderr, "No FWS client window to register with.\n"); + #endif + + return !badWindowFound; +} + +/*************************************<->*********************************** + * + * AddFwsProtocols - + * + * Add the FWS protocol atoms to the WMProtocols property for the window. + * + *************************************<->***********************************/ + +void +AddFwsProtocols (Display *display, Window window) +{ + #define MAX_FWS_PROTOS 10 + + Atom fwsProtocols[ MAX_FWS_PROTOS ]; + int nProtos = 0; + + fwsProtocols[ nProtos++ ] = FWS_CLIENT; + fwsProtocols[ nProtos++ ] = FWS_STACK_UNDER; + fwsProtocols[ nProtos++ ] = FWS_STATE_CHANGE; + fwsProtocols[ nProtos++ ] = FWS_PASS_ALL_INPUT; + XChangeProperty (display, window, WM_PROTOCOLS, + XA_ATOM, 32, PropModeAppend, + (unsigned char *) fwsProtocols, nProtos); +} + diff --git a/vcl/unx/source/window/FWS.hxx b/vcl/unx/source/window/FWS.hxx new file mode 100644 index 000000000000..a687870ede4a --- /dev/null +++ b/vcl/unx/source/window/FWS.hxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#ifndef _FOREIGN_WINDOW_SYSTEM_HXX +#define _FOREIGN_WINDOW_SYSTEM_HXX + +#include <X11/Xlib.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Initialize our atoms and determine if the current window manager is + * providing FWS extension support. + */ + +Bool +WMSupportsFWS (Display *display, int screen); + +/* Send a client message to the FWS_COMM_WINDOW indicating the existance + * of a new FWS client window. Be careful to avoid BadWindow errors on + * the XSendEvent in case the FWS_COMM_WINDOW root window property had + * old/obsolete junk in it. + */ + +Bool +RegisterFwsWindow (Display *display, Window window); + +/* Add the FWS protocol atoms to the WMProtocols property for the window. + */ + +void +AddFwsProtocols (Display *display, Window window); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif // _FOREIGN_WINDOW_SYSTEM_HXX + diff --git a/vcl/unx/source/window/makefile.mk b/vcl/unx/source/window/makefile.mk new file mode 100644 index 000000000000..c5cd95ba6b1c --- /dev/null +++ b/vcl/unx/source/window/makefile.mk @@ -0,0 +1,59 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=vcl +TARGET=salwin +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile2.pmk + +# --- Files -------------------------------------------------------- + +.IF "$(GUIBASE)"!="unx" + +dummy: + @echo "Nothing to build for GUIBASE $(GUIBASE)" + +.ELSE # "$(GUIBASE)"!="unx" + +SLOFILES= \ + $(SLO)/FWS.obj $(SLO)/salframe.obj $(SLO)/salobj.obj + +.ENDIF # "$(GUIBASE)"!="unx" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.INCLUDE : $(PRJ)$/util$/target.pmk diff --git a/vcl/unx/source/window/salframe.cxx b/vcl/unx/source/window/salframe.cxx new file mode 100644 index 000000000000..5ad3a9d94375 --- /dev/null +++ b/vcl/unx/source/window/salframe.cxx @@ -0,0 +1,4518 @@ +/************************************************************************* + * + * 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" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <tools/prex.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include "FWS.hxx" +#include <X11/extensions/shape.h> +#ifndef SOLARIS +#include <X11/extensions/dpms.h> +#endif +#include <tools/postx.h> + +#include "salunx.h" +#include "saldata.hxx" +#include "saldisp.hxx" +#include "salgdi.h" +#include "salframe.h" +#include "soicon.hxx" +#include "dtint.hxx" +#include "sm.hxx" +#include "wmadaptor.hxx" +#include "salprn.h" +#include "salbmp.h" +#include "i18n_ic.hxx" +#include "i18n_keysym.hxx" +#include "i18n_status.hxx" + +#include "vcl/salinst.hxx" +#include "vcl/floatwin.hxx" +#include "vcl/sallayout.hxx" +#include "vcl/svapp.hxx" +#include "vcl/keycodes.hxx" +#include "vcl/printerinfomanager.hxx" +#include "vcl/settings.hxx" + +#include "tools/debug.hxx" + +#include "sal/alloca.h" +#include <com/sun/star/uno/Exception.hpp> + +#include <algorithm> + +#ifndef Button6 +# define Button6 6 +#endif +#ifndef Button7 +# define Button7 7 +#endif + +using namespace vcl_sal; +using namespace vcl; + +// -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#define CLIENT_EVENTS StructureNotifyMask \ + | SubstructureNotifyMask \ + | KeyPressMask \ + | KeyReleaseMask \ + | ButtonPressMask \ + | ButtonReleaseMask \ + | PointerMotionMask \ + | EnterWindowMask \ + | LeaveWindowMask \ + | FocusChangeMask \ + | ExposureMask \ + | VisibilityChangeMask \ + | PropertyChangeMask \ + | ColormapChangeMask + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +static XLIB_Window hPresentationWindow = None, hPresFocusWindow = None; +static ::std::list< XLIB_Window > aPresentationReparentList; +static int nVisibleFloats = 0; + +X11SalFrame* X11SalFrame::s_pSaveYourselfFrame = NULL; + +// -=-= C++ statics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +static void doReparentPresentationDialogues( SalDisplay* pDisplay ) +{ + pDisplay->GetXLib()->PushXErrorLevel( true ); + while( aPresentationReparentList.begin() != aPresentationReparentList.end() ) + { + int x, y; + XLIB_Window aRoot, aChild; + unsigned int w, h, bw, d; + XGetGeometry( pDisplay->GetDisplay(), + aPresentationReparentList.front(), + &aRoot, + &x, &y, &w, &h, &bw, &d ); + XTranslateCoordinates( pDisplay->GetDisplay(), + hPresentationWindow, + aRoot, + x, y, + &x, &y, + &aChild ); + XReparentWindow( pDisplay->GetDisplay(), + aPresentationReparentList.front(), + aRoot, + x, y ); + aPresentationReparentList.pop_front(); + } + if( hPresFocusWindow ) + XSetInputFocus( pDisplay->GetDisplay(), hPresFocusWindow, PointerRoot, CurrentTime ); + XSync( pDisplay->GetDisplay(), False ); + pDisplay->GetXLib()->PopXErrorLevel(); +} + +// -=-= SalFrame / X11SalFrame =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +bool X11SalFrame::IsOverrideRedirect() const +{ + return + ((nStyle_ & SAL_FRAME_STYLE_INTRO) && !pDisplay_->getWMAdaptor()->supportsSplash()) + || + (!( nStyle_ & ~SAL_FRAME_STYLE_DEFAULT ) && !pDisplay_->getWMAdaptor()->supportsFullScreen()) + ; +} + +bool X11SalFrame::IsFloatGrabWindow() const +{ + static const char* pDisableGrab = getenv( "SAL_DISABLE_FLOATGRAB" ); + + return + ( ( !pDisableGrab || !*pDisableGrab ) && + ( + (nStyle_ & SAL_FRAME_STYLE_FLOAT) && + ! (nStyle_ & SAL_FRAME_STYLE_TOOLTIP) && + ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) + ) + ); +} + +void X11SalFrame::setXEmbedInfo() +{ + if( m_bXEmbed ) + { + long aInfo[2]; + aInfo[0] = 1; // XEMBED protocol version + aInfo[1] = (bMapped_ ? 1 : 0); // XEMBED_MAPPED + XChangeProperty( pDisplay_->GetDisplay(), + mhWindow, + pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ), + pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED_INFO ), + 32, + PropModeReplace, + reinterpret_cast<unsigned char*>(aInfo), + sizeof(aInfo)/sizeof(aInfo[0]) ); + } +} + +void X11SalFrame::askForXEmbedFocus( sal_Int32 i_nTimeCode ) +{ + XEvent aEvent; + + rtl_zeroMemory( &aEvent, sizeof(aEvent) ); + aEvent.xclient.window = mhForeignParent; + aEvent.xclient.type = ClientMessage; + aEvent.xclient.message_type = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::XEMBED ); + aEvent.xclient.format = 32; + aEvent.xclient.data.l[0] = i_nTimeCode ? i_nTimeCode : CurrentTime; + aEvent.xclient.data.l[1] = 3; // XEMBED_REQUEST_FOCUS + aEvent.xclient.data.l[2] = 0; + aEvent.xclient.data.l[3] = 0; + aEvent.xclient.data.l[4] = 0; + + GetDisplay()->GetXLib()->PushXErrorLevel( true ); + XSendEvent( pDisplay_->GetDisplay(), + mhForeignParent, + False, NoEventMask, &aEvent ); + XSync( pDisplay_->GetDisplay(), False ); + GetDisplay()->GetXLib()->PopXErrorLevel(); +} + + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::Init( sal_uLong nSalFrameStyle, int nScreen, SystemParentData* pParentData, bool bUseGeometry ) +{ + if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) + nScreen = GetDisplay()->GetDefaultScreenNumber(); + if( mpParent ) + nScreen = mpParent->m_nScreen; + + m_nScreen = nScreen; + nStyle_ = nSalFrameStyle; + XWMHints Hints; + Hints.flags = InputHint; + Hints.input = (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? False : True; + + int x = 0, y = 0; + unsigned int w = 500, h = 500; + XSetWindowAttributes Attributes; + + int nAttrMask = CWBorderPixel + | CWBackPixmap + | CWColormap + | CWOverrideRedirect + | CWEventMask + ; + Attributes.border_pixel = 0; + Attributes.background_pixmap = None; + Attributes.colormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap(); + Attributes.override_redirect = False; + Attributes.event_mask = CLIENT_EVENTS; + + const SalVisual& rVis = GetDisplay()->GetVisual( m_nScreen ); + XLIB_Window aFrameParent = pParentData ? pParentData->aWindow : GetDisplay()->GetRootWindow( m_nScreen ); + XLIB_Window aClientLeader = None; + + if( bUseGeometry ) + { + x = maGeometry.nX; + y = maGeometry.nY; + w = maGeometry.nWidth; + h = maGeometry.nHeight; + } + + if( (nSalFrameStyle & SAL_FRAME_STYLE_FLOAT) && + ! (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) + ) + { + if( nShowState_ == SHOWSTATE_UNKNOWN ) + { + w = 10; + h = 10; + } + Attributes.override_redirect = True; + } + else if( (nSalFrameStyle & SAL_FRAME_STYLE_SYSTEMCHILD ) ) + { + DBG_ASSERT( mpParent, "SAL_FRAME_STYLE_SYSTEMCHILD window without parent" ); + if( mpParent ) + { + aFrameParent = mpParent->mhWindow; + // FIXME: since with SAL_FRAME_STYLE_SYSTEMCHILD + // multiple X11SalFrame objects can have the same shell window + // dispatching events in saldisp.cxx is unclear (the first frame) + // wins. HTH this correctly is unclear yet + // for the time being, treat set the shell window to own window + // like for a normal frame + // mhShellWindow = mpParent->GetShellWindow(); + } + } + else if( pParentData ) + { + // plugin parent may be killed unexpectedly by + // plugging process; ignore XErrors in that case + GetDisplay()->setHaveSystemChildFrame(); + + nStyle_ |= SAL_FRAME_STYLE_PLUG; + Attributes.override_redirect = True; + if( pParentData->nSize >= sizeof(SystemParentData) ) + m_bXEmbed = pParentData->bXEmbedSupport; + + int x_ret, y_ret; + unsigned int bw, d; + XLIB_Window aRoot, aParent; + + XGetGeometry( GetXDisplay(), pParentData->aWindow, + &aRoot, &x_ret, &y_ret, &w, &h, &bw, &d ); + mhForeignParent = pParentData->aWindow; + + mhShellWindow = aParent = mhForeignParent; + XLIB_Window* pChildren; + unsigned int nChildren; + bool bBreak = false; + do + { + XQueryTree( GetDisplay()->GetDisplay(), mhShellWindow, + &aRoot, &aParent, &pChildren, &nChildren ); + XFree( pChildren ); + if( aParent != aRoot ) + mhShellWindow = aParent; + int nCount = 0; + Atom* pProps = XListProperties( GetDisplay()->GetDisplay(), + mhShellWindow, + &nCount ); + for( int i = 0; i < nCount && ! bBreak; ++i ) + bBreak = (pProps[i] == XA_WM_HINTS); + if( pProps ) + XFree( pProps ); + } while( aParent != aRoot && ! bBreak ); + + // check if this is really one of our own frames + // do not change the input mask in that case + const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); + std::list< SalFrame* >::const_iterator it = rFrames.begin(); + while( it != rFrames.end() && mhForeignParent != static_cast<const X11SalFrame*>(*it)->GetWindow() ) + ++it; + + if( it == rFrames.end() ) + { + XSelectInput( GetDisplay()->GetDisplay(), mhForeignParent, StructureNotifyMask | FocusChangeMask ); + XSelectInput( GetDisplay()->GetDisplay(), mhShellWindow, StructureNotifyMask | FocusChangeMask ); + } + } + else + { + if( ! bUseGeometry ) + { + Size aScreenSize( GetDisplay()->getDataForScreen( m_nScreen ).m_aSize ); + w = aScreenSize.Width(); + h = aScreenSize.Height(); + if( nSalFrameStyle & SAL_FRAME_STYLE_SIZEABLE && + nSalFrameStyle & SAL_FRAME_STYLE_MOVEABLE ) + { + // fill in holy default values brought to us by product management + if( aScreenSize.Width() >= 800 ) + w = 785; + if( aScreenSize.Width() >= 1024 ) + w = 920; + + if( aScreenSize.Height() >= 600 ) + h = 550; + if( aScreenSize.Height() >= 768 ) + h = 630; + if( aScreenSize.Height() >= 1024 ) + h = 875; + } + if( ! mpParent ) + { + // find the last document window (if any) + const X11SalFrame* pFrame = NULL; + const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); + std::list< SalFrame* >::const_iterator it = rFrames.begin(); + while( it != rFrames.end() ) + { + pFrame = static_cast< const X11SalFrame* >(*it); + if( ! ( pFrame->mpParent + || pFrame->mbFullScreen + || ! ( pFrame->nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) + || ! pFrame->GetUnmirroredGeometry().nWidth + || ! pFrame->GetUnmirroredGeometry().nHeight + ) + ) + break; + ++it; + } + + if( it != rFrames.end() ) + { + // set a document position and size + // the first frame gets positioned by the window manager + const SalFrameGeometry& rGeom( pFrame->GetUnmirroredGeometry() ); + x = rGeom.nX; + y = rGeom.nY; + if( x+(int)w+40 <= (int)aScreenSize.Width() && + y+(int)h+40 <= (int)aScreenSize.Height() + ) + { + y += 40; + x += 40; + } + else + { + x = 10; // leave some space for decoration + y = 20; + } + } + else if( GetDisplay()->IsXinerama() ) + { + // place frame on same screen as mouse pointer + XLIB_Window aRoot, aChild; + int root_x = 0, root_y = 0, lx, ly; + unsigned int mask; + XQueryPointer( GetXDisplay(), + GetDisplay()->GetRootWindow( m_nScreen ), + &aRoot, &aChild, + &root_x, &root_y, &lx, &ly, &mask ); + const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens(); + for( unsigned int i = 0; i < rScreens.size(); i++ ) + if( rScreens[i].IsInside( Point( root_x, root_y ) ) ) + { + x = rScreens[i].Left(); + y = rScreens[i].Top(); + break; + } + } + } + } + Attributes.win_gravity = pDisplay_->getWMAdaptor()->getInitWinGravity(); + nAttrMask |= CWWinGravity; + if( mpParent ) + { + Attributes.save_under = True; + nAttrMask |= CWSaveUnder; + } + if( IsOverrideRedirect() ) + Attributes.override_redirect = True; + // default icon + if( (nStyle_ & SAL_FRAME_STYLE_INTRO) == 0 ) + { + bool bOk=false; + try + { + bOk=SelectAppIconPixmap( pDisplay_, m_nScreen, + mnIconID != 1 ? mnIconID : + (mpParent ? mpParent->mnIconID : 1), 32, + Hints.icon_pixmap, Hints.icon_mask ); + } + catch( com::sun::star::uno::Exception& ) + { + // can happen - no ucb during early startup + } + if( bOk ) + { + Hints.flags |= IconPixmapHint; + if( Hints.icon_mask ) + Hints.flags |= IconMaskHint; + } + } + + // find the top level frame of the transience hierarchy + X11SalFrame* pFrame = this; + while( pFrame->mpParent ) + pFrame = pFrame->mpParent; + if( (pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) ) + { + // if the top level window is a plugin window, + // then we should place us in the same window group as + // the parent application (or none if there is no window group + // hint in the parent). + if( pFrame->GetShellWindow() ) + { + XWMHints* pWMHints = XGetWMHints( pDisplay_->GetDisplay(), + pFrame->GetShellWindow() ); + if( pWMHints ) + { + if( (pWMHints->flags & WindowGroupHint) ) + { + Hints.flags |= WindowGroupHint; + Hints.window_group = pWMHints->window_group; + } + XFree( pWMHints ); + } + } + } + else + { + Hints.flags |= WindowGroupHint; + Hints.window_group = pFrame->GetShellWindow(); + // note: for a normal document window this will produce None + // as the window is not yet created and the shell window is + // initialized to None. This must be corrected after window creation. + aClientLeader = GetDisplay()->GetDrawable( m_nScreen ); + } + } + + nShowState_ = SHOWSTATE_UNKNOWN; + bViewable_ = sal_True; + bMapped_ = sal_False; + nVisibility_ = VisibilityFullyObscured; + mhWindow = XCreateWindow( GetXDisplay(), + aFrameParent, + x, y, + w, h, + 0, + rVis.GetDepth(), + InputOutput, + rVis.GetVisual(), + nAttrMask, + &Attributes ); + // FIXME: see above: fake shell window for now to own window + if( /*! IsSysChildWindow() &&*/ pParentData == NULL ) + { + mhShellWindow = mhWindow; + } + + // correct window group if necessary + if( (Hints.flags & WindowGroupHint) == WindowGroupHint ) + { + if( Hints.window_group == None ) + Hints.window_group = GetShellWindow(); + } + + maGeometry.nX = x; + maGeometry.nY = y; + maGeometry.nWidth = w; + maGeometry.nHeight = h; + updateScreenNumber(); + + XSync( GetXDisplay(), False ); + setXEmbedInfo(); + + XLIB_Time nUserTime = (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_TOOLWINDOW) ) == 0 ? + pDisplay_->GetLastUserEventTime() : 0; + pDisplay_->getWMAdaptor()->setUserTime( this, nUserTime ); + + if( ! pParentData && ! IsChildWindow() && ! Attributes.override_redirect ) + { + XSetWMHints( GetXDisplay(), mhWindow, &Hints ); + // WM Protocols && internals + Atom a[4]; + int n = 0; + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW ); + if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) ) + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ); + if( ! s_pSaveYourselfFrame && ! mpParent) + { + // at all times have only one frame with SaveYourself + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF ); + s_pSaveYourselfFrame = this; + } + if( (nSalFrameStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_TAKE_FOCUS ); + XSetWMProtocols( GetXDisplay(), GetShellWindow(), a, n ); + + XClassHint* pClass = XAllocClassHint(); + pClass->res_name = const_cast<char*>(X11SalData::getFrameResName()); + pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName()); + XSetClassHint( GetXDisplay(), GetShellWindow(), pClass ); + XFree( pClass ); + + XSizeHints* pHints = XAllocSizeHints(); + pHints->flags = PWinGravity | PPosition; + pHints->win_gravity = GetDisplay()->getWMAdaptor()->getPositionWinGravity(); + pHints->x = 0; + pHints->y = 0; + if( mbFullScreen ) + { + pHints->flags |= PMaxSize | PMinSize; + pHints->max_width = w+100; + pHints->max_height = h+100; + pHints->min_width = w; + pHints->min_height = h; + } + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree (pHints); + + // set PID and WM_CLIENT_MACHINE + pDisplay_->getWMAdaptor()->setClientMachine( this ); + pDisplay_->getWMAdaptor()->setPID( this ); + + // set client leader + if( aClientLeader ) + { + XChangeProperty( GetXDisplay(), + mhWindow, + pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_CLIENT_LEADER), + XA_WINDOW, + 32, + PropModeReplace, + (unsigned char*)&aClientLeader, + 1 + ); + } +#define DECOFLAGS (SAL_FRAME_STYLE_MOVEABLE | SAL_FRAME_STYLE_SIZEABLE | SAL_FRAME_STYLE_CLOSEABLE) + int nDecoFlags = WMAdaptor::decoration_All; + if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) || + (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) + ) + nDecoFlags = 0; + else if( (nStyle_ & DECOFLAGS ) != DECOFLAGS || (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) + { + if( nStyle_ & DECOFLAGS ) + // if any decoration, then show a border + nDecoFlags = WMAdaptor::decoration_Border; + else + nDecoFlags = 0; + + if( ! mpParent && (nStyle_ & DECOFLAGS) ) + // don't add a min button if window should be decorationless + nDecoFlags |= WMAdaptor::decoration_MinimizeBtn; + if( nStyle_ & SAL_FRAME_STYLE_CLOSEABLE ) + nDecoFlags |= WMAdaptor::decoration_CloseBtn; + if( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) + { + nDecoFlags |= WMAdaptor::decoration_Resize; + if( ! (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) + nDecoFlags |= WMAdaptor::decoration_MaximizeBtn; + } + if( nStyle_ & SAL_FRAME_STYLE_MOVEABLE ) + nDecoFlags |= WMAdaptor::decoration_Title; + } + + WMAdaptor::WMWindowType eType = WMAdaptor::windowType_Normal; + if( nStyle_ & SAL_FRAME_STYLE_INTRO ) + eType = WMAdaptor::windowType_Splash; + if( (nStyle_ & SAL_FRAME_STYLE_DIALOG) && hPresentationWindow == None ) + eType = WMAdaptor::windowType_ModelessDialogue; + if( nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW ) + eType = WMAdaptor::windowType_Utility; + if( nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION ) + eType = WMAdaptor::windowType_Toolbar; + if( (nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) + && GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) + eType = WMAdaptor::windowType_Dock; + + GetDisplay()->getWMAdaptor()-> + setFrameTypeAndDecoration( this, + eType, + nDecoFlags, + hPresentationWindow ? NULL : mpParent ); + + if( (nStyle_ & (SAL_FRAME_STYLE_DEFAULT | + SAL_FRAME_STYLE_OWNERDRAWDECORATION| + SAL_FRAME_STYLE_FLOAT | + SAL_FRAME_STYLE_INTRO | + SAL_FRAME_STYLE_PARTIAL_FULLSCREEN) ) + == SAL_FRAME_STYLE_DEFAULT ) + pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true ); + } + + m_nWorkArea = GetDisplay()->getWMAdaptor()->getCurrentWorkArea(); + + // Pointer + SetPointer( POINTER_ARROW ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +X11SalFrame::X11SalFrame( SalFrame *pParent, sal_uLong nSalFrameStyle, SystemParentData* pSystemParent ) +{ + X11SalData* pSalData = GetX11SalData(); + + // initialize frame geometry + memset( &maGeometry, 0, sizeof(maGeometry) ); + + mpParent = static_cast< X11SalFrame* >( pParent ); + + mbTransientForRoot = false; + + pDisplay_ = pSalData->GetDisplay(); + // insert frame in framelist + pDisplay_->registerFrame( this ); + + mhWindow = None; + mhShellWindow = None; + mhStackingWindow = None; + mhForeignParent = None; + mhBackgroundPixmap = None; + m_bSetFocusOnMap = false; + + pGraphics_ = NULL; + pFreeGraphics_ = NULL; + + hCursor_ = None; + nCaptured_ = 0; + + nReleaseTime_ = 0; + nKeyCode_ = 0; + nKeyState_ = 0; + nCompose_ = -1; + mbKeyMenu = false; + mbSendExtKeyModChange = false; + mnExtKeyMod = 0; + + nShowState_ = SHOWSTATE_UNKNOWN; + nWidth_ = 0; + nHeight_ = 0; + nStyle_ = 0; + mnExtStyle = 0; + bAlwaysOnTop_ = sal_False; + + // set bViewable_ to sal_True: hack GetClientSize to report something + // different to 0/0 before first map + bViewable_ = sal_True; + bMapped_ = sal_False; + bDefaultPosition_ = sal_True; + nVisibility_ = VisibilityFullyObscured; + m_nWorkArea = 0; + mbInShow = sal_False; + m_bXEmbed = false; + + nScreenSaversTimeout_ = 0; + + mpInputContext = NULL; + mbInputFocus = False; + + maAlwaysOnTopRaiseTimer.SetTimeoutHdl( LINK( this, X11SalFrame, HandleAlwaysOnTopRaise ) ); + maAlwaysOnTopRaiseTimer.SetTimeout( 100 ); + + meWindowType = WMAdaptor::windowType_Normal; + mnDecorationFlags = WMAdaptor::decoration_All; + mbMaximizedVert = false; + mbMaximizedHorz = false; + mbShaded = false; + mbFullScreen = false; + + mnIconID = 1; // ICON_DEFAULT + + m_pClipRectangles = NULL; + m_nCurClipRect = 0; + m_nMaxClipRect = 0; + + if( mpParent ) + mpParent->maChildren.push_back( this ); + + Init( nSalFrameStyle, GetDisplay()->GetDefaultScreenNumber(), pSystemParent ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::passOnSaveYourSelf() +{ + if( this == s_pSaveYourselfFrame ) + { + // pass on SaveYourself + const X11SalFrame* pFrame = NULL; + const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); + std::list< SalFrame* >::const_iterator it = rFrames.begin(); + while( it != rFrames.end() ) + { + pFrame = static_cast< const X11SalFrame* >(*it); + if( ! ( IsChildWindow() || pFrame->mpParent ) + && pFrame != s_pSaveYourselfFrame ) + break; + ++it; + } + + s_pSaveYourselfFrame = (it != rFrames.end() ) ? const_cast<X11SalFrame*>(pFrame) : NULL; + if( s_pSaveYourselfFrame ) + { + Atom a[4]; + int n = 0; + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_DELETE_WINDOW ); + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_SAVE_YOURSELF ); + if( pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ) ) + a[n++] = pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::NET_WM_PING ); + XSetWMProtocols( GetXDisplay(), s_pSaveYourselfFrame->GetShellWindow(), a, n ); + } + } +} + +X11SalFrame::~X11SalFrame() +{ + notifyDelete(); + + if( m_pClipRectangles ) + { + delete [] m_pClipRectangles; + m_pClipRectangles = NULL; + m_nCurClipRect = m_nMaxClipRect = 0; + } + + if( mhBackgroundPixmap ) + { + XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None ); + XFreePixmap( GetXDisplay(), mhBackgroundPixmap ); + } + + if( mhStackingWindow ) + aPresentationReparentList.remove( mhStackingWindow ); + + // remove from parent's list + if( mpParent ) + mpParent->maChildren.remove( this ); + + // deregister on SalDisplay + pDisplay_->deregisterFrame( this ); + + // unselect all events, some may be still in the queue anyway + if( ! IsSysChildWindow() ) + XSelectInput( GetXDisplay(), GetShellWindow(), 0 ); + XSelectInput( GetXDisplay(), GetWindow(), 0 ); + + ShowFullScreen( sal_False, 0 ); + + if( bMapped_ ) + Show( sal_False ); + + if( mpInputContext ) + { + mpInputContext->UnsetICFocus( this ); + mpInputContext->Unmap( this ); + delete mpInputContext; + } + + if( GetWindow() == hPresentationWindow ) + { + hPresentationWindow = None; + doReparentPresentationDialogues( GetDisplay() ); + } + + if( pGraphics_ ) + { + pGraphics_->DeInit(); + delete pGraphics_; + } + + if( pFreeGraphics_ ) + { + pFreeGraphics_->DeInit(); + delete pFreeGraphics_; + } + + + XDestroyWindow( GetXDisplay(), mhWindow ); + + /* + * check if there is only the status frame left + * if so, free it + */ + if( ! GetDisplay()->getFrames().empty() && I18NStatus::exists() ) + { + SalFrame* pStatusFrame = I18NStatus::get().getStatusFrame(); + std::list< SalFrame* >::const_iterator sit = GetDisplay()->getFrames().begin(); + if( pStatusFrame + && *sit == pStatusFrame + && ++sit == GetDisplay()->getFrames().end() ) + vcl::I18NStatus::free(); + } + + passOnSaveYourSelf(); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) +{ + if( nStyle != mnExtStyle && ! IsChildWindow() ) + { + mnExtStyle = nStyle; + + XClassHint* pClass = XAllocClassHint(); + rtl::OString aResHint = X11SalData::getFrameResName( mnExtStyle ); + pClass->res_name = const_cast<char*>(aResHint.getStr()); + pClass->res_class = const_cast<char*>(X11SalData::getFrameClassName()); + XSetClassHint( GetXDisplay(), GetShellWindow(), pClass ); + XFree( pClass ); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetBackgroundBitmap( SalBitmap* pBitmap ) +{ + if( mhBackgroundPixmap ) + { + XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), None ); + XFreePixmap( GetXDisplay(), mhBackgroundPixmap ); + mhBackgroundPixmap = None; + } + if( pBitmap ) + { + X11SalBitmap* pBM = static_cast<X11SalBitmap*>(pBitmap); + Size aSize = pBM->GetSize(); + if( aSize.Width() && aSize.Height() ) + { + mhBackgroundPixmap = + XCreatePixmap( GetXDisplay(), + GetWindow(), + aSize.Width(), + aSize.Height(), + GetDisplay()->GetVisual( m_nScreen ).GetDepth() ); + if( mhBackgroundPixmap ) + { + SalTwoRect aTwoRect; + aTwoRect.mnSrcX = aTwoRect.mnSrcY = aTwoRect.mnDestX = aTwoRect.mnDestY = 0; + aTwoRect.mnSrcWidth = aTwoRect.mnDestWidth = aSize.Width(); + aTwoRect.mnSrcHeight = aTwoRect.mnDestHeight = aSize.Height(); + pBM->ImplDraw( mhBackgroundPixmap, + m_nScreen, + GetDisplay()->GetVisual( m_nScreen ).GetDepth(), + aTwoRect, GetDisplay()->GetCopyGC( m_nScreen ) ); + XSetWindowBackgroundPixmap( GetXDisplay(), GetWindow(), mhBackgroundPixmap ); + } + } + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +const SystemChildData* X11SalFrame::GetSystemData() const +{ + X11SalFrame *pFrame = const_cast<X11SalFrame*>(this); + pFrame->maSystemChildData.nSize = sizeof( SystemChildData ); + pFrame->maSystemChildData.pDisplay = GetXDisplay(); + pFrame->maSystemChildData.aWindow = pFrame->GetWindow(); + pFrame->maSystemChildData.pSalFrame = pFrame; + pFrame->maSystemChildData.pWidget = NULL; + pFrame->maSystemChildData.pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual(); + pFrame->maSystemChildData.nScreen = m_nScreen; + pFrame->maSystemChildData.nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth(); + pFrame->maSystemChildData.aColormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap(); + pFrame->maSystemChildData.pAppContext = NULL; + pFrame->maSystemChildData.aShellWindow = pFrame->GetShellWindow(); + pFrame->maSystemChildData.pShellWidget = NULL; + return &maSystemChildData; +} + +SalGraphics *X11SalFrame::GetGraphics() +{ + if( pGraphics_ ) + return NULL; + + if( pFreeGraphics_ ) + { + pGraphics_ = pFreeGraphics_; + pFreeGraphics_ = NULL; + } + else + { + pGraphics_ = new X11SalGraphics(); + pGraphics_->Init( this, GetWindow(), m_nScreen ); + } + + return pGraphics_; +} + +void X11SalFrame::ReleaseGraphics( SalGraphics *pGraphics ) +{ + DBG_ASSERT( pGraphics == pGraphics_, "SalFrame::ReleaseGraphics pGraphics!=pGraphics_" ); + + if( pGraphics != pGraphics_ ) + return; + + pFreeGraphics_ = pGraphics_; + pGraphics_ = NULL; +} + +void X11SalFrame::updateGraphics( bool bClear ) +{ + Drawable aDrawable = bClear ? None : GetWindow(); + if( pGraphics_ ) + pGraphics_->SetDrawable( aDrawable, m_nScreen ); + if( pFreeGraphics_ ) + pFreeGraphics_->SetDrawable( aDrawable, m_nScreen ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::Enable( sal_Bool /*bEnable*/ ) +{ + // NYI: enable/disable frame +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetIcon( sal_uInt16 nIcon ) +{ + if ( ! IsChildWindow() ) + { + // 0 == default icon -> #1 + if ( nIcon == 0 ) + nIcon = 1; + + mnIconID = nIcon; + + XIconSize *pIconSize = NULL; + int nSizes = 0; + int iconSize = 32; + if ( XGetIconSizes( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ), &pIconSize, &nSizes ) ) + { +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "X11SalFrame::SetIcon(): found %d IconSizes:\n", nSizes); +#endif + + const int ourLargestIconSize = 48; + bool bFoundIconSize = false; + + int i; + for( i=0; i<nSizes; i++) + { + // select largest supported icon + + // Note: olwm/olvwm reports a huge max icon size of + // 160x160 pixels; always choosing the max as the + // preferred icon size is apparently wrong under olvwm + // - so we keep the safe default |iconSize| when we see + // unreasonable large max icon sizes (> twice of our + // largest available icon) reported by XGetIconSizes. + if( pIconSize[i].max_width > iconSize + && pIconSize[i].max_width <= 2*ourLargestIconSize ) + { + iconSize = pIconSize[i].max_width; + bFoundIconSize = true; + } + iconSize = pIconSize[i].max_width; + +#if OSL_DEBUG_LEVEL > 1 + fprintf(stderr, "min: %d, %d\nmax: %d, %d\ninc: %d, %d\n\n", + pIconSize[i].min_width, pIconSize[i].min_height, + pIconSize[i].max_width, pIconSize[i].max_height, + pIconSize[i].width_inc, pIconSize[i].height_inc); +#endif + } + + if ( !bFoundIconSize ) + { + // Unless someone has fixed olwm/olvwm, we have rejected + // the max icon size from |XGetIconSizes()|. Provide a + // better icon size default value, in case our window manager + // is olwm/olvwm. + const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() ); + + if ( rWM.EqualsAscii( "Olwm" ) ) + iconSize = 48; + } + + XFree( pIconSize ); + } + else + { + const String& rWM( pDisplay_->getWMAdaptor()->getWindowManagerName() ); + if( rWM.EqualsAscii( "KWin" ) ) // assume KDE is running + iconSize = 48; + static bool bGnomeIconSize = false; + static bool bGnomeChecked = false; + if( ! bGnomeChecked ) + { + bGnomeChecked=true; + int nCount = 0; + Atom* pProps = XListProperties( GetXDisplay(), + GetDisplay()->GetRootWindow( m_nScreen ), + &nCount ); + for( int i = 0; i < nCount && !bGnomeIconSize; i++ ) + { + char* pName = XGetAtomName( GetXDisplay(), pProps[i] ); + if( !strcmp( pName, "GNOME_PANEL_DESKTOP_AREA" ) ) + bGnomeIconSize = true; + if( pName ) + XFree( pName ); + } + if( pProps ) + XFree( pProps ); + } + if( bGnomeIconSize ) + iconSize = 48; + } + + XWMHints Hints; + Hints.flags = 0; + XWMHints *pHints = XGetWMHints( GetXDisplay(), GetShellWindow() ); + if( pHints ) + { + memcpy(&Hints, pHints, sizeof( XWMHints )); + XFree( pHints ); + } + pHints = &Hints; + + sal_Bool bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen, + nIcon, iconSize, + pHints->icon_pixmap, pHints->icon_mask ); + if ( !bOk ) + { + // load default icon (0) + bOk = SelectAppIconPixmap( GetDisplay(), m_nScreen, + 0, iconSize, + pHints->icon_pixmap, pHints->icon_mask ); + } + if( bOk ) + { + pHints->flags |= IconPixmapHint; + if( pHints->icon_mask ) + pHints->flags |= IconMaskHint; + + XSetWMHints( GetXDisplay(), GetShellWindow(), pHints ); + } + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetMaxClientSize( long nWidth, long nHeight ) +{ + if( ! IsChildWindow() ) + { + if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) + { + XSizeHints* pHints = XAllocSizeHints(); + long nSupplied = 0; + XGetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints, + &nSupplied + ); + pHints->max_width = nWidth; + pHints->max_height = nHeight; + pHints->flags |= PMaxSize; + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree( pHints ); + } + } +} + +void X11SalFrame::SetMinClientSize( long nWidth, long nHeight ) +{ + if( ! IsChildWindow() ) + { + if( GetShellWindow() && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) + { + XSizeHints* pHints = XAllocSizeHints(); + long nSupplied = 0; + XGetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints, + &nSupplied + ); + pHints->min_width = nWidth; + pHints->min_height = nHeight; + pHints->flags |= PMinSize; + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree( pHints ); + } + } +} + +// Show + Pos (x,y,z) + Size (width,height) +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate ) +{ + if( ( bVisible && bMapped_ ) + || ( !bVisible && !bMapped_ ) ) + return; + + // HACK: this is a workaround for (at least) kwin + // even though transient frames should be kept above their parent + // this does not necessarily hold true for DOCK type windows + // so artificially set ABOVE and remove it again on hide + if( mpParent && (mpParent->nStyle_ & SAL_FRAME_STYLE_PARTIAL_FULLSCREEN ) && pDisplay_->getWMAdaptor()->isLegacyPartialFullscreen()) + pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bVisible ); + + bMapped_ = bVisible; + bViewable_ = bVisible; + setXEmbedInfo(); + if( bVisible ) + { + SessionManagerClient::open(); // will simply return after the first time + + mbInShow = sal_True; + if( ! (nStyle_ & SAL_FRAME_STYLE_INTRO) ) + { + // hide all INTRO frames + const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); + for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) + { + const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); + // look for intro bit map; if present, hide it + if( pFrame->nStyle_ & SAL_FRAME_STYLE_INTRO ) + { + if( pFrame->bMapped_ ) + const_cast<X11SalFrame*>(pFrame)->Show( sal_False ); + } + } + } + + // update NET_WM_STATE which may have been deleted due to earlier Show(sal_False) + if( nShowState_ == SHOWSTATE_HIDDEN ) + GetDisplay()->getWMAdaptor()->frameIsMapping( this ); + + /* + * #95097# + * Actually this is rather exotic and currently happens only in conjunction + * with the basic dialogue editor, + * which shows a frame and instantly hides it again. After that the + * editor window is shown and the WM takes this as an opportunity + * to show our hidden transient frame also. So Show( sal_False ) must + * withdraw the frame AND delete the WM_TRANSIENT_FOR property. + * In case the frame is shown again, the transient hint must be restored here. + */ + if( ! IsChildWindow() + && ! IsOverrideRedirect() + && ! IsFloatGrabWindow() + && mpParent + ) + { + GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent ); + } + + // #i45160# switch to desktop where a dialog with parent will appear + if( mpParent && mpParent->m_nWorkArea != m_nWorkArea ) + GetDisplay()->getWMAdaptor()->switchToWorkArea( mpParent->m_nWorkArea ); + + if( IsFloatGrabWindow() && + mpParent && + nVisibleFloats == 0 && + ! GetDisplay()->GetCaptureFrame() ) + { + /* #i39420# + * outsmart KWin's "focus strictly under mouse" mode + * which insists on taking the focus from the document + * to the new float. Grab focus to parent frame BEFORE + * showing the float (cannot grab it to the float + * before show). + */ + XGrabPointer( GetXDisplay(), + mpParent->GetWindow(), + True, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, + GrabModeAsync, + None, + mpParent ? mpParent->GetCursor() : None, + CurrentTime + ); + } + + XLIB_Time nUserTime = 0; + if( ! bNoActivate && (nStyle_ & (SAL_FRAME_STYLE_OWNERDRAWDECORATION)) == 0 ) + nUserTime = pDisplay_->GetLastUserEventTime( true ); + GetDisplay()->getWMAdaptor()->setUserTime( this, nUserTime ); + if( ! bNoActivate && (nStyle_ & SAL_FRAME_STYLE_TOOLWINDOW) ) + m_bSetFocusOnMap = true; + + // actually map the window + if( m_bXEmbed ) + askForXEmbedFocus( 0 ); + else + { + if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() ) + { + if( IsChildWindow() ) + XMapWindow( GetXDisplay(), GetShellWindow() ); + XSelectInput( GetXDisplay(), GetShellWindow(), CLIENT_EVENTS ); + } + if( nStyle_ & SAL_FRAME_STYLE_FLOAT ) + XMapRaised( GetXDisplay(), GetWindow() ); + else + XMapWindow( GetXDisplay(), GetWindow() ); + } + XSelectInput( GetXDisplay(), GetWindow(), CLIENT_EVENTS ); + + if( maGeometry.nWidth > 0 + && maGeometry.nHeight > 0 + && ( nWidth_ != (int)maGeometry.nWidth + || nHeight_ != (int)maGeometry.nHeight ) ) + { + nWidth_ = maGeometry.nWidth; + nHeight_ = maGeometry.nHeight; + } + + XSync( GetXDisplay(), False ); + + if( IsFloatGrabWindow() ) + { + /* + * #95453# + * Sawfish and twm can be switched to enter-exit focus behaviour. In this case + * we must grab the pointer else the dumb WM will put the focus to the + * override-redirect float window. The application window will be deactivated + * which causes that the floats are destroyed, so the user can never click on + * a menu because it vanishes as soon as he enters it. + */ + nVisibleFloats++; + if( nVisibleFloats == 1 && ! GetDisplay()->GetCaptureFrame() ) + { + /* #i39420# now move grab to the new float window */ + XGrabPointer( GetXDisplay(), + GetWindow(), + True, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, + GrabModeAsync, + None, + mpParent ? mpParent->GetCursor() : None, + CurrentTime + ); + } + } + CallCallback( SALEVENT_RESIZE, NULL ); + + /* + * sometimes a message box/dialogue is brought up when a frame is not mapped + * the corresponding TRANSIENT_FOR hint is then set to the root window + * so that the dialogue shows in all cases. Correct it here if the + * frame is shown afterwards. + */ + if( ! IsChildWindow() + && ! IsOverrideRedirect() + && ! IsFloatGrabWindow() + ) + { + for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); + it != maChildren.end(); ++it ) + { + if( (*it)->mbTransientForRoot ) + GetDisplay()->getWMAdaptor()->changeReferenceFrame( *it, this ); + } + } + /* + * leave SHOWSTATE_UNKNOWN as this indicates first mapping + * and is only reset int HandleSizeEvent + */ + if( nShowState_ != SHOWSTATE_UNKNOWN ) + nShowState_ = SHOWSTATE_NORMAL; + + /* + * #98107# plugged windows don't necessarily get the + * focus on show because the parent may already be mapped + * and have the focus. So try to set the focus + * to the child on Show(sal_True) + */ + if( (nStyle_ & SAL_FRAME_STYLE_PLUG) && ! m_bXEmbed ) + XSetInputFocus( GetXDisplay(), + GetWindow(), + RevertToParent, + CurrentTime ); + + if( mpParent ) + { + // push this frame so it will be in front of its siblings + // only necessary for insane transient behaviour of Dtwm/olwm + mpParent->maChildren.remove( this ); + mpParent->maChildren.push_front(this); + } + } + else + { + if( getInputContext() ) + getInputContext()->Unmap( this ); + + if( ! IsChildWindow() ) + { + /* FIXME: Is deleting the property really necessary ? It hurts + * owner drawn windows at least. + */ + if( mpParent && ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + XDeleteProperty( GetXDisplay(), GetShellWindow(), GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::WM_TRANSIENT_FOR ) ); + XWithdrawWindow( GetXDisplay(), GetShellWindow(), m_nScreen ); + } + else if( ! m_bXEmbed ) + XUnmapWindow( GetXDisplay(), GetWindow() ); + + nShowState_ = SHOWSTATE_HIDDEN; + if( IsFloatGrabWindow() && nVisibleFloats ) + { + nVisibleFloats--; + if( nVisibleFloats == 0 && ! GetDisplay()->GetCaptureFrame() ) + XUngrabPointer( GetXDisplay(), + CurrentTime ); + } + // flush here; there may be a very seldom race between + // the display connection used for clipboard and our connection + Flush(); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::ToTop( sal_uInt16 nFlags ) +{ + if( ( nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN ) + && ! ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) + && nShowState_ != SHOWSTATE_HIDDEN + && nShowState_ != SHOWSTATE_UNKNOWN + ) + { + GetDisplay()->getWMAdaptor()->frameIsMapping( this ); + if( GetWindow() != GetShellWindow() && ! IsSysChildWindow() ) + XMapWindow( GetXDisplay(), GetShellWindow() ); + XMapWindow( GetXDisplay(), GetWindow() ); + } + + XLIB_Window aToTopWindow = IsSysChildWindow() ? GetWindow() : GetShellWindow(); + if( ! (nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY) ) + { + XRaiseWindow( GetXDisplay(), aToTopWindow ); + if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() ) + for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); + it != maChildren.end(); ++it ) + (*it)->ToTop( nFlags & ~SAL_FRAME_TOTOP_GRABFOCUS ); + } + + if( ( ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) || ( nFlags & SAL_FRAME_TOTOP_GRABFOCUS_ONLY ) ) + && bMapped_ ) + { + if( m_bXEmbed ) + askForXEmbedFocus( 0 ); + else + XSetInputFocus( GetXDisplay(), aToTopWindow, RevertToParent, CurrentTime ); + } +} +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::GetWorkArea( Rectangle& rWorkArea ) +{ + rWorkArea = pDisplay_->getWMAdaptor()->getWorkArea( 0 ); +} +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::GetClientSize( long &rWidth, long &rHeight ) +{ + if( ! bViewable_ ) + { + rWidth = rHeight = 0; + return; + } + + rWidth = maGeometry.nWidth; + rHeight = maGeometry.nHeight; + + if( !rWidth || !rHeight ) + { + XWindowAttributes aAttrib; + + XGetWindowAttributes( GetXDisplay(), GetWindow(), &aAttrib ); + + maGeometry.nWidth = rWidth = aAttrib.width; + maGeometry.nHeight = rHeight = aAttrib.height; + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetWindowGravity (int nGravity) const +{ + if( ! IsChildWindow() ) + { + XSizeHints* pHint = XAllocSizeHints(); + long nFlag; + + XGetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint, &nFlag); + pHint->flags |= PWinGravity; + pHint->win_gravity = nGravity; + + XSetWMNormalHints (GetXDisplay(), GetShellWindow(), pHint); + XSync (GetXDisplay(), False); + + XFree (pHint); + } +} + +void X11SalFrame::Center( ) +{ + int nX, nY, nScreenWidth, nScreenHeight; + int nRealScreenWidth, nRealScreenHeight; + int nScreenX = 0, nScreenY = 0; + + const Size& aScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize; + nScreenWidth = aScreenSize.Width(); + nScreenHeight = aScreenSize.Height(); + nRealScreenWidth = nScreenWidth; + nRealScreenHeight = nScreenHeight; + + if( GetDisplay()->IsXinerama() ) + { + // get xinerama screen we are on + // if there is a parent, use its center for screen determination + // else use the pointer + XLIB_Window aRoot, aChild; + int root_x, root_y, x, y; + unsigned int mask; + if( mpParent ) + { + root_x = mpParent->maGeometry.nX + mpParent->maGeometry.nWidth/2; + root_y = mpParent->maGeometry.nY + mpParent->maGeometry.nHeight/2; + } + else + XQueryPointer( GetXDisplay(), + GetShellWindow(), + &aRoot, &aChild, + &root_x, &root_y, + &x, &y, + &mask ); + const std::vector< Rectangle >& rScreens = GetDisplay()->GetXineramaScreens(); + for( unsigned int i = 0; i < rScreens.size(); i++ ) + if( rScreens[i].IsInside( Point( root_x, root_y ) ) ) + { + nScreenX = rScreens[i].Left(); + nScreenY = rScreens[i].Top(); + nRealScreenWidth = rScreens[i].GetWidth(); + nRealScreenHeight = rScreens[i].GetHeight(); + break; + } + } + + if( mpParent ) + { + X11SalFrame* pFrame = mpParent; + while( pFrame->mpParent ) + pFrame = pFrame->mpParent; + if( pFrame->maGeometry.nWidth < 1 || pFrame->maGeometry.nHeight < 1 ) + { + Rectangle aRect; + pFrame->GetPosSize( aRect ); + pFrame->maGeometry.nX = aRect.Left(); + pFrame->maGeometry.nY = aRect.Top(); + pFrame->maGeometry.nWidth = aRect.GetWidth(); + pFrame->maGeometry.nHeight = aRect.GetHeight(); + } + + if( pFrame->nStyle_ & SAL_FRAME_STYLE_PLUG ) + { + XLIB_Window aRoot; + unsigned int bw, depth; + XGetGeometry( GetXDisplay(), + pFrame->GetShellWindow(), + &aRoot, + &nScreenX, &nScreenY, + (unsigned int*)&nScreenWidth, + (unsigned int*)&nScreenHeight, + &bw, &depth ); + } + else + { + nScreenX = pFrame->maGeometry.nX; + nScreenY = pFrame->maGeometry.nY; + nScreenWidth = pFrame->maGeometry.nWidth; + nScreenHeight = pFrame->maGeometry.nHeight; + } + } + + if( mpParent && mpParent->nShowState_ == SHOWSTATE_NORMAL ) + { + if( maGeometry.nWidth >= mpParent->maGeometry.nWidth && + maGeometry.nHeight >= mpParent->maGeometry.nHeight ) + { + nX = nScreenX + 40; + nY = nScreenY + 40; + } + else + { + // center the window relative to the top level frame + nX = (nScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX; + nY = (nScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY; + } + } + else + { + // center the window relative to screen + nX = (nRealScreenWidth - (int)maGeometry.nWidth ) / 2 + nScreenX; + nY = (nRealScreenHeight - (int)maGeometry.nHeight) / 2 + nScreenY; + } + nX = nX < 0 ? 0 : nX; + nY = nY < 0 ? 0 : nY; + + bDefaultPosition_ = False; + if( mpParent ) + { + nX -= mpParent->maGeometry.nX; + nY -= mpParent->maGeometry.nY; + } + + Point aPoint(nX, nY); + SetPosSize( Rectangle( aPoint, Size( maGeometry.nWidth, maGeometry.nHeight ) ) ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::updateScreenNumber() +{ + if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) + { + Point aPoint( maGeometry.nX, maGeometry.nY ); + const std::vector<Rectangle>& rScreenRects( GetDisplay()->GetXineramaScreens() ); + size_t nScreens = rScreenRects.size(); + for( size_t i = 0; i < nScreens; i++ ) + { + if( rScreenRects[i].IsInside( aPoint ) ) + { + maGeometry.nScreenNumber = static_cast<unsigned int>(i); + break; + } + } + } + else + maGeometry.nScreenNumber = static_cast<unsigned int>(m_nScreen); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags ) +{ + if( nStyle_ & SAL_FRAME_STYLE_PLUG ) + return; + + // relative positioning in X11SalFrame::SetPosSize + Rectangle aPosSize( Point( maGeometry.nX, maGeometry.nY ), Size( maGeometry.nWidth, maGeometry.nHeight ) ); + aPosSize.Justify(); + + if( ! ( nFlags & SAL_FRAME_POSSIZE_X ) ) + { + nX = aPosSize.Left(); + if( mpParent ) + nX -= mpParent->maGeometry.nX; + } + if( ! ( nFlags & SAL_FRAME_POSSIZE_Y ) ) + { + nY = aPosSize.Top(); + if( mpParent ) + nY -= mpParent->maGeometry.nY; + } + if( ! ( nFlags & SAL_FRAME_POSSIZE_WIDTH ) ) + nWidth = aPosSize.GetWidth(); + if( ! ( nFlags & SAL_FRAME_POSSIZE_HEIGHT ) ) + nHeight = aPosSize.GetHeight(); + + aPosSize = Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ); + + if( ! ( nFlags & ( SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ) ) ) + { + if( bDefaultPosition_ ) + { + maGeometry.nWidth = aPosSize.GetWidth(); + maGeometry.nHeight = aPosSize.GetHeight(); + Center(); + } + else + SetSize( Size( nWidth, nHeight ) ); + } + else + SetPosSize( aPosSize ); + + bDefaultPosition_ = False; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::SetAlwaysOnTop( sal_Bool bOnTop ) +{ + if( ! IsOverrideRedirect() ) + { + bAlwaysOnTop_ = bOnTop; + pDisplay_->getWMAdaptor()->enableAlwaysOnTop( this, bOnTop ); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#define _FRAMESTATE_MASK_GEOMETRY \ + (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_Y | \ + SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT) +#define _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY \ + (SAL_FRAMESTATE_MASK_MAXIMIZED_X | SAL_FRAMESTATE_MASK_MAXIMIZED_Y | \ + SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT) + +void X11SalFrame::SetWindowState( const SalFrameState *pState ) +{ + if (pState == NULL) + return; + + // Request for position or size change + if (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) + { + Rectangle aPosSize; + bool bDoAdjust = false; + + /* #i44325# + * if maximized, set restore size and guess maximized size from last time + * in state change below maximize window + */ + if( ! IsChildWindow() && + (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) && + (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) && + (pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) == _FRAMESTATE_MASK_GEOMETRY && + (pState->mnMask & _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY) == _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY + ) + { + XSizeHints* pHints = XAllocSizeHints(); + long nSupplied = 0; + XGetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints, + &nSupplied ); + pHints->flags |= PPosition | PWinGravity; + pHints->x = pState->mnX; + pHints->y = pState->mnY; + pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity(); + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree( pHints ); + + XMoveResizeWindow( GetXDisplay(), GetShellWindow(), + pState->mnX, pState->mnY, + pState->mnWidth, pState->mnHeight ); + // guess maximized geometry from last time + maGeometry.nX = pState->mnMaximizedX; + maGeometry.nY = pState->mnMaximizedY; + maGeometry.nWidth = pState->mnMaximizedWidth; + maGeometry.nHeight = pState->mnMaximizedHeight; + updateScreenNumber(); + } + else + { + // initialize with current geometry + if ((pState->mnMask & _FRAMESTATE_MASK_GEOMETRY) != _FRAMESTATE_MASK_GEOMETRY) + GetPosSize (aPosSize); + + // change requested properties + if (pState->mnMask & SAL_FRAMESTATE_MASK_X) + { + aPosSize.setX (pState->mnX); + } + if (pState->mnMask & SAL_FRAMESTATE_MASK_Y) + { + aPosSize.setY (pState->mnY); + } + if (pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH) + { + long nWidth = pState->mnWidth > 0 ? pState->mnWidth - 1 : 0; + aPosSize.setWidth (nWidth); + bDoAdjust = true; + } + if (pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT) + { + int nHeight = pState->mnHeight > 0 ? pState->mnHeight - 1 : 0; + aPosSize.setHeight (nHeight); + bDoAdjust = true; + } + + const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize; + const WMAdaptor *pWM = GetDisplay()->getWMAdaptor(); + + if( bDoAdjust && aPosSize.GetWidth() <= aScreenSize.Width() + && aPosSize.GetHeight() <= aScreenSize.Height() ) + { + SalFrameGeometry aGeom = maGeometry; + + if( ! (nStyle_ & ( SAL_FRAME_STYLE_FLOAT | SAL_FRAME_STYLE_PLUG ) ) && + mpParent && + aGeom.nLeftDecoration == 0 && + aGeom.nTopDecoration == 0 ) + { + aGeom = mpParent->maGeometry; + if( aGeom.nLeftDecoration == 0 && + aGeom.nTopDecoration == 0 ) + { + aGeom.nLeftDecoration = 5; + aGeom.nTopDecoration = 20; + aGeom.nRightDecoration = 5; + aGeom.nBottomDecoration = 5; + } + } + + // adjust position so that frame fits onto screen + if( aPosSize.Right()+(long)aGeom.nRightDecoration > aScreenSize.Width()-1 ) + aPosSize.Move( (long)aScreenSize.Width() - (long)aPosSize.Right() - (long)aGeom.nRightDecoration, 0 ); + if( aPosSize.Bottom()+(long)aGeom.nBottomDecoration > aScreenSize.Height()-1 ) + aPosSize.Move( 0, (long)aScreenSize.Height() - (long)aPosSize.Bottom() - (long)aGeom.nBottomDecoration ); + if( aPosSize.Left() < (long)aGeom.nLeftDecoration ) + aPosSize.Move( (long)aGeom.nLeftDecoration - (long)aPosSize.Left(), 0 ); + if( aPosSize.Top() < (long)aGeom.nTopDecoration ) + aPosSize.Move( 0, (long)aGeom.nTopDecoration - (long)aPosSize.Top() ); + } + + // resize with new args + if (pWM->supportsICCCMPos()) + { + if( mpParent ) + aPosSize.Move( -mpParent->maGeometry.nX, + -mpParent->maGeometry.nY ); + SetPosSize( aPosSize ); + bDefaultPosition_ = False; + } + else + SetPosSize( 0, 0, aPosSize.GetWidth(), aPosSize.GetHeight(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); + } + } + + // request for status change + if (pState->mnMask & SAL_FRAMESTATE_MASK_STATE) + { + if (pState->mnState & SAL_FRAMESTATE_MAXIMIZED) + { + nShowState_ = SHOWSTATE_NORMAL; + if( ! (pState->mnState & (SAL_FRAMESTATE_MAXIMIZED_HORZ|SAL_FRAMESTATE_MAXIMIZED_VERT) ) ) + Maximize(); + else + { + bool bHorz = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_HORZ) ? true : false; + bool bVert = (pState->mnState & SAL_FRAMESTATE_MAXIMIZED_VERT) ? true : false; + GetDisplay()->getWMAdaptor()->maximizeFrame( this, bHorz, bVert ); + } + maRestorePosSize.Left() = pState->mnX; + maRestorePosSize.Top() = pState->mnY; + maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnWidth; + maRestorePosSize.Right() = maRestorePosSize.Left() + pState->mnHeight; + } + else if( mbMaximizedHorz || mbMaximizedVert ) + GetDisplay()->getWMAdaptor()->maximizeFrame( this, false, false ); + + if (pState->mnState & SAL_FRAMESTATE_MINIMIZED) + { + if (nShowState_ == SHOWSTATE_UNKNOWN) + nShowState_ = SHOWSTATE_NORMAL; + Minimize(); + } + if (pState->mnState & SAL_FRAMESTATE_NORMAL) + { + if (nShowState_ != SHOWSTATE_NORMAL) + Restore(); + } + if (pState->mnState & SAL_FRAMESTATE_ROLLUP) + GetDisplay()->getWMAdaptor()->shade( this, true ); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +sal_Bool X11SalFrame::GetWindowState( SalFrameState* pState ) +{ + if( SHOWSTATE_MINIMIZED == nShowState_ ) + pState->mnState = SAL_FRAMESTATE_MINIMIZED; + else + pState->mnState = SAL_FRAMESTATE_NORMAL; + + Rectangle aPosSize; + if( maRestorePosSize.IsEmpty() ) + GetPosSize( aPosSize ); + else + aPosSize = maRestorePosSize; + + if( mbMaximizedHorz ) + pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_HORZ; + if( mbMaximizedVert ) + pState->mnState |= SAL_FRAMESTATE_MAXIMIZED_VERT; + if( mbShaded ) + pState->mnState |= SAL_FRAMESTATE_ROLLUP; + + pState->mnX = aPosSize.Left(); + pState->mnY = aPosSize.Top(); + pState->mnWidth = aPosSize.GetWidth(); + pState->mnHeight = aPosSize.GetHeight(); + + pState->mnMask = _FRAMESTATE_MASK_GEOMETRY | SAL_FRAMESTATE_MASK_STATE; + + + if (! maRestorePosSize.IsEmpty() ) + { + GetPosSize( aPosSize ); + pState->mnState |= SAL_FRAMESTATE_MAXIMIZED; + pState->mnMaximizedX = aPosSize.Left(); + pState->mnMaximizedY = aPosSize.Top(); + pState->mnMaximizedWidth = aPosSize.GetWidth(); + pState->mnMaximizedHeight = aPosSize.GetHeight(); + pState->mnMask |= _FRAMESTATE_MASK_MAXIMIZED_GEOMETRY; + } + + return sal_True; +} + +// ---------------------------------------------------------------------------- +// get a screenshot of the current frame including window manager decoration +SalBitmap* X11SalFrame::SnapShot() +{ + Display* pDisplay = GetXDisplay(); + + // make sure the frame has been reparented and all paint timer have been + // expired + do + { + XSync(pDisplay, False); + Application::Reschedule (); + } + while (XPending(pDisplay)); + TimeValue aVal; + aVal.Seconds = 0; + aVal.Nanosec = 50000000; + osl_waitThread( &aVal ); + do + { + XSync(pDisplay, False); + Application::Reschedule (); + } + while (XPending(pDisplay)); + + // get the most outer window, usually the window manager decoration + Drawable hWindow = None; + if (IsOverrideRedirect()) + hWindow = GetDrawable(); + else + if (hPresentationWindow != None) + hWindow = hPresentationWindow; + else + hWindow = GetStackingWindow(); + + // query the contents of the window + if (hWindow != None) + { + X11SalBitmap *pBmp = new X11SalBitmap; + if (pBmp->SnapShot (pDisplay, hWindow)) + return pBmp; + else + delete pBmp; + } + + return NULL; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// native menu implementation - currently empty +void X11SalFrame::DrawMenuBar() +{ +} + +void X11SalFrame::SetMenu( SalMenu* ) +{ +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::GetPosSize( Rectangle &rPosSize ) +{ + if( maGeometry.nWidth < 1 || maGeometry.nHeight < 1 ) + { + const Size& aScreenSize = pDisplay_->getDataForScreen( m_nScreen ).m_aSize; + long w = aScreenSize.Width() - maGeometry.nLeftDecoration - maGeometry.nRightDecoration; + long h = aScreenSize.Height() - maGeometry.nTopDecoration - maGeometry.nBottomDecoration; + + rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), Size( w, h ) ); + } + else + rPosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), + Size( maGeometry.nWidth, maGeometry.nHeight ) ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::SetSize( const Size &rSize ) +{ + if( rSize.Width() > 0 && rSize.Height() > 0 ) + { + if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) + && ! IsChildWindow() + && ( nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT ) + { + XSizeHints* pHints = XAllocSizeHints(); + long nSupplied = 0; + XGetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints, + &nSupplied + ); + pHints->min_width = rSize.Width(); + pHints->min_height = rSize.Height(); + pHints->max_width = rSize.Width(); + pHints->max_height = rSize.Height(); + pHints->flags |= PMinSize | PMaxSize; + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree( pHints ); + } + XResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), rSize.Width(), rSize.Height() ); + if( GetWindow() != GetShellWindow() ) + { + if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) ) + XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, rSize.Width(), rSize.Height() ); + else + XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() ); + } + + maGeometry.nWidth = rSize.Width(); + maGeometry.nHeight = rSize.Height(); + + // allow the external status window to reposition + if (mbInputFocus && mpInputContext != NULL) + mpInputContext->SetICFocus ( this ); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetPosSize( const Rectangle &rPosSize ) +{ + XWindowChanges values; + values.x = rPosSize.Left(); + values.y = rPosSize.Top(); + values.width = rPosSize.GetWidth(); + values.height = rPosSize.GetHeight(); + + if( !values.width || !values.height ) + return; + + if( mpParent && ! IsSysChildWindow() ) + { + // --- RTL --- (mirror window pos) + if( Application::GetSettings().GetLayoutRTL() ) + values.x = mpParent->maGeometry.nWidth-values.width-1-values.x; + + XLIB_Window aChild; + // coordinates are relative to parent, so translate to root coordinates + XTranslateCoordinates( GetDisplay()->GetDisplay(), + mpParent->GetWindow(), + GetDisplay()->GetRootWindow( m_nScreen ), + values.x, values.y, + &values.x, &values.y, + & aChild ); + } + + bool bMoved = false; + bool bSized = false; + if( values.x != maGeometry.nX || values.y != maGeometry.nY ) + bMoved = true; + if( values.width != (int)maGeometry.nWidth || values.height != (int)maGeometry.nHeight ) + bSized = true; + + if( ! ( nStyle_ & ( SAL_FRAME_STYLE_PLUG | SAL_FRAME_STYLE_FLOAT ) ) + && !(pDisplay_->GetProperties() & PROPERTY_SUPPORT_WM_ClientPos) ) + { + values.x -= maGeometry.nLeftDecoration; + values.y -= maGeometry.nTopDecoration; + } + + // do net set WMNormalHints for .. + if( + // child windows + ! IsChildWindow() + // popups (menu, help window, etc.) + && (nStyle_ & (SAL_FRAME_STYLE_FLOAT|SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) != SAL_FRAME_STYLE_FLOAT + // shown, sizeable windows + && ( nShowState_ == SHOWSTATE_UNKNOWN || + nShowState_ == SHOWSTATE_HIDDEN || + ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) + ) + ) + { + XSizeHints* pHints = XAllocSizeHints(); + long nSupplied = 0; + XGetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints, + &nSupplied + ); + if( ! ( nStyle_ & SAL_FRAME_STYLE_SIZEABLE ) ) + { + pHints->min_width = rPosSize.GetWidth(); + pHints->min_height = rPosSize.GetHeight(); + pHints->max_width = rPosSize.GetWidth(); + pHints->max_height = rPosSize.GetHeight(); + pHints->flags |= PMinSize | PMaxSize; + } + if( nShowState_ == SHOWSTATE_UNKNOWN || nShowState_ == SHOWSTATE_HIDDEN ) + { + pHints->flags |= PPosition | PWinGravity; + pHints->x = values.x; + pHints->y = values.y; + pHints->win_gravity = pDisplay_->getWMAdaptor()->getPositionWinGravity(); + } + if( mbFullScreen ) + { + pHints->max_width = 10000; + pHints->max_height = 10000; + pHints->flags |= PMaxSize; + } + XSetWMNormalHints( GetXDisplay(), + GetShellWindow(), + pHints ); + XFree( pHints ); + } + + XMoveResizeWindow( GetXDisplay(), IsSysChildWindow() ? GetWindow() : GetShellWindow(), values.x, values.y, values.width, values.height ); + if( GetShellWindow() != GetWindow() ) + { + if( (nStyle_ & SAL_FRAME_STYLE_PLUG ) ) + XMoveResizeWindow( GetXDisplay(), GetWindow(), 0, 0, values.width, values.height ); + else + XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height ); + } + + maGeometry.nX = values.x; + maGeometry.nY = values.y; + maGeometry.nWidth = values.width; + maGeometry.nHeight = values.height; + if( IsSysChildWindow() && mpParent ) + { + // translate back to root coordinates + maGeometry.nX += mpParent->maGeometry.nX; + maGeometry.nY += mpParent->maGeometry.nY; + } + + updateScreenNumber(); + if( bSized && ! bMoved ) + CallCallback( SALEVENT_RESIZE, NULL ); + else if( bMoved && ! bSized ) + CallCallback( SALEVENT_MOVE, NULL ); + else + CallCallback( SALEVENT_MOVERESIZE, NULL ); + + // allow the external status window to reposition + if (mbInputFocus && mpInputContext != NULL) + mpInputContext->SetICFocus ( this ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::Minimize() +{ + if( IsSysChildWindow() ) + return; + + if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ ) + { + stderr0( "X11SalFrame::Minimize on withdrawn window\n" ); + return; + } + + if( XIconifyWindow( GetXDisplay(), + GetShellWindow(), + pDisplay_->GetDefaultScreenNumber() ) ) + nShowState_ = SHOWSTATE_MINIMIZED; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::Maximize() +{ + if( IsSysChildWindow() ) + return; + + if( SHOWSTATE_MINIMIZED == nShowState_ ) + { + GetDisplay()->getWMAdaptor()->frameIsMapping( this ); + XMapWindow( GetXDisplay(), GetShellWindow() ); + nShowState_ = SHOWSTATE_NORMAL; + } + + pDisplay_->getWMAdaptor()->maximizeFrame( this, true, true ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::Restore() +{ + if( IsSysChildWindow() ) + return; + + if( SHOWSTATE_UNKNOWN == nShowState_ || SHOWSTATE_HIDDEN == nShowState_ ) + { + stderr0( "X11SalFrame::Restore on withdrawn window\n" ); + return; + } + + if( SHOWSTATE_MINIMIZED == nShowState_ ) + { + GetDisplay()->getWMAdaptor()->frameIsMapping( this ); + XMapWindow( GetXDisplay(), GetShellWindow() ); + nShowState_ = SHOWSTATE_NORMAL; + } + + pDisplay_->getWMAdaptor()->maximizeFrame( this, false, false ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetScreenNumber( unsigned int nNewScreen ) +{ + if( nNewScreen == maGeometry.nScreenNumber ) + return; + + if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) + { + if( nNewScreen >= GetDisplay()->GetXineramaScreens().size() ) + return; + + Rectangle aOldScreenRect( GetDisplay()->GetXineramaScreens()[maGeometry.nScreenNumber] ); + Rectangle aNewScreenRect( GetDisplay()->GetXineramaScreens()[nNewScreen] ); + bool bVisible = bMapped_; + if( bVisible ) + Show( sal_False ); + maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left()); + maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top()); + createNewWindow( None, m_nScreen ); + if( bVisible ) + Show( sal_True ); + maGeometry.nScreenNumber = nNewScreen; + } + else if( sal_Int32(nNewScreen) < GetDisplay()->GetScreenCount() ) + { + bool bVisible = bMapped_; + if( bVisible ) + Show( sal_False ); + createNewWindow( None, nNewScreen ); + if( bVisible ) + Show( sal_True ); + maGeometry.nScreenNumber = nNewScreen; + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nScreen ) +{ + if( GetDisplay()->IsXinerama() && GetDisplay()->GetXineramaScreens().size() > 1 ) + { + if( mbFullScreen == (bool)bFullScreen ) + return; + if( bFullScreen ) + { + maRestorePosSize = Rectangle( Point( maGeometry.nX, maGeometry.nY ), + Size( maGeometry.nWidth, maGeometry.nHeight ) ); + Rectangle aRect; + if( nScreen < 0 || nScreen >= static_cast<int>(GetDisplay()->GetXineramaScreens().size()) ) + aRect = Rectangle( Point(0,0), GetDisplay()->GetScreenSize( m_nScreen ) ); + else + aRect = GetDisplay()->GetXineramaScreens()[nScreen]; + nStyle_ |= SAL_FRAME_STYLE_PARTIAL_FULLSCREEN; + bool bVisible = bMapped_; + if( bVisible ) + Show( sal_False ); + maGeometry.nX = aRect.Left(); + maGeometry.nY = aRect.Top(); + maGeometry.nWidth = aRect.GetWidth(); + maGeometry.nHeight = aRect.GetHeight(); + mbMaximizedHorz = mbMaximizedVert = false; + mbFullScreen = true; + createNewWindow( None, m_nScreen ); + if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() ) + GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true ); + else + GetDisplay()->getWMAdaptor()->showFullScreen( this, true ); + if( bVisible ) + Show(sal_True); + + } + else + { + mbFullScreen = false; + nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN; + bool bVisible = bMapped_; + Rectangle aRect = maRestorePosSize; + maRestorePosSize = Rectangle(); + if( bVisible ) + Show( sal_False ); + createNewWindow( None, m_nScreen ); + if( !aRect.IsEmpty() ) + SetPosSize( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), + SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | + SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); + if( bVisible ) + Show( sal_True ); + } + } + else + { + if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) + nScreen = m_nScreen; + if( nScreen != m_nScreen ) + { + bool bVisible = bMapped_; + if( mbFullScreen ) + pDisplay_->getWMAdaptor()->showFullScreen( this, false ); + if( bVisible ) + Show( sal_False ); + createNewWindow( None, nScreen ); + if( mbFullScreen ) + pDisplay_->getWMAdaptor()->showFullScreen( this, true ); + if( bVisible ) + Show( sal_True ); + } + if( mbFullScreen == (bool)bFullScreen ) + return; + + pDisplay_->getWMAdaptor()->showFullScreen( this, bFullScreen ); + if( IsOverrideRedirect() + && WMSupportsFWS( GetXDisplay(), GetDisplay()->GetRootWindow( m_nScreen ) ) ) + { + AddFwsProtocols( GetXDisplay(), GetShellWindow() ); + RegisterFwsWindow( GetXDisplay(), GetShellWindow() ); + } + } +} + +/* --------------------------------------------------------------------- + the xautolock pseudo screen saver needs special treatment since it + doesn't cooperate with XxxxScreenSaver settings + ------------------------------------------------------------------- */ + +static Bool +IsRunningXAutoLock( Display *p_display, XLIB_Window a_window ) +{ + const char *p_atomname = "XAUTOLOCK_SEMAPHORE_PID"; + Atom a_pidatom; + + // xautolock interns this atom + a_pidatom = XInternAtom( p_display, p_atomname, True ); + if ( a_pidatom == None ) + return False; + + Atom a_type; + int n_format; + unsigned long n_items; + unsigned long n_bytes_after; + pid_t *p_pid; + pid_t n_pid; + // get pid of running xautolock + XGetWindowProperty (p_display, a_window, a_pidatom, 0L, 2L, False, + AnyPropertyType, &a_type, &n_format, &n_items, &n_bytes_after, + (unsigned char**) &p_pid ); + n_pid = *p_pid; + XFree( p_pid ); + + if ( a_type == XA_INTEGER ) + { + // check if xautolock pid points to a running process + if ( kill(n_pid, 0) == -1 ) + return False; + else + return True; + } + + return False; +} + +/* definitions from xautolock.c (pl15) */ +#define XAUTOLOCK_DISABLE 1 +#define XAUTOLOCK_ENABLE 2 + +static Bool +MessageToXAutoLock( Display *p_display, int n_message ) +{ + const char *p_atomname = "XAUTOLOCK_MESSAGE" ; + Atom a_messageatom; + XLIB_Window a_rootwindow; + + a_rootwindow = RootWindowOfScreen( ScreenOfDisplay(p_display, 0) ); + if ( ! IsRunningXAutoLock(p_display, a_rootwindow) ) + { + // remove any pending messages + a_messageatom = XInternAtom( p_display, p_atomname, True ); + if ( a_messageatom != None ) + XDeleteProperty( p_display, a_rootwindow, a_messageatom ); + return False; + } + + a_messageatom = XInternAtom( p_display, p_atomname, False ); + XChangeProperty (p_display, a_rootwindow, a_messageatom, XA_INTEGER, + 8, PropModeReplace, (unsigned char*)&n_message, sizeof(n_message) ); + + return True; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::StartPresentation( sal_Bool bStart ) +{ + I18NStatus::get().show( !bStart, I18NStatus::presentation ); + if ( bStart ) + MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_DISABLE ); + else + MessageToXAutoLock( GetXDisplay(), XAUTOLOCK_ENABLE ); + + if( ! bStart && hPresentationWindow != None ) + doReparentPresentationDialogues( GetDisplay() ); + hPresentationWindow = (bStart && IsOverrideRedirect() ) ? GetWindow() : None; + + + // needs static here to save DPMS settings + int dummy; + static bool DPMSExtensionAvailable = +#ifndef SOLARIS + (DPMSQueryExtension(GetXDisplay(), &dummy, &dummy) != 0); + static sal_Bool DPMSEnabled = false; +#else + false; + bool DPMSEnabled = false; + (void)dummy; +#define CARD16 unsigned short +#endif + static CARD16 dpms_standby_timeout=0; + static CARD16 dpms_suspend_timeout=0; + static CARD16 dpms_off_timeout=0; + + + if( bStart || nScreenSaversTimeout_ || DPMSEnabled) + { + if( hPresentationWindow ) + { + /* #i10559# workaround for WindowMaker: try to restore + * current focus after presentation window is gone + */ + int revert_to = 0; + XGetInputFocus( GetXDisplay(), &hPresFocusWindow, &revert_to ); + } + int timeout, interval, prefer_blanking, allow_exposures; + XGetScreenSaver( GetXDisplay(), + &timeout, + &interval, + &prefer_blanking, + &allow_exposures ); + + + // get the DPMS state right before the start + if (DPMSExtensionAvailable) + { +#ifndef SOLARIS + CARD16 state; // card16 is defined in Xdm.h + DPMSInfo( GetXDisplay(), + &state, + &DPMSEnabled); +#endif + } + if( bStart ) // start show + { + if ( timeout ) + { + nScreenSaversTimeout_ = timeout; + XResetScreenSaver( GetXDisplay() ); + XSetScreenSaver( GetXDisplay(), + 0, + interval, + prefer_blanking, + allow_exposures ); + } +#ifndef SOLARIS + if( DPMSEnabled ) + { + if ( DPMSExtensionAvailable ) + { + DPMSGetTimeouts( GetXDisplay(), + &dpms_standby_timeout, + &dpms_suspend_timeout, + &dpms_off_timeout); + DPMSSetTimeouts(GetXDisplay(), 0,0,0); + } + } +#endif + } + else // if( !bStart ) // end of show + { + if( nScreenSaversTimeout_ ) + { + XSetScreenSaver( GetXDisplay(), + nScreenSaversTimeout_, + interval, + prefer_blanking, + allow_exposures ); + nScreenSaversTimeout_ = 0; + } +#ifndef SOLARIS + if ( DPMSEnabled ) + { + if ( DPMSExtensionAvailable ) + { + // restore timeouts + DPMSSetTimeouts(GetXDisplay(), dpms_standby_timeout, + dpms_suspend_timeout, dpms_off_timeout); + } + } +#endif + } + } +} + +// Pointer +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::SetPointer( PointerStyle ePointerStyle ) +{ + hCursor_ = pDisplay_->GetPointer( ePointerStyle ); + XDefineCursor( GetXDisplay(), GetWindow(), hCursor_ ); + + if( IsCaptured() || nVisibleFloats > 0 ) + XChangeActivePointerGrab( GetXDisplay(), + PointerMotionMask|ButtonPressMask|ButtonReleaseMask, + hCursor_, + CurrentTime ); +} + +void X11SalFrame::SetPointerPos(long nX, long nY) +{ + /* #87921# when the application tries to center the mouse in the dialog the + * window isn't mapped already. So use coordinates relative to the root window. + */ + unsigned int nWindowLeft = maGeometry.nX + nX; + unsigned int nWindowTop = maGeometry.nY + nY; + + XWarpPointer( GetXDisplay(), None, pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ), + 0, 0, 0, 0, nWindowLeft, nWindowTop); +} + +// delay handling of extended text input +#if !defined(__synchronous_extinput__) +void +X11SalFrame::PostExtTextEvent (sal_uInt16 nExtTextEventType, void *pExtTextEvent) +{ + XLIB_Window nFocusWindow = GetWindow(); + Atom nEventAtom = GetDisplay()->getWMAdaptor()->getAtom( WMAdaptor::SAL_EXTTEXTEVENT ); + + XEvent aEvent; + aEvent.xclient.type = ClientMessage; + aEvent.xclient.serial = 0; + aEvent.xclient.send_event = True; + aEvent.xclient.display = GetXDisplay(); + aEvent.xclient.window = nFocusWindow; + aEvent.xclient.message_type = nEventAtom; + aEvent.xclient.format = 32; + +#if SAL_TYPES_SIZEOFLONG > 4 + aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent & 0xffffffff); + aEvent.xclient.data.l[1] = (sal_uInt32)((long)pExtTextEvent >> 32); +#else + aEvent.xclient.data.l[0] = (sal_uInt32)((long)pExtTextEvent); + aEvent.xclient.data.l[1] = 0; +#endif + aEvent.xclient.data.l[2] = (sal_uInt32)nExtTextEventType; + aEvent.xclient.data.l[3] = 0; + aEvent.xclient.data.l[4] = 0; + + XPutBackEvent( GetXDisplay(), &aEvent ); +} + +void +X11SalFrame::HandleExtTextEvent (XClientMessageEvent *pEvent) +{ + #if SAL_TYPES_SIZEOFLONG > 4 + void* pExtTextEvent = (void*)( (pEvent->data.l[0] & 0xffffffff) + | (pEvent->data.l[1] << 32) ); + #else + void* pExtTextEvent = (void*)(pEvent->data.l[0]); + #endif + sal_uInt16 nExtTextEventType = sal_uInt16(pEvent->data.l[2]); + + CallCallback(nExtTextEventType, pExtTextEvent); + + switch (nExtTextEventType) + { + case SALEVENT_ENDEXTTEXTINPUT: + break; + + case SALEVENT_EXTTEXTINPUT: + break; + + default: + + fprintf(stderr, "X11SalFrame::HandleExtTextEvent: invalid extended input\n"); + } +} +#endif /* defined(__synchronous_extinput__) */ + +// PostEvent +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +sal_Bool X11SalFrame::PostEvent( void *pData ) +{ + GetDisplay()->SendInternalEvent( this, pData ); + return sal_True; +} + +// Title +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::SetTitle( const XubString& rTitle ) +{ + if( ! ( IsChildWindow() || (nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) ) + { + m_aTitle = rTitle; + GetDisplay()->getWMAdaptor()->setWMName( this, rTitle ); + } +} + +// ----------------------------------------------------------------------- + +void X11SalFrame::Flush() +{ + XFlush( GetDisplay()->GetDisplay() ); +} + +// ----------------------------------------------------------------------- + +void X11SalFrame::Sync() +{ + XSync( GetDisplay()->GetDisplay(), False ); +} + +// Keyboard +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +// ----------------------------------------------------------------------- + +void X11SalFrame::SetInputContext( SalInputContext* pContext ) +{ + if (pContext == NULL) + return; + + // 1. We should create an input context for this frame + // only when SAL_INPUTCONTEXT_TEXT is set. + + if (!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) + { + if( mpInputContext ) + mpInputContext->Unmap( this ); + return; + } + + // 2. We should use on-the-spot inputstyle + // only when SAL_INPUTCONTEXT_EXTTEXTINPUT is set. + + if (mpInputContext == NULL) + { + I18NStatus& rStatus( I18NStatus::get() ); + rStatus.setParent( this ); + mpInputContext = new SalI18N_InputContext( this ); + if (mpInputContext->UseContext()) + { + mpInputContext->ExtendEventMask( GetShellWindow() ); + if (pContext->mnOptions & SAL_INPUTCONTEXT_CHANGELANGUAGE) + mpInputContext->SetLanguage(pContext->meLanguage); + if (mbInputFocus) + mpInputContext->SetICFocus( this ); + } + } + else + mpInputContext->Map( this ); + return; +} + +// ----------------------------------------------------------------------- + +void X11SalFrame::EndExtTextInput( sal_uInt16 nFlags ) +{ + if (mpInputContext != NULL) + mpInputContext->EndExtTextInput( nFlags ); +} + +// ----------------------------------------------------------------------- + +XubString X11SalFrame::GetKeyName( sal_uInt16 nKeyCode ) +{ + return GetDisplay()->GetKeyName( nKeyCode ); +} + +XubString X11SalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode ) +{ + return GetKeyName( nKeyCode ); +} + +sal_Bool X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) +{ + // not supported yet + return sal_False; +} + +LanguageType X11SalFrame::GetInputLanguage() +{ + // could be improved by checking unicode ranges of the last input + return LANGUAGE_DONTKNOW; +} + +// Settings +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +inline Color getColorFromLong( long nColor ) +{ + return Color( (nColor & 0xff), (nColor & 0xff00)>>8, (nColor & 0xff0000)>>16); +} + +void X11SalFrame::UpdateSettings( AllSettings& rSettings ) +{ + + DtIntegrator* pIntegrator = GetDisplay()->getDtIntegrator(); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "DtIntegrator: %d\n", pIntegrator ? pIntegrator->GetDtType() : -1 ); +#endif + if( pIntegrator ) + pIntegrator->GetSystemLook( rSettings ); +} + +void X11SalFrame::CaptureMouse( sal_Bool bCapture ) +{ + nCaptured_ = pDisplay_->CaptureMouse( bCapture ? this : NULL ); +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +void X11SalFrame::SetParent( SalFrame* pNewParent ) +{ + if( mpParent != pNewParent ) + { + if( mpParent ) + mpParent->maChildren.remove( this ); + + mpParent = static_cast<X11SalFrame*>(pNewParent); + mpParent->maChildren.push_back( this ); + if( mpParent->m_nScreen != m_nScreen ) + createNewWindow( None, mpParent->m_nScreen ); + GetDisplay()->getWMAdaptor()->changeReferenceFrame( this, mpParent ); + } +} + +SalFrame* X11SalFrame::GetParent() const +{ + return mpParent; +} + +void X11SalFrame::createNewWindow( XLIB_Window aNewParent, int nScreen ) +{ + bool bWasVisible = bMapped_; + if( bWasVisible ) + Show( sal_False ); + + if( nScreen < 0 || nScreen >= GetDisplay()->GetScreenCount() ) + nScreen = m_nScreen; + + SystemParentData aParentData; + aParentData.aWindow = aNewParent; + aParentData.bXEmbedSupport = (aNewParent != None && m_bXEmbed); // caution: this is guesswork + if( aNewParent == None ) + { + aNewParent = GetDisplay()->GetRootWindow(nScreen); + aParentData.aWindow = None; + m_bXEmbed = false; + } + else + { + // is new parent a root window ? + Display* pDisp = GetDisplay()->GetDisplay(); + int nScreens = GetDisplay()->GetScreenCount(); + for( int i = 0; i < nScreens; i++ ) + { + if( aNewParent == RootWindow( pDisp, i ) ) + { + nScreen = i; + aParentData.aWindow = None; + m_bXEmbed = false; + break; + } + } + } + + // first deinit frame + updateGraphics(true); + if( mpInputContext ) + { + mpInputContext->UnsetICFocus( this ); + mpInputContext->Unmap( this ); + } + if( GetWindow() == hPresentationWindow ) + { + hPresentationWindow = None; + doReparentPresentationDialogues( GetDisplay() ); + } + XDestroyWindow( GetXDisplay(), mhWindow ); + mhWindow = None; + + passOnSaveYourSelf(); + + // now init with new parent again + if ( aParentData.aWindow != None ) + Init( nStyle_ | SAL_FRAME_STYLE_PLUG, nScreen, &aParentData ); + else + Init( nStyle_ & ~SAL_FRAME_STYLE_PLUG, nScreen, NULL, true ); + + // update graphics if necessary + updateGraphics(false); + + if( m_aTitle.Len() ) + SetTitle( m_aTitle ); + + if( mpParent ) + { + if( mpParent->m_nScreen != m_nScreen ) + SetParent( NULL ); + else + pDisplay_->getWMAdaptor()->changeReferenceFrame( this, mpParent ); + } + + if( bWasVisible ) + Show( sal_True ); + + std::list< X11SalFrame* > aChildren = maChildren; + for( std::list< X11SalFrame* >::iterator it = aChildren.begin(); it != aChildren.end(); ++it ) + (*it)->createNewWindow( None, m_nScreen ); + + // FIXME: SalObjects +} + +bool X11SalFrame::SetPluginParent( SystemParentData* pNewParent ) +{ + if( pNewParent->nSize >= sizeof(SystemParentData) ) + m_bXEmbed = pNewParent->aWindow != None && pNewParent->bXEmbedSupport; + createNewWindow( pNewParent ? pNewParent->aWindow : None ); + + return true; +} + +// Sound +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +void X11SalFrame::Beep( SoundType eSoundType ) // not fully suported +{ + switch( eSoundType ) + { + case SOUND_DEFAULT: + case SOUND_ERROR: + GetDisplay()->Beep(); + break; + default: + // Excessive beeping averted + break; + } +} + +// Event Handling +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +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; + + // Map Meta/Super modifier to MOD3 on all Unix systems + // except Mac OS X + if( (state & Mod3Mask) ) + nCode |= KEY_MOD3; + + return nCode; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +SalFrame::SalPointerState X11SalFrame::GetPointerState() +{ + SalPointerState aState; + XLIB_Window aRoot, aChild; + int rx, ry, wx, wy; + unsigned int nMask = 0; + XQueryPointer( GetXDisplay(), + GetShellWindow(), + &aRoot, + &aChild, + &rx, &ry, + &wx, &wy, + &nMask + ); + + aState.maPos = Point(wx, wy); + aState.mnState = sal_GetCode( nMask ); + return aState; +} + +long X11SalFrame::HandleMouseEvent( XEvent *pEvent ) +{ + SalMouseEvent aMouseEvt; + sal_uInt16 nEvent = 0; + bool bClosePopups = false; + + if( nVisibleFloats && pEvent->type == EnterNotify ) + return 0; + + // Solaris X86: clicking the right button on a two-button mouse + // generates a button2 event not a button3 event + if (pDisplay_->GetProperties() & PROPERTY_SUPPORT_3ButtonMouse ) + { + switch (pEvent->type) + { + case EnterNotify: + case LeaveNotify: + if ( pEvent->xcrossing.state & Button2Mask ) + { + pEvent->xcrossing.state &= ~Button2Mask; + pEvent->xcrossing.state |= Button3Mask; + } + break; + + case MotionNotify: + if ( pEvent->xmotion.state & Button2Mask ) + { + pEvent->xmotion.state &= ~Button2Mask; + pEvent->xmotion.state |= Button3Mask; + } + break; + + default: + if ( Button2 == pEvent->xbutton.button ) + { + pEvent->xbutton.state &= ~Button2Mask; + pEvent->xbutton.state |= Button3Mask; + pEvent->xbutton.button = Button3; + } + break; + } + } + + + if( LeaveNotify == pEvent->type || EnterNotify == pEvent->type ) + { + /* + * #89075# #89335# + * + * some WMs (and/or) applications have a passive grab on + * mouse buttons (XGrabButton). This leads to enter/leave notifies + * with mouse buttons pressed in the state mask before the actual + * ButtonPress event gets dispatched. But EnterNotify + * is reported in vcl as MouseMove event. Some office code + * decides that a pressed button in a MouseMove belongs to + * a drag operation which leads to doing things differently. + * + * #95901# + * ignore Enter/LeaveNotify resulting from grabs so that + * help windows do not disappear just after appearing + * + * hopefully this workaround will not break anything. + */ + if( pEvent->xcrossing.mode == NotifyGrab || pEvent->xcrossing.mode == NotifyUngrab ) + return 0; + + aMouseEvt.mnX = pEvent->xcrossing.x; + aMouseEvt.mnY = pEvent->xcrossing.y; + aMouseEvt.mnTime = pEvent->xcrossing.time; + aMouseEvt.mnCode = sal_GetCode( pEvent->xcrossing.state ); + aMouseEvt.mnButton = 0; + + nEvent = LeaveNotify == pEvent->type + ? SALEVENT_MOUSELEAVE + : SALEVENT_MOUSEMOVE; + } + else if( pEvent->type == MotionNotify ) + { + aMouseEvt.mnX = pEvent->xmotion.x; + aMouseEvt.mnY = pEvent->xmotion.y; + aMouseEvt.mnTime = pEvent->xmotion.time; + aMouseEvt.mnCode = sal_GetCode( pEvent->xmotion.state ); + + aMouseEvt.mnButton = 0; + + nEvent = SALEVENT_MOUSEMOVE; + if( nVisibleFloats > 0 && mpParent ) + { + XLIB_Cursor aCursor = mpParent->GetCursor(); + if( pEvent->xmotion.x >= 0 && pEvent->xmotion.x < (int)maGeometry.nWidth && + pEvent->xmotion.y >= 0 && pEvent->xmotion.y < (int)maGeometry.nHeight ) + aCursor = None; + + XChangeActivePointerGrab( GetXDisplay(), + PointerMotionMask|ButtonPressMask|ButtonReleaseMask, + aCursor, + CurrentTime ); + } + } + else + { + // let mouse events reach the correct window + if( nVisibleFloats < 1 ) + { + if( ! (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) + XUngrabPointer( GetXDisplay(), CurrentTime ); + } + else if( pEvent->type == ButtonPress ) + { + // see if the user clicks outside all of the floats + // if yes release the grab + bool bInside = false; + const std::list< SalFrame* >& rFrames = GetDisplay()->getFrames(); + for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) + { + const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); + if( pFrame->IsFloatGrabWindow() && + pFrame->bMapped_ && + pEvent->xbutton.x_root >= pFrame->maGeometry.nX && + pEvent->xbutton.x_root < pFrame->maGeometry.nX + (int)pFrame->maGeometry.nWidth && + pEvent->xbutton.y_root >= pFrame->maGeometry.nY && + pEvent->xbutton.y_root < pFrame->maGeometry.nY + (int)pFrame->maGeometry.nHeight ) + { + bInside = true; + break; + } + } + if( ! bInside ) + { + // need not take care of the XUngrabPointer in Show( sal_False ) + // because XUngrabPointer does not produce errors if pointer + // is not grabbed + XUngrabPointer( GetXDisplay(), CurrentTime ); + bClosePopups = true; + + /* #i15246# only close popups if pointer is outside all our frames + * cannot use our own geometry data here because stacking + * is unknown (the above case implicitly assumes + * that floats are on top which should be true) + */ + XLIB_Window aRoot, aChild; + int root_x, root_y, win_x, win_y; + unsigned int mask_return; + if( XQueryPointer( GetXDisplay(), + GetDisplay()->GetRootWindow( m_nScreen ), + &aRoot, &aChild, + &root_x, &root_y, + &win_x, &win_y, + &mask_return ) + && aChild // pointer may not be in any child + ) + { + for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it ) + { + const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); + if( ! pFrame->IsFloatGrabWindow() + && ( pFrame->GetWindow() == aChild || + pFrame->GetShellWindow() == aChild || + pFrame->GetStackingWindow() == aChild ) + ) + { + // #i63638# check that pointer is inside window, not + // only inside stacking window + if( root_x >= pFrame->maGeometry.nX && root_x < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nWidth) && + root_y >= pFrame->maGeometry.nY && root_y < sal::static_int_cast< int >(pFrame->maGeometry.nX+pFrame->maGeometry.nHeight) ) + { + bClosePopups = false; + } + break; + } + } + } + } + } + + if( m_bXEmbed && pEvent->xbutton.button == Button1 ) + askForXEmbedFocus( pEvent->xbutton.time ); + + if( pEvent->xbutton.button == Button1 || + pEvent->xbutton.button == Button2 || + pEvent->xbutton.button == Button3 ) + { + aMouseEvt.mnX = pEvent->xbutton.x; + aMouseEvt.mnY = pEvent->xbutton.y; + aMouseEvt.mnTime = pEvent->xbutton.time; + aMouseEvt.mnCode = sal_GetCode( pEvent->xbutton.state ); + + if( Button1 == pEvent->xbutton.button ) + aMouseEvt.mnButton = MOUSE_LEFT; + else if( Button2 == pEvent->xbutton.button ) + aMouseEvt.mnButton = MOUSE_MIDDLE; + else if( Button3 == pEvent->xbutton.button ) + aMouseEvt.mnButton = MOUSE_RIGHT; + + nEvent = ButtonPress == pEvent->type + ? SALEVENT_MOUSEBUTTONDOWN + : SALEVENT_MOUSEBUTTONUP; + } + else if( pEvent->xbutton.button == Button4 || + pEvent->xbutton.button == Button5 || + pEvent->xbutton.button == Button6 || + pEvent->xbutton.button == Button7 ) + { + const bool bIncrement( + pEvent->xbutton.button == Button4 || + pEvent->xbutton.button == Button6 ); + const bool bHoriz( + pEvent->xbutton.button == Button6 || + pEvent->xbutton.button == Button7 ); + + if( pEvent->type == ButtonRelease ) + return 0; + + static sal_uLong nLines = 0; + if( ! nLines ) + { + char* pEnv = getenv( "SAL_WHEELLINES" ); + nLines = pEnv ? atoi( pEnv ) : 3; + if( nLines > 10 ) + nLines = SAL_WHEELMOUSE_EVENT_PAGESCROLL; + } + + SalWheelMouseEvent aWheelEvt; + aWheelEvt.mnTime = pEvent->xbutton.time; + aWheelEvt.mnX = pEvent->xbutton.x; + aWheelEvt.mnY = pEvent->xbutton.y; + aWheelEvt.mnDelta = bIncrement ? 120 : -120; + aWheelEvt.mnNotchDelta = bIncrement ? 1 : -1; + aWheelEvt.mnScrollLines = nLines; + aWheelEvt.mnCode = sal_GetCode( pEvent->xbutton.state ); + aWheelEvt.mbHorz = bHoriz; + + nEvent = SALEVENT_WHEELMOUSE; + + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aWheelEvt.mnX = nWidth_-1-aWheelEvt.mnX; + return CallCallback( nEvent, &aWheelEvt ); + } + } + + int nRet = 0; + if( nEvent == SALEVENT_MOUSELEAVE + || ( aMouseEvt.mnX < nWidth_ && aMouseEvt.mnX > -1 && + aMouseEvt.mnY < nHeight_ && aMouseEvt.mnY > -1 ) + || pDisplay_->MouseCaptured( this ) + ) + { + // --- RTL --- (mirror mouse pos) + if( Application::GetSettings().GetLayoutRTL() ) + aMouseEvt.mnX = nWidth_-1-aMouseEvt.mnX; + nRet = CallCallback( nEvent, &aMouseEvt ); + } + + if( bClosePopups ) + { + /* #108213# close popups after dispatching the event outside the popup; + * applications do weird things. + */ + ImplSVData* pSVData = ImplGetSVData(); + if ( pSVData->maWinData.mpFirstFloat ) + { + static const char* pEnv = getenv( "SAL_FLOATWIN_NOAPPFOCUSCLOSE" ); + if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE) && !(pEnv && *pEnv) ) + pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL ); + } + } + + return nRet; +} + +// F10 means either KEY_F10 or KEY_MENU, which has to be decided +// in the independent part. +struct KeyAlternate +{ + sal_uInt16 nKeyCode; + sal_Unicode nCharCode; + KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {} + KeyAlternate( sal_uInt16 nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {} +}; + +inline KeyAlternate +GetAlternateKeyCode( const sal_uInt16 nKeyCode ) +{ + KeyAlternate aAlternate; + + switch( nKeyCode ) + { + case KEY_F10: aAlternate = KeyAlternate( KEY_MENU );break; + case KEY_F24: aAlternate = KeyAlternate( KEY_SUBTRACT, '-' );break; + } + + return aAlternate; +} + +void X11SalFrame::beginUnicodeSequence() +{ + rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); + DeletionListener aDeleteWatch( this ); + + if( rSeq.getLength() ) + endUnicodeSequence(); + + rSeq = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "u" ) ); + + if( ! aDeleteWatch.isDeleted() ) + { + sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE; + SalExtTextInputEvent aEv; + aEv.mnTime = 0; + aEv.maText = rSeq; + aEv.mpTextAttr = &nTextAttr; + aEv.mnCursorPos = 0; + aEv.mnDeltaStart = 0; + aEv.mnCursorFlags = 0; + aEv.mbOnlyCursor = sal_False; + + CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); + } +} + +bool X11SalFrame::appendUnicodeSequence( sal_Unicode c ) +{ + bool bRet = false; + rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); + if( rSeq.getLength() > 0 ) + { + // range check + if( (c >= sal_Unicode('0') && c <= sal_Unicode('9')) || + (c >= sal_Unicode('a') && c <= sal_Unicode('f')) || + (c >= sal_Unicode('A') && c <= sal_Unicode('F')) ) + { + rtl::OUStringBuffer aBuf( rSeq.getLength() + 1 ); + aBuf.append( rSeq ); + aBuf.append( c ); + rSeq = aBuf.makeStringAndClear(); + std::vector<sal_uInt16> attribs( rSeq.getLength(), SAL_EXTTEXTINPUT_ATTR_UNDERLINE ); + + SalExtTextInputEvent aEv; + aEv.mnTime = 0; + aEv.maText = rSeq; + aEv.mpTextAttr = &attribs[0]; + aEv.mnCursorPos = 0; + aEv.mnDeltaStart = 0; + aEv.mnCursorFlags = 0; + aEv.mbOnlyCursor = sal_False; + + CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); + bRet = true; + } + else + bRet = endUnicodeSequence(); + } + else + endUnicodeSequence(); + return bRet; +} + +bool X11SalFrame::endUnicodeSequence() +{ + rtl::OUString& rSeq( GetX11SalData()->GetUnicodeAccumulator() ); + + DeletionListener aDeleteWatch( this ); + if( rSeq.getLength() > 1 && rSeq.getLength() < 6 ) + { + // cut the "u" + rtl::OUString aNumbers( rSeq.copy( 1 ) ); + sal_Int32 nValue = aNumbers.toInt32( 16 ); + if( nValue >= 32 ) + { + sal_uInt16 nTextAttr = SAL_EXTTEXTINPUT_ATTR_UNDERLINE; + SalExtTextInputEvent aEv; + aEv.mnTime = 0; + aEv.maText = rtl::OUString( sal_Unicode(nValue) ); + aEv.mpTextAttr = &nTextAttr; + aEv.mnCursorPos = 0; + aEv.mnDeltaStart = 0; + aEv.mnCursorFlags = 0; + aEv.mbOnlyCursor = sal_False; + CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aEv); + } + } + bool bWasInput = rSeq.getLength() > 0; + rSeq = rtl::OUString(); + if( bWasInput && ! aDeleteWatch.isDeleted() ) + CallCallback(SALEVENT_ENDEXTTEXTINPUT, NULL); + return bWasInput; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleKeyEvent( XKeyEvent *pEvent ) +{ + KeySym nKeySym; + KeySym nUnmodifiedKeySym; + int nLen = 2048; + unsigned char *pPrintable = (unsigned char*)alloca( nLen ); + + // singlebyte code composed by input method, the new default + if (mpInputContext != NULL && mpInputContext->UseContext()) + { + // returns a keysym as well as the pPrintable (in system encoding) + // printable may be empty. + Status nStatus; + nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, + &nUnmodifiedKeySym, + &nStatus, mpInputContext->GetContext() ); + if ( nStatus == XBufferOverflow ) + { + nLen *= 2; + pPrintable = (unsigned char*)alloca( nLen ); + nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, + &nUnmodifiedKeySym, + &nStatus, mpInputContext->GetContext() ); + } + } + else + { + // fallback, this should never ever be called + Status nStatus = 0; + nKeySym = pDisplay_->GetKeySym( pEvent, pPrintable, &nLen, &nUnmodifiedKeySym, &nStatus ); + } + + SalKeyEvent aKeyEvt; + sal_uInt16 nKeyCode; + sal_uInt16 nModCode = 0; + char aDummy; + + if( pEvent->state & ShiftMask ) + nModCode |= KEY_SHIFT; + if( pEvent->state & ControlMask ) + nModCode |= KEY_MOD1; + if( pEvent->state & Mod1Mask ) + nModCode |= KEY_MOD2; + + if( nModCode != (KEY_SHIFT|KEY_MOD1) ) + endUnicodeSequence(); + + if( nKeySym == XK_Shift_L || nKeySym == XK_Shift_R + || nKeySym == XK_Control_L || nKeySym == XK_Control_R + || nKeySym == XK_Alt_L || nKeySym == XK_Alt_R + || nKeySym == XK_Meta_L || nKeySym == XK_Meta_R + || nKeySym == XK_Super_L || nKeySym == XK_Super_R ) + { + SalKeyModEvent aModEvt; + aModEvt.mnModKeyCode = 0; + if( pEvent->type == XLIB_KeyPress && mnExtKeyMod == 0 ) + mbSendExtKeyModChange = true; + else if( pEvent->type == KeyRelease && mbSendExtKeyModChange ) + { + aModEvt.mnModKeyCode = mnExtKeyMod; + mnExtKeyMod = 0; + } + + // pressing just the ctrl key leads to a keysym of XK_Control but + // the event state does not contain ControlMask. In the release + // event its the other way round: it does contain the Control mask. + // The modifier mode therefore has to be adapted manually. + sal_uInt16 nExtModMask = 0; + sal_uInt16 nModMask = 0; + switch( nKeySym ) + { + case XK_Control_L: + nExtModMask = MODKEY_LMOD1; + nModMask = KEY_MOD1; + break; + case XK_Control_R: + nExtModMask = MODKEY_RMOD1; + nModMask = KEY_MOD1; + break; + case XK_Alt_L: + nExtModMask = MODKEY_LMOD2; + nModMask = KEY_MOD2; + break; + case XK_Alt_R: + nExtModMask = MODKEY_RMOD2; + nModMask = KEY_MOD2; + break; + case XK_Shift_L: + nExtModMask = MODKEY_LSHIFT; + nModMask = KEY_SHIFT; + break; + case XK_Shift_R: + nExtModMask = MODKEY_RSHIFT; + nModMask = KEY_SHIFT; + break; + // Map Meta/Super keys to MOD3 modifier on all Unix systems + // except Mac OS X + case XK_Meta_L: + case XK_Super_L: + nExtModMask = MODKEY_LMOD3; + nModMask = KEY_MOD3; + break; + case XK_Meta_R: + case XK_Super_R: + nExtModMask = MODKEY_RMOD3; + nModMask = KEY_MOD3; + break; + } + if( pEvent->type == KeyRelease ) + { + nModCode &= ~nModMask; + mnExtKeyMod &= ~nExtModMask; + } + else + { + nModCode |= nModMask; + mnExtKeyMod |= nExtModMask; + } + + aModEvt.mnCode = nModCode; + aModEvt.mnTime = pEvent->time; + + int nRet = CallCallback( SALEVENT_KEYMODCHANGE, &aModEvt ); + + // emulate KEY_MENU + if ( ( (nKeySym == XK_Alt_L) || (nKeySym == XK_Alt_R) ) && + ( (nModCode & ~(KEY_MOD3|KEY_MOD2)) == 0 ) ) + { + if( pEvent->type == XLIB_KeyPress ) + mbKeyMenu = true; + else if( mbKeyMenu ) + { + // simulate KEY_MENU + aKeyEvt.mnCode = KEY_MENU | nModCode; + aKeyEvt.mnRepeat = 0; + aKeyEvt.mnTime = pEvent->time; + aKeyEvt.mnCharCode = 0; + nRet = CallCallback( SALEVENT_KEYINPUT, &aKeyEvt ); + nRet = CallCallback( SALEVENT_KEYUP, &aKeyEvt ); + } + } + else + mbKeyMenu = false; + return nRet; + } + + mbSendExtKeyModChange = mbKeyMenu = false; + + // try to figure out the vcl code for the keysym + // #i52338# use the unmodified KeySym if there is none for the real KeySym + // because the independent part has only keycodes for unshifted keys + nKeyCode = pDisplay_->GetKeyCode( nKeySym, &aDummy ); + if( nKeyCode == 0 ) + nKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy ); + + // try to figure out a printable if XmbLookupString returns only a keysym + // and NOT a printable. Do not store it in pPrintable[0] since it is expected to + // be in system encoding, not unicode. + // #i8988##, if KeySym and printable look equally promising then prefer KeySym + // the printable is bound to the encoding so the KeySym might contain more + // information (in et_EE locale: "Compose + Z + <" delivers "," in printable and + // (the desired) Zcaron in KeySym + sal_Unicode nKeyString = 0x0; + if ( (nLen == 0) + || ((nLen == 1) && (nKeySym > 0)) ) + nKeyString = KeysymToUnicode (nKeySym); + // if we have nothing we give up + if( !nKeyCode && !nLen && !nKeyString) + return 0; + + DeletionListener aDeleteWatch( this ); + + if( nModCode == (KEY_SHIFT | KEY_MOD1) && pEvent->type == XLIB_KeyPress ) + { + sal_uInt16 nSeqKeyCode = pDisplay_->GetKeyCode( nUnmodifiedKeySym, &aDummy ); + if( nSeqKeyCode == KEY_U ) + { + beginUnicodeSequence(); + return 1; + } + else if( nSeqKeyCode >= KEY_0 && nSeqKeyCode <= KEY_9 ) + { + if( appendUnicodeSequence( sal_Unicode( '0' ) + sal_Unicode(nSeqKeyCode - KEY_0) ) ) + return 1; + } + else if( nSeqKeyCode >= KEY_A && nSeqKeyCode <= KEY_F ) + { + if( appendUnicodeSequence( sal_Unicode( 'a' ) + sal_Unicode(nSeqKeyCode - KEY_A) ) ) + return 1; + } + else + endUnicodeSequence(); + } + + if( aDeleteWatch.isDeleted() ) + return 0; + + rtl_TextEncoding nEncoding; + + if (mpInputContext != NULL && mpInputContext->IsMultiLingual() ) + nEncoding = RTL_TEXTENCODING_UTF8; + else + nEncoding = osl_getThreadTextEncoding(); + + sal_Unicode *pBuffer; + sal_Unicode *pString; + sal_Size nBufferSize = nLen * 2; + sal_Size nSize; + pBuffer = (sal_Unicode*) malloc( nBufferSize + 2 ); + pBuffer[ 0 ] = 0; + + if (nKeyString != 0) + { + pString = &nKeyString; + nSize = 1; + } + else + if (nLen > 0 && nEncoding != RTL_TEXTENCODING_UNICODE) + { + // create text converter + rtl_TextToUnicodeConverter aConverter = + rtl_createTextToUnicodeConverter( nEncoding ); + rtl_TextToUnicodeContext aContext = + rtl_createTextToUnicodeContext( aConverter ); + + sal_uInt32 nConversionInfo; + sal_Size nConvertedChars; + + // convert to single byte text stream + nSize = rtl_convertTextToUnicode( + aConverter, aContext, + (char*)pPrintable, nLen, + pBuffer, nBufferSize, + RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE | + RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE, + &nConversionInfo, &nConvertedChars ); + + // destroy converter + rtl_destroyTextToUnicodeContext( aConverter, aContext ); + rtl_destroyTextToUnicodeConverter( aConverter ); + + pString = pBuffer; + } + else + if (nLen > 0 /* nEncoding == RTL_TEXTENCODING_UNICODE */) + { + pString = (sal_Unicode*)pPrintable; + nSize = nLen; + } + else + { + pString = pBuffer; + nSize = 0; + } + + if ( mpInputContext != NULL + && mpInputContext->UseContext() + && KeyRelease != pEvent->type + && ( (nSize > 1) + || (nSize > 0 && mpInputContext->IsPreeditMode())) ) + { + mpInputContext->CommitKeyEvent(pString, nSize); + } + else + // normal single character keyinput + { + aKeyEvt.mnCode = nKeyCode | nModCode; + aKeyEvt.mnRepeat = 0; + aKeyEvt.mnTime = pEvent->time; + aKeyEvt.mnCharCode = pString[ 0 ]; + + if( KeyRelease == pEvent->type ) + { + CallCallback( SALEVENT_KEYUP, &aKeyEvt ); + } + else + { + if ( ! CallCallback(SALEVENT_KEYINPUT, &aKeyEvt) ) + { + // independent layer doesnt want to handle key-event, so check + // whether the keycode may have an alternate meaning + KeyAlternate aAlternate = GetAlternateKeyCode( nKeyCode ); + if ( aAlternate.nKeyCode != 0 ) + { + aKeyEvt.mnCode = aAlternate.nKeyCode | nModCode; + if( aAlternate.nCharCode ) + aKeyEvt.mnCharCode = aAlternate.nCharCode; + CallCallback(SALEVENT_KEYINPUT, &aKeyEvt); + } + } + } + } + + // + // update the spot location for PreeditPosition IME style + // + if (! aDeleteWatch.isDeleted()) + { + if (mpInputContext != NULL && mpInputContext->UseContext()) + mpInputContext->UpdateSpotLocation(); + } + + free (pBuffer); + return True; +} + + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleFocusEvent( XFocusChangeEvent *pEvent ) +{ + // #107739# ReflectionX in Windows mode changes focus while mouse is grabbed + if( nVisibleFloats > 0 && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "ReflectionX Windows" ) ) + return 1; + + /* #55691# ignore focusout resulting from keyboard grabs + * we do not grab it and are not interested when + * someone else does CDE e.g. does a XGrabKey on arrow keys + * #73179# handle focus events with mode NotifyWhileGrabbed + * because with CDE alt-tab focus changing we do not get + * normal focus events + * #71791# cast focus event to the input context, otherwise the + * status window does not follow the application frame + */ + + if ( mpInputContext != NULL ) + { + if( FocusIn == pEvent->type ) + mpInputContext->SetICFocus( this ); + else + { + /* + * do not unset the IC focuse here because would kill + * a lookup choice windows that might have the focus now + * mpInputContext->UnsetICFocus( this ); + */ + I18NStatus::get().show( false, I18NStatus::focus ); + } + } + + + if ( pEvent->mode == NotifyNormal || pEvent->mode == NotifyWhileGrabbed || + ( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() ) + ) + { + if( hPresentationWindow != None && hPresentationWindow != GetShellWindow() ) + return 0; + + if( FocusIn == pEvent->type ) + { + vcl_sal::PrinterUpdate::update(); + mbInputFocus = True; + ImplSVData* pSVData = ImplGetSVData(); + + + + long nRet = CallCallback( SALEVENT_GETFOCUS, 0 ); + if ((mpParent != NULL && nStyle_ == 0) + && pSVData->maWinData.mpFirstFloat ) + { + sal_uLong nMode = pSVData->maWinData.mpFirstFloat->GetPopupModeFlags(); + pSVData->maWinData.mpFirstFloat->SetPopupModeFlags( + nMode & ~(FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE)); + } + return nRet; + } + else + { + mbInputFocus = False; + mbSendExtKeyModChange = mbKeyMenu = false; + mnExtKeyMod = 0; + return CallCallback( SALEVENT_LOSEFOCUS, 0 ); + } + } + + return 0; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +long X11SalFrame::HandleExposeEvent( XEvent *pEvent ) +{ + XRectangle aRect = { 0, 0, 0, 0 }; + sal_uInt16 nCount = 0; + + if( pEvent->type == Expose ) + { + aRect.x = pEvent->xexpose.x; + aRect.y = pEvent->xexpose.y; + aRect.width = pEvent->xexpose.width; + aRect.height = pEvent->xexpose.height; + nCount = pEvent->xexpose.count; + } + else if( pEvent->type == GraphicsExpose ) + { + aRect.x = pEvent->xgraphicsexpose.x; + aRect.y = pEvent->xgraphicsexpose.y; + aRect.width = pEvent->xgraphicsexpose.width; + aRect.height = pEvent->xgraphicsexpose.height; + nCount = pEvent->xgraphicsexpose.count; + } + + if( IsOverrideRedirect() && mbFullScreen && + aPresentationReparentList.begin() == aPresentationReparentList.end() ) + // we are in fullscreen mode -> override redirect + // focus is possibly lost, so reget it + XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToNone, CurrentTime ); + + // width and height are extents, so they are of by one for rectangle + maPaintRegion.Union( Rectangle( Point(aRect.x, aRect.y), Size(aRect.width+1, aRect.height+1) ) ); + + if( nCount ) + // wait for last expose rectangle, do not wait for resize timer + // if a completed graphics expose sequence is available + return 1; + + SalPaintEvent aPEvt( maPaintRegion.Left(), maPaintRegion.Top(), maPaintRegion.GetWidth(), maPaintRegion.GetHeight() ); + + CallCallback( SALEVENT_PAINT, &aPEvt ); + maPaintRegion = Rectangle(); + + return 1; +} + +void X11SalFrame::RestackChildren( XLIB_Window* pTopLevelWindows, int nTopLevelWindows ) +{ + if( maChildren.begin() != maChildren.end() ) + { + int nWindow = nTopLevelWindows; + while( nWindow-- ) + if( pTopLevelWindows[nWindow] == GetStackingWindow() ) + break; + if( nWindow < 0 ) + return; + + std::list< X11SalFrame* >::const_iterator it; + for( it = maChildren.begin(); it != maChildren.end(); ++it ) + { + X11SalFrame* pData = *it; + if( pData->bMapped_ ) + { + int nChild = nWindow; + while( nChild-- ) + { + if( pTopLevelWindows[nChild] == pData->GetStackingWindow() ) + { + // if a child is behind its parent, place it above the + // parent (for insane WMs like Dtwm and olwm) + XWindowChanges aCfg; + aCfg.sibling = GetStackingWindow(); + aCfg.stack_mode = Above; + XConfigureWindow( GetXDisplay(), pData->GetStackingWindow(), CWSibling|CWStackMode, &aCfg ); + break; + } + } + } + } + for( it = maChildren.begin(); it != maChildren.end(); ++it ) + { + X11SalFrame* pData = *it; + pData->RestackChildren( pTopLevelWindows, nTopLevelWindows ); + } + } +} + +void X11SalFrame::RestackChildren() +{ + if( ! GetDisplay()->getWMAdaptor()->isTransientBehaviourAsExpected() + && maChildren.begin() != maChildren.end() ) + { + XLIB_Window aRoot, aParent, *pChildren = NULL; + unsigned int nChildren; + if( XQueryTree( GetXDisplay(), + GetDisplay()->GetRootWindow( m_nScreen ), + &aRoot, + &aParent, + &pChildren, + &nChildren ) ) + { + RestackChildren( pChildren, nChildren ); + XFree( pChildren ); + } + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent ) +{ + if ( pEvent->window != GetShellWindow() + && pEvent->window != GetWindow() + && pEvent->window != GetForeignParent() + && pEvent->window != GetStackingWindow() + ) + { + // could be as well a sys-child window (aka SalObject) + return 1; + } + + + if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) && pEvent->window == GetShellWindow() ) + { + // just update the children's positions + RestackChildren(); + return 1; + } + + if( pEvent->window == GetForeignParent() ) + XResizeWindow( GetXDisplay(), + GetWindow(), + pEvent->width, + pEvent->height ); + + XLIB_Window hDummy; + XTranslateCoordinates( GetXDisplay(), + GetWindow(), + pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ), + 0, 0, + &pEvent->x, &pEvent->y, + &hDummy ); + + if( pEvent->window == GetStackingWindow() ) + { + if( maGeometry.nX != pEvent->x || maGeometry.nY != pEvent->y ) + { + maGeometry.nX = pEvent->x; + maGeometry.nY = pEvent->y; + CallCallback( SALEVENT_MOVE, NULL ); + } + return 1; + } + + // check size hints in first time SalFrame::Show + if( SHOWSTATE_UNKNOWN == nShowState_ && bMapped_ ) + nShowState_ = SHOWSTATE_NORMAL; + + nWidth_ = pEvent->width; + nHeight_ = pEvent->height; + + bool bMoved = ( pEvent->x != maGeometry.nX || pEvent->y != maGeometry.nY ); + bool bSized = ( pEvent->width != (int)maGeometry.nWidth || pEvent->height != (int)maGeometry.nHeight ); + + maGeometry.nX = pEvent->x; + maGeometry.nY = pEvent->y; + maGeometry.nWidth = pEvent->width; + maGeometry.nHeight = pEvent->height; + updateScreenNumber(); + + // update children's position + RestackChildren(); + + if( bSized && ! bMoved ) + CallCallback( SALEVENT_RESIZE, NULL ); + else if( bMoved && ! bSized ) + CallCallback( SALEVENT_MOVE, NULL ); + else if( bMoved && bSized ) + CallCallback( SALEVENT_MOVERESIZE, NULL ); + + return 1; +} + +IMPL_LINK( X11SalFrame, HandleAlwaysOnTopRaise, void*, EMPTYARG ) +{ + if( bMapped_ ) + ToTop( 0 ); + return 0; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleReparentEvent( XReparentEvent *pEvent ) +{ + Display *pDisplay = pEvent->display; + XLIB_Window hWM_Parent; + XLIB_Window hRoot, *Children, hDummy; + unsigned int nChildren; + sal_Bool bNone = pDisplay_->GetProperties() + & PROPERTY_SUPPORT_WM_Parent_Pixmap_None; + sal_Bool bAccessParentWindow = ! (pDisplay_->GetProperties() + & PROPERTY_FEATURE_TrustedSolaris); + + static const char* pDisableStackingCheck = getenv( "SAL_DISABLE_STACKING_CHECK" ); + + GetDisplay()->GetXLib()->PushXErrorLevel( true ); + + /* + * #89186# don't rely on the new parent from the event. + * the event may be "out of date", that is the window manager + * window may not exist anymore. This can happen if someone + * shows a frame and hides it again quickly (not that that would + * be very sensible) + */ + hWM_Parent = GetShellWindow(); + do + { + Children = NULL; + XQueryTree( pDisplay, + hWM_Parent, + &hRoot, + &hDummy, + &Children, + &nChildren ); + if( GetDisplay()->GetXLib()->HasXErrorOccured() ) + { + hWM_Parent = GetShellWindow(); + break; + } + /* #107048# this sometimes happens if a Show(sal_True) is + * immediately followed by Show(sal_False) (which is braindead anyway) + */ + if( hDummy == hWM_Parent ) + hDummy = hRoot; + if( hDummy != hRoot ) + { + hWM_Parent = hDummy; + if( bAccessParentWindow && bNone ) + XSetWindowBackgroundPixmap( pDisplay, hWM_Parent, None ); + } + if( Children ) + XFree( Children ); + } while( hDummy != hRoot ); + + if( GetStackingWindow() == None + && hWM_Parent != hPresentationWindow + && hWM_Parent != GetShellWindow() + && ( ! pDisableStackingCheck || ! *pDisableStackingCheck ) + ) + { + mhStackingWindow = hWM_Parent; + if (bAccessParentWindow) + XSelectInput( pDisplay, GetStackingWindow(), StructureNotifyMask ); + } + + if( hWM_Parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ) + || hWM_Parent == GetForeignParent() + || pEvent->parent == pDisplay_->GetRootWindow( pDisplay_->GetDefaultScreenNumber() ) + || ( nStyle_ & SAL_FRAME_STYLE_FLOAT ) ) + { + // Reparenting before Destroy + aPresentationReparentList.remove( GetStackingWindow() ); + mhStackingWindow = None; + GetDisplay()->GetXLib()->PopXErrorLevel(); + return 0; + } + + /* + * evil hack to show decorated windows on top + * of override redirect presentation windows: + * reparent the window manager window to the presentation window + * does not work with non-reparenting WMs + * in future this should not be necessary anymore with + * _NET_WM_STATE_FULLSCREEN available + */ + if( hPresentationWindow != None + && hPresentationWindow != GetWindow() + && GetStackingWindow() != None + && GetStackingWindow() != GetDisplay()->GetRootWindow( m_nScreen ) + ) + { + int x = 0, y = 0; + XLIB_Window aChild; + XTranslateCoordinates( GetXDisplay(), + GetStackingWindow(), + GetDisplay()->GetRootWindow( m_nScreen ), + 0, 0, + &x, &y, + &aChild + ); + XReparentWindow( GetXDisplay(), + GetStackingWindow(), + hPresentationWindow, + x, y + ); + aPresentationReparentList.push_back( GetStackingWindow() ); + } + + int nLeft = 0, nTop = 0; + XTranslateCoordinates( GetXDisplay(), + GetShellWindow(), + hWM_Parent, + 0, 0, + &nLeft, + &nTop, + &hDummy ); + maGeometry.nLeftDecoration = nLeft > 0 ? nLeft-1 : 0; + maGeometry.nTopDecoration = nTop > 0 ? nTop-1 : 0; + + /* + * decorations are not symmetric, + * so need real geometries here + * (this will fail with virtual roots ?) + */ + GetDisplay()->GetXLib()->ResetXErrorOccured(); + int xp, yp, x, y; + unsigned int wp, w, hp, h, bw, d; + XGetGeometry( GetXDisplay(), + GetShellWindow(), + &hRoot, + &x, &y, &w, &h, &bw, &d ); + XGetGeometry( GetXDisplay(), + hWM_Parent, + &hRoot, + &xp, &yp, &wp, &hp, &bw, &d ); + bool bResized = false; + if( ! GetDisplay()->GetXLib()->HasXErrorOccured() ) + { + maGeometry.nRightDecoration = wp - w - maGeometry.nLeftDecoration; + maGeometry.nBottomDecoration = hp - h - maGeometry.nTopDecoration; + /* + * note: this works because hWM_Parent is direct child of root, + * not necessarily parent of GetShellWindow() + */ + maGeometry.nX = xp + nLeft; + maGeometry.nY = yp + nTop; + bResized = w != maGeometry.nWidth || h != maGeometry.nHeight; + maGeometry.nWidth = w; + maGeometry.nHeight = h; + } + + + // limit width and height if we are too large: #47757 + // olwm and fvwm need this, it doesnt harm the rest + + // #i81311# do this only for sizable frames + if( (nStyle_ & SAL_FRAME_STYLE_SIZEABLE) != 0 ) + { + Size aScreenSize = GetDisplay()->GetScreenSize( m_nScreen ); + int nScreenWidth = aScreenSize.Width(); + int nScreenHeight = aScreenSize.Height(); + int nFrameWidth = maGeometry.nWidth + maGeometry.nLeftDecoration + maGeometry.nRightDecoration; + int nFrameHeight = maGeometry.nHeight + maGeometry.nTopDecoration + maGeometry.nBottomDecoration; + + if ((nFrameWidth > nScreenWidth) || (nFrameHeight > nScreenHeight)) + { + Size aSize(maGeometry.nWidth, maGeometry.nHeight); + + if (nFrameWidth > nScreenWidth) + aSize.Width() = nScreenWidth - maGeometry.nRightDecoration - maGeometry.nLeftDecoration; + if (nFrameHeight > nScreenHeight) + aSize.Height() = nScreenHeight - maGeometry.nBottomDecoration - maGeometry.nTopDecoration; + + SetSize( aSize ); + bResized = false; + } + } + if( bResized ) + CallCallback( SALEVENT_RESIZE, NULL ); + + GetDisplay()->GetXLib()->PopXErrorLevel(); + + return 1; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleColormapEvent( XColormapEvent* ) +{ + return 0; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleStateEvent( XPropertyEvent *pEvent ) +{ + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *prop = NULL; + + if( 0 != XGetWindowProperty( GetXDisplay(), + GetShellWindow(), + pEvent->atom, // property + 0, // long_offset (32bit) + 2, // long_length (32bit) + False, // delete + pEvent->atom, // req_type + &actual_type, + &actual_format, + &nitems, + &bytes_after, + &prop ) + || ! prop + ) + return 0; + + DBG_ASSERT( actual_type = pEvent->atom + && 32 == actual_format + && 2 == nitems + && 0 == bytes_after, "HandleStateEvent" ); + + if( *(unsigned long*)prop == NormalState ) + nShowState_ = SHOWSTATE_NORMAL; + else if( *(unsigned long*)prop == IconicState ) + nShowState_ = SHOWSTATE_MINIMIZED; + + XFree( prop ); + return 1; +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +long X11SalFrame::HandleClientMessage( XClientMessageEvent *pEvent ) +{ + const WMAdaptor& rWMAdaptor( *pDisplay_->getWMAdaptor() ); + +#if !defined(__synchronous_extinput__) + if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_EXTTEXTEVENT ) ) + { + HandleExtTextEvent (pEvent); + return 1; + } +#endif + else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::SAL_QUITEVENT ) ) + { + stderr0( "X11SalFrame::Dispatch Quit\n" ); + Close(); // ??? + return 1; + } + else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::WM_PROTOCOLS ) ) + { + if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::NET_WM_PING ) ) + rWMAdaptor.answerPing( this, pEvent ); + else if( ! ( nStyle_ & SAL_FRAME_STYLE_PLUG ) + && ! (( nStyle_ & SAL_FRAME_STYLE_FLOAT ) && (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION)) + ) + { + if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_DELETE_WINDOW ) ) + { + Close(); + return 1; + } + else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_TAKE_FOCUS ) ) + { + // do nothing, we set the input focus in ToTop() if necessary + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "got WM_TAKE_FOCUS on %s window\n", + (nStyle_&SAL_FRAME_STYLE_OWNERDRAWDECORATION) ? + "ownerdraw" : "NON OWNERDRAW" ); + #endif + } + else if( (Atom)pEvent->data.l[0] == rWMAdaptor.getAtom( WMAdaptor::WM_SAVE_YOURSELF ) ) + { + bool bSession = rWMAdaptor.getWindowManagerName().EqualsAscii( "Dtwm" ); + + if( ! bSession ) + { + if( this == s_pSaveYourselfFrame ) + { + ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() ); + const char* argv[2]; + argv[0] = "/bin/sh"; + argv[1] = const_cast<char*>(aExec.GetBuffer()); + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] ); + #endif + XSetCommand( GetXDisplay(), GetShellWindow(), (char**)argv, 2 ); + } + else + // can only happen in race between WM and window closing + XChangeProperty( GetXDisplay(), GetShellWindow(), rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 ); + } + else + { + // save open documents; would be good for non Dtwm, too, + // but there is no real Shutdown message in the ancient + // SM protocol; on Dtwm SaveYourself really means Shutdown, too. + IceSalSession::handleOldX11SaveYourself( this ); + } + } + } + } + else if( pEvent->message_type == rWMAdaptor.getAtom( WMAdaptor::XEMBED ) && + pEvent->window == GetWindow() ) + { + if( pEvent->data.l[1] == 1 || // XEMBED_WINDOW_ACTIVATE + pEvent->data.l[1] == 2 ) // XEMBED_WINDOW_DEACTIVATE + { + XFocusChangeEvent aEvent; + aEvent.type = (pEvent->data.l[1] == 1 ? FocusIn : FocusOut); + aEvent.serial = pEvent->serial; + aEvent.send_event = True; + aEvent.display = pEvent->display; + aEvent.window = pEvent->window; + aEvent.mode = NotifyNormal; + aEvent.detail = NotifyDetailNone; + HandleFocusEvent( &aEvent ); + } + } + return 0; +} + +void X11SalFrame::SaveYourselfDone( SalFrame* pSaveFrame ) +{ + // session save was done, inform dtwm + if( s_pSaveYourselfFrame && pSaveFrame ) + { + ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() ); + const char* argv[2]; + argv[0] = "/bin/sh"; + argv[1] = const_cast<char*>(aExec.GetBuffer()); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "SaveYourself request, setting command: %s %s\n", argv[0], argv[1] ); +#endif + XSetCommand( s_pSaveYourselfFrame->GetXDisplay(), + s_pSaveYourselfFrame->GetShellWindow(), + (char**)argv, 2 ); + if( pSaveFrame != s_pSaveYourselfFrame ) + { + // check if it still exists + const X11SalFrame* pFrame = NULL; + const std::list< SalFrame* >& rFrames = static_cast<X11SalFrame*>(pSaveFrame)->GetDisplay()->getFrames(); + std::list< SalFrame* >::const_iterator it = rFrames.begin(); + while( it != rFrames.end() ) + { + pFrame = static_cast< const X11SalFrame* >(*it); + if( pFrame == pSaveFrame ) + break; + ++it; + } + if( pFrame == pSaveFrame ) + { + const WMAdaptor& rWMAdaptor( *pFrame->pDisplay_->getWMAdaptor() ); + XChangeProperty( pFrame->GetXDisplay(), + pFrame->GetShellWindow(), + rWMAdaptor.getAtom( WMAdaptor::WM_COMMAND ), XA_STRING, 8, PropModeReplace, (unsigned char*)"", 0 ); + } + } + s_pSaveYourselfFrame->ShutDown(); + } +} + +// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +extern "C" +{ +Bool call_checkKeyReleaseForRepeat( Display* pDisplay, XEvent* pCheck, XPointer pX11SalFrame ) +{ + return X11SalFrame::checkKeyReleaseForRepeat( pDisplay, pCheck, pX11SalFrame ); +} +} + +Bool X11SalFrame::checkKeyReleaseForRepeat( Display*, XEvent* pCheck, XPointer pX11SalFrame ) +{ + X11SalFrame* pThis = (X11SalFrame*)pX11SalFrame; + return + pCheck->type == XLIB_KeyPress && + pCheck->xkey.state == pThis->nKeyState_ && + pCheck->xkey.keycode == pThis->nKeyCode_ && + pCheck->xkey.time == pThis->nReleaseTime_ ? True : False; +} + +long X11SalFrame::Dispatch( XEvent *pEvent ) +{ + long nRet = 0; + + if( -1 == nCaptured_ ) + { + CaptureMouse( sal_True ); +#ifdef DBG_UTIL + if( -1 != nCaptured_ ) + pDisplay_->PrintEvent( "Captured", pEvent ); +#endif + } + + if( pEvent->xany.window == GetShellWindow() || pEvent->xany.window == GetWindow() ) + { + switch( pEvent->type ) + { + case XLIB_KeyPress: + nKeyCode_ = pEvent->xkey.keycode; + nKeyState_ = pEvent->xkey.state; + nRet = HandleKeyEvent( &pEvent->xkey ); + break; + + case KeyRelease: + if( -1 == nCompose_ ) + { + nReleaseTime_ = pEvent->xkey.time; + XEvent aEvent; + if( XCheckIfEvent( pEvent->xkey.display, &aEvent, call_checkKeyReleaseForRepeat, (XPointer)this ) ) + XPutBackEvent( pEvent->xkey.display, &aEvent ); + else + nRet = HandleKeyEvent( &pEvent->xkey ); + } + break; + + case ButtonPress: + // #74406# if we loose the focus in presentation mode + // there are good chances that we never get it back + // since the WM ignores us + if( IsOverrideRedirect() ) + { + XSetInputFocus( GetXDisplay(), GetShellWindow(), + RevertToNone, CurrentTime ); + } + + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + nRet = HandleMouseEvent( pEvent ); + break; + + case FocusIn: + case FocusOut: + nRet = HandleFocusEvent( &pEvent->xfocus ); + break; + + case Expose: + case GraphicsExpose: + nRet = HandleExposeEvent( pEvent ); + break; + + case MapNotify: + if( pEvent->xmap.window == GetShellWindow() ) + { + if( nShowState_ == SHOWSTATE_HIDDEN ) + { + /* + * #95097# workaround for (at least) KWin 2.2.2 + * which will map windows that were once transient + * even if they are withdrawn when the respective + * document is mapped. + */ + if( ! (nStyle_ & SAL_FRAME_STYLE_PLUG) ) + XUnmapWindow( GetXDisplay(), GetShellWindow() ); + break; + } + bMapped_ = sal_True; + bViewable_ = sal_True; + nRet = sal_True; + if ( mpInputContext != NULL ) + mpInputContext->Map( this ); + CallCallback( SALEVENT_RESIZE, NULL ); + if( pDisplay_->GetServerVendor() == vendor_hummingbird ) + { + /* + * With Exceed sometimes there does not seem to be + * an Expose after the MapNotify. + * so start a delayed paint here + */ + maPaintRegion.Union( Rectangle( Point( 0, 0 ), Size( maGeometry.nWidth, maGeometry.nHeight ) ) ); + XEvent aEvent; + aEvent.xexpose.type = Expose; + aEvent.xexpose.display = pDisplay_->GetDisplay(); + aEvent.xexpose.x = 0; + aEvent.xexpose.y = 0; + aEvent.xexpose.width = maGeometry.nWidth; + aEvent.xexpose.height = maGeometry.nHeight; + aEvent.xexpose.count = 0; + XSendEvent( pDisplay_->GetDisplay(), + GetWindow(), + True, + ExposureMask, + &aEvent ); + } + + bool bSetFocus = m_bSetFocusOnMap; + /* #99570# another workaround for sawfish: if a transient window for the same parent is shown + * sawfish does not set the focus to it. Applies only for click to focus mode. + */ + if( ! (nStyle_ & SAL_FRAME_STYLE_FLOAT ) && mbInShow && GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Sawfish" ) ) + { + // #101775# don't set the focus into the IME status window + // since this will lead to a parent loose-focus, close status, + // reget focus, open status, .... flicker loop + if ( (I18NStatus::get().getStatusFrame() != this) ) + bSetFocus = true; + } + + /* + * sometimes a message box/dialogue is brought up when a frame is not mapped + * the corresponding TRANSIENT_FOR hint is then set to the root window + * so that the dialogue shows in all cases. Correct it here if the + * frame is shown afterwards. + */ + if( ! IsChildWindow() + && ! IsOverrideRedirect() + && ! IsFloatGrabWindow() + ) + { + for( std::list< X11SalFrame* >::const_iterator it = maChildren.begin(); + it != maChildren.end(); ++it ) + { + if( (*it)->mbTransientForRoot ) + pDisplay_->getWMAdaptor()->changeReferenceFrame( *it, this ); + } + } + + if( hPresentationWindow != None && GetShellWindow() == hPresentationWindow ) + XSetInputFocus( GetXDisplay(), GetShellWindow(), RevertToParent, CurrentTime ); + /* For unknown reasons Dtwm does respect the input_hint + * set to False, but not when mapping the window. So + * emulate the correct behaviour and set the focus back + * to where it most probably should have been. + */ + if( (nStyle_ & SAL_FRAME_STYLE_OWNERDRAWDECORATION) && + mpParent && + GetDisplay()->getWMAdaptor()->getWindowManagerName().EqualsAscii( "Dtwm" ) + ) + { + XSetInputFocus( GetXDisplay(), + mpParent->GetShellWindow(), + RevertToParent, + CurrentTime ); + bSetFocus = false; + } + + if( bSetFocus ) + { + XSetInputFocus( GetXDisplay(), + GetShellWindow(), + RevertToParent, + CurrentTime ); + } + + + RestackChildren(); + mbInShow = sal_False; + m_bSetFocusOnMap = false; + } + break; + + case UnmapNotify: + if( pEvent->xunmap.window == GetShellWindow() ) + { + bMapped_ = sal_False; + bViewable_ = sal_False; + nRet = sal_True; + if ( mpInputContext != NULL ) + mpInputContext->Unmap( this ); + CallCallback( SALEVENT_RESIZE, NULL ); + } + break; + + case ConfigureNotify: + if( pEvent->xconfigure.window == GetShellWindow() + || pEvent->xconfigure.window == GetWindow() ) + nRet = HandleSizeEvent( &pEvent->xconfigure ); + break; + + case VisibilityNotify: + nVisibility_ = pEvent->xvisibility.state; + nRet = sal_True; + if( bAlwaysOnTop_ + && bMapped_ + && ! GetDisplay()->getWMAdaptor()->isAlwaysOnTopOK() + && nVisibility_ != VisibilityUnobscured ) + maAlwaysOnTopRaiseTimer.Start(); + break; + + case ReparentNotify: + nRet = HandleReparentEvent( &pEvent->xreparent ); + break; + + case MappingNotify: + if( MappingPointer != pEvent->xmapping.request ) + nRet = CallCallback( SALEVENT_KEYBOARDCHANGED, 0 ); + break; + + case ColormapNotify: + nRet = HandleColormapEvent( &pEvent->xcolormap ); + break; + + case PropertyNotify: + { + if( pEvent->xproperty.atom == pDisplay_->getWMAdaptor()->getAtom( WMAdaptor::WM_STATE ) ) + nRet = HandleStateEvent( &pEvent->xproperty ); + else + nRet = pDisplay_->getWMAdaptor()->handlePropertyNotify( this, &pEvent->xproperty ); + break; + } + + case ClientMessage: + nRet = HandleClientMessage( &pEvent->xclient ); + break; + } + } + else + { + switch( pEvent->type ) + { + case FocusIn: + case FocusOut: + if( ( nStyle_ & SAL_FRAME_STYLE_PLUG ) + && ( pEvent->xfocus.window == GetShellWindow() + || pEvent->xfocus.window == GetForeignParent() ) + ) + { + nRet = HandleFocusEvent( &pEvent->xfocus ); + } + break; + + case ConfigureNotify: + if( pEvent->xconfigure.window == GetForeignParent() || + pEvent->xconfigure.window == GetShellWindow() ) + nRet = HandleSizeEvent( &pEvent->xconfigure ); + + if( pEvent->xconfigure.window == GetStackingWindow() ) + nRet = HandleSizeEvent( &pEvent->xconfigure ); + + RestackChildren(); + break; + } + } + + return nRet; +} + +void X11SalFrame::ResetClipRegion() +{ + delete [] m_pClipRectangles; + m_pClipRectangles = NULL; + m_nCurClipRect = m_nMaxClipRect = 0; + + const int dest_kind = ShapeBounding; + const int op = ShapeSet; + const int ordering = YSorted; + + XWindowAttributes win_attrib; + XRectangle win_size; + + XLIB_Window aShapeWindow = mhShellWindow; + + XGetWindowAttributes ( GetDisplay()->GetDisplay(), + aShapeWindow, + &win_attrib ); + + win_size.x = 0; + win_size.y = 0; + win_size.width = win_attrib.width; + win_size.height = win_attrib.height; + + XShapeCombineRectangles ( GetDisplay()->GetDisplay(), + aShapeWindow, + dest_kind, + 0, 0, // x_off, y_off + &win_size, // list of rectangles + 1, // number of rectangles + op, ordering ); +} + +void X11SalFrame::BeginSetClipRegion( sal_uLong nRects ) +{ + if( m_pClipRectangles ) + delete [] m_pClipRectangles; + if( nRects ) + m_pClipRectangles = new XRectangle[nRects]; + else + m_pClipRectangles = NULL; + m_nMaxClipRect = static_cast<int>(nRects); + m_nCurClipRect = 0; +} + +void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) +{ + if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect ) + { + m_pClipRectangles[m_nCurClipRect].x = nX; + m_pClipRectangles[m_nCurClipRect].y = nY; + m_pClipRectangles[m_nCurClipRect].width = nWidth; + m_pClipRectangles[m_nCurClipRect].height = nHeight; + m_nCurClipRect++; + } +} + +void X11SalFrame::EndSetClipRegion() +{ + const int dest_kind = ShapeBounding; + const int ordering = YSorted; + const int op = ShapeSet; + + XLIB_Window aShapeWindow = mhShellWindow; + XShapeCombineRectangles ( GetDisplay()->GetDisplay(), + aShapeWindow, + dest_kind, + 0, 0, // x_off, y_off + m_pClipRectangles, + m_nCurClipRect, + op, ordering ); + +} + diff --git a/vcl/unx/source/window/salobj.cxx b/vcl/unx/source/window/salobj.cxx new file mode 100644 index 000000000000..93aeeba66ee8 --- /dev/null +++ b/vcl/unx/source/window/salobj.cxx @@ -0,0 +1,568 @@ +/************************************************************************* + * + * 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" + +#include <tools/prex.h> +#include <X11/Xlib.h> +#include <X11/extensions/shape.h> +#include <tools/postx.h> + +#include <salunx.h> +#include <salstd.hxx> +#include <saldata.hxx> +#ifndef _SV_SALINST_HXX +#include <salinst.h> +#endif +#include <saldisp.hxx> +#ifndef _SV_SALFRAME_HXX +#include <salframe.h> +#endif +#include <salobj.h> +#include <vcl/salwtype.hxx> +#include <vcl/keycodes.hxx> + +#include <tools/debug.hxx> +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif + +// ======================================================================= +// 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*/ ) +{ +} + |