| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| #include "tools/debug.hxx" |
| |
| #include "sal/alloca.h" |
| |
| #include "vcl/floatwin.hxx" |
| #include "vcl/svapp.hxx" |
| #include "vcl/keycodes.hxx" |
| #include "vcl/printerinfomanager.hxx" |
| #include "vcl/settings.hxx" |
| |
| #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 "unx/salunx.h" |
| #include "unx/saldata.hxx" |
| #include "unx/saldisp.hxx" |
| #include "unx/salgdi.h" |
| #include "unx/salframe.h" |
| #include "unx/soicon.hxx" |
| #include "unx/dtint.hxx" |
| #include "unx/sm.hxx" |
| #include "unx/wmadaptor.hxx" |
| #include "unx/salprn.h" |
| #include "unx/salbmp.h" |
| #include "unx/i18n_ic.hxx" |
| #include "unx/i18n_keysym.hxx" |
| #include "unx/i18n_status.hxx" |
| |
| #include "salinst.hxx" |
| #include "sallayout.hxx" |
| |
| #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()->setFullScreenMonitors( GetShellWindow(), nScreen ); |
| 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 ); |
| |
| } |
| |