summaryrefslogtreecommitdiff
path: root/vcl/unx/generic/window
diff options
context:
space:
mode:
authorPhilipp Lohmann [pl] <Philipp.Lohmann@Oracle.COM>2011-01-24 16:34:14 +0100
committerPhilipp Lohmann [pl] <Philipp.Lohmann@Oracle.COM>2011-01-24 16:34:14 +0100
commit5d463c719bb2881d63da68d0752e4086c265876d (patch)
treec9a8206ce0f705d67536626aec1ff777ad1c7b1e /vcl/unx/generic/window
parent7640d6a69f69172127221455b5bc5ae644f595ca (diff)
vcl2gnumake: #i116589# header cleanup: linux,solaris,macos
Diffstat (limited to 'vcl/unx/generic/window')
-rw-r--r--vcl/unx/generic/window/FWS.cxx280
-rw-r--r--vcl/unx/generic/window/FWS.hxx64
-rw-r--r--vcl/unx/generic/window/makefile.mk59
-rw-r--r--vcl/unx/generic/window/salframe.cxx4520
-rw-r--r--vcl/unx/generic/window/salobj.cxx567
5 files changed, 5490 insertions, 0 deletions
diff --git a/vcl/unx/generic/window/FWS.cxx b/vcl/unx/generic/window/FWS.cxx
new file mode 100644
index 000000000000..4683864fd116
--- /dev/null
+++ b/vcl/unx/generic/window/FWS.cxx
@@ -0,0 +1,280 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include "FWS.hxx"
+
+static Atom fwsIconAtom;
+
+static Atom FWS_CLIENT;
+static Atom FWS_COMM_WINDOW;
+static Atom FWS_PROTOCOLS;
+static Atom FWS_STACK_UNDER;
+static Atom FWS_PARK_ICONS;
+static Atom FWS_PASS_ALL_INPUT;
+static Atom FWS_PASSES_INPUT;
+static Atom FWS_HANDLES_FOCUS;
+
+static Atom FWS_REGISTER_WINDOW;
+static Atom FWS_STATE_CHANGE;
+static Atom FWS_UNSEEN_STATE;
+static Atom FWS_NORMAL_STATE;
+static Atom WM_PROTOCOLS;
+static Atom WM_CHANGE_STATE;
+
+static Bool fwsStackUnder;
+static Bool fwsParkIcons;
+static Bool fwsPassesInput;
+static Bool fwsHandlesFocus;
+
+static Window fwsCommWindow;
+
+/*************************************<->***********************************
+ *
+ * WMSupportsFWS() -
+ *
+ * Initialize our atoms and determine if the current window manager is
+ * providing FWS extension support.
+ *
+ *************************************<->***********************************/
+
+Bool
+WMSupportsFWS (Display *display, int screen)
+{
+ unsigned int i;
+ Atom protocol;
+ Atom propType;
+ int propFormat;
+ unsigned long propItems;
+ unsigned long propBytesAfter;
+ unsigned char *propData;
+ char propName[64];
+
+ FWS_CLIENT = XInternAtom(display, "_SUN_FWS_CLIENT", False);
+ FWS_COMM_WINDOW = XInternAtom(display, "_SUN_FWS_COMM_WINDOW", False);
+ FWS_PROTOCOLS = XInternAtom(display, "_SUN_FWS_PROTOCOLS", False);
+ FWS_STACK_UNDER = XInternAtom(display, "_SUN_FWS_STACK_UNDER", False);
+ FWS_PARK_ICONS = XInternAtom(display, "_SUN_FWS_PARK_ICONS", False);
+ FWS_PASS_ALL_INPUT = XInternAtom(display, "_SUN_FWS_PASS_ALL_INPUT", False);
+ FWS_PASSES_INPUT = XInternAtom(display, "_SUN_FWS_PASSES_INPUT", False);
+ FWS_HANDLES_FOCUS = XInternAtom(display, "_SUN_FWS_HANDLES_FOCUS", False);
+ FWS_REGISTER_WINDOW= XInternAtom(display, "_SUN_FWS_REGISTER_WINDOW",False);
+ FWS_STATE_CHANGE = XInternAtom(display, "_SUN_FWS_STATE_CHANGE", False);
+ FWS_UNSEEN_STATE = XInternAtom(display, "_SUN_FWS_UNSEEN_STATE", False);
+ FWS_NORMAL_STATE = XInternAtom(display, "_SUN_FWS_NORMAL_STATE", False);
+ WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", False);
+ WM_CHANGE_STATE = XInternAtom(display, "WM_CHANGE_STATE", False);
+
+ snprintf (propName, sizeof(propName), "_SUN_FWS_NEXT_ICON_%d", screen);
+ fwsIconAtom = XInternAtom(display, propName, False);
+
+ if (XGetWindowProperty (display, DefaultRootWindow (display),
+ FWS_COMM_WINDOW, 0, 1,
+ False, AnyPropertyType, &propType,
+ &propFormat, &propItems,
+ &propBytesAfter, &propData) != Success)
+ return False;
+
+ if (propFormat != 32 ||
+ propItems != 1 ||
+ propBytesAfter != 0)
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Bad FWS_COMM_WINDOW property on root window.\n");
+ #endif
+ XFree (propData);
+ return False;
+ }
+
+ fwsCommWindow = *(Window *) propData;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Using fwsCommWindow = 0x%lx.\n", fwsCommWindow);
+ #endif
+ XFree (propData);
+
+
+ if (XGetWindowProperty (display, DefaultRootWindow (display),
+ FWS_PROTOCOLS, 0, 10,
+ False, AnyPropertyType, &propType,
+ &propFormat, &propItems,
+ &propBytesAfter, &propData) != Success)
+ {
+ return False;
+ }
+
+ if (propFormat != 32 ||
+ propBytesAfter != 0)
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Bad FWS_PROTOCOLS property on root window.\n");
+ #endif
+ XFree (propData);
+ return False;
+ }
+
+ for (i = 0; i < propItems; ++i)
+ {
+ protocol = ((Atom *) propData)[i];
+ if (protocol == FWS_STACK_UNDER)
+ {
+ fwsStackUnder = True;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Using fwsStackUnder.\n");
+ #endif
+ }
+ else
+ if (protocol == FWS_PARK_ICONS)
+ {
+ fwsParkIcons = True;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Using fwsParkIcons.\n");
+ #endif
+ }
+ else
+ if (protocol == FWS_PASSES_INPUT)
+ {
+ fwsPassesInput = True;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Using fwsPassesInput.\n");
+ #endif
+ }
+ else
+ if (protocol == FWS_HANDLES_FOCUS)
+ {
+ fwsHandlesFocus = True;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf (stderr, "Using fwsHandlesFocus.\n");
+ #endif
+ }
+ }
+
+ XFree (propData);
+ return True;
+}
+
+/*************************************<->***********************************
+ *
+ * newHandler() -
+ *
+ * Handle X errors (temporarily) to record the occurance of BadWindow
+ * errors without crashing. Used to detect the FWS_COMM_WINDOW root window
+ * property containing an old or obsolete window id.
+ *
+ *************************************<->***********************************/
+
+extern "C" {
+
+static Bool badWindowFound;
+static int (* oldHandler) (Display *, XErrorEvent *);
+
+static int
+newHandler (Display *display, XErrorEvent *xerror)
+{
+ if (xerror->error_code != BadWindow)
+ (*oldHandler)(display, xerror);
+ else
+ badWindowFound = True;
+
+ return 0;
+}
+
+}
+
+/*************************************<->***********************************
+ *
+ * RegisterFwsWindow() -
+ *
+ * Send a client message to the FWS_COMM_WINDOW indicating the existance
+ * of a new FWS client window. Be careful to avoid BadWindow errors on
+ * the XSendEvent in case the FWS_COMM_WINDOW root window property had
+ * old/obsolete junk in it.
+ *
+ *************************************<->***********************************/
+
+Bool
+RegisterFwsWindow (Display *display, Window window)
+{
+ XClientMessageEvent msg;
+
+ msg.type = ClientMessage;
+ msg.window = fwsCommWindow;
+ msg.message_type = FWS_REGISTER_WINDOW;
+ msg.format = 32;
+ msg.data.l[0] = window;
+
+ XSync (display, False);
+ badWindowFound = False;
+ oldHandler = XSetErrorHandler (newHandler);
+
+ XSendEvent (display, fwsCommWindow, False, NoEventMask,
+ (XEvent *) &msg);
+ XSync (display, False);
+
+ XSetErrorHandler (oldHandler);
+ #if OSL_DEBUG_LEVEL > 1
+ if (badWindowFound)
+ fprintf (stderr, "No FWS client window to register with.\n");
+ #endif
+
+ return !badWindowFound;
+}
+
+/*************************************<->***********************************
+ *
+ * AddFwsProtocols -
+ *
+ * Add the FWS protocol atoms to the WMProtocols property for the window.
+ *
+ *************************************<->***********************************/
+
+void
+AddFwsProtocols (Display *display, Window window)
+{
+ #define MAX_FWS_PROTOS 10
+
+ Atom fwsProtocols[ MAX_FWS_PROTOS ];
+ int nProtos = 0;
+
+ fwsProtocols[ nProtos++ ] = FWS_CLIENT;
+ fwsProtocols[ nProtos++ ] = FWS_STACK_UNDER;
+ fwsProtocols[ nProtos++ ] = FWS_STATE_CHANGE;
+ fwsProtocols[ nProtos++ ] = FWS_PASS_ALL_INPUT;
+ XChangeProperty (display, window, WM_PROTOCOLS,
+ XA_ATOM, 32, PropModeAppend,
+ (unsigned char *) fwsProtocols, nProtos);
+}
+
diff --git a/vcl/unx/generic/window/FWS.hxx b/vcl/unx/generic/window/FWS.hxx
new file mode 100644
index 000000000000..a687870ede4a
--- /dev/null
+++ b/vcl/unx/generic/window/FWS.hxx
@@ -0,0 +1,64 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _FOREIGN_WINDOW_SYSTEM_HXX
+#define _FOREIGN_WINDOW_SYSTEM_HXX
+
+#include <X11/Xlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Initialize our atoms and determine if the current window manager is
+ * providing FWS extension support.
+ */
+
+Bool
+WMSupportsFWS (Display *display, int screen);
+
+/* Send a client message to the FWS_COMM_WINDOW indicating the existance
+ * of a new FWS client window. Be careful to avoid BadWindow errors on
+ * the XSendEvent in case the FWS_COMM_WINDOW root window property had
+ * old/obsolete junk in it.
+ */
+
+Bool
+RegisterFwsWindow (Display *display, Window window);
+
+/* Add the FWS protocol atoms to the WMProtocols property for the window.
+ */
+
+void
+AddFwsProtocols (Display *display, Window window);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif // _FOREIGN_WINDOW_SYSTEM_HXX
+
diff --git a/vcl/unx/generic/window/makefile.mk b/vcl/unx/generic/window/makefile.mk
new file mode 100644
index 000000000000..c5cd95ba6b1c
--- /dev/null
+++ b/vcl/unx/generic/window/makefile.mk
@@ -0,0 +1,59 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=vcl
+TARGET=salwin
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUIBASE)"!="unx"
+
+dummy:
+ @echo "Nothing to build for GUIBASE $(GUIBASE)"
+
+.ELSE # "$(GUIBASE)"!="unx"
+
+SLOFILES= \
+ $(SLO)/FWS.obj $(SLO)/salframe.obj $(SLO)/salobj.obj
+
+.ENDIF # "$(GUIBASE)"!="unx"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx
new file mode 100644
index 000000000000..7be7d9bff6c5
--- /dev/null
+++ b/vcl/unx/generic/window/salframe.cxx
@@ -0,0 +1,4520 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tools/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( 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_ = TRUE;
+ bMapped_ = 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, 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_ = FALSE;
+
+ // set bViewable_ to TRUE: hack GetClientSize to report something
+ // different to 0/0 before first map
+ bViewable_ = TRUE;
+ bMapped_ = FALSE;
+ bDefaultPosition_ = TRUE;
+ nVisibility_ = VisibilityFullyObscured;
+ m_nWorkArea = 0;
+ mbInShow = 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( FALSE, 0 );
+
+ if( bMapped_ )
+ Show( 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( BOOL /*bEnable*/ )
+{
+ // NYI: enable/disable frame
+}
+
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+void X11SalFrame::SetIcon( USHORT 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;
+
+ 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( BOOL bVisible, 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 = 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( FALSE );
+ }
+ }
+ }
+
+ // update NET_WM_STATE which may have been deleted due to earlier Show(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( 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(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( USHORT 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, USHORT 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( 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 );
+ }
+}
+
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+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 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( FALSE );
+ maGeometry.nX = aNewScreenRect.Left() + (maGeometry.nX - aOldScreenRect.Left());
+ maGeometry.nY = aNewScreenRect.Top() + (maGeometry.nY - aOldScreenRect.Top());
+ createNewWindow( None, m_nScreen );
+ if( bVisible )
+ Show( TRUE );
+ maGeometry.nScreenNumber = nNewScreen;
+ }
+ else if( sal_Int32(nNewScreen) < GetDisplay()->GetScreenCount() )
+ {
+ bool bVisible = bMapped_;
+ if( bVisible )
+ Show( FALSE );
+ createNewWindow( None, nNewScreen );
+ if( bVisible )
+ Show( TRUE );
+ maGeometry.nScreenNumber = nNewScreen;
+ }
+}
+
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+void X11SalFrame::ShowFullScreen( 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( FALSE );
+ maGeometry.nX = aRect.Left();
+ maGeometry.nY = aRect.Top();
+ maGeometry.nWidth = aRect.GetWidth();
+ maGeometry.nHeight = aRect.GetHeight();
+ mbMaximizedHorz = mbMaximizedVert = false;
+ mbFullScreen = true;
+ createNewWindow( None, m_nScreen );
+ if( GetDisplay()->getWMAdaptor()->isLegacyPartialFullscreen() )
+ GetDisplay()->getWMAdaptor()->enableAlwaysOnTop( this, true );
+ else
+ GetDisplay()->getWMAdaptor()->showFullScreen( this, true );
+ if( bVisible )
+ Show(TRUE);
+
+ }
+ else
+ {
+ mbFullScreen = false;
+ nStyle_ &= ~SAL_FRAME_STYLE_PARTIAL_FULLSCREEN;
+ bool bVisible = bMapped_;
+ Rectangle aRect = maRestorePosSize;
+ maRestorePosSize = Rectangle();
+ if( bVisible )
+ Show( 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( 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( FALSE );
+ createNewWindow( None, nScreen );
+ if( mbFullScreen )
+ pDisplay_->getWMAdaptor()->showFullScreen( this, true );
+ if( bVisible )
+ Show( 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( 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 XLIB_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
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+BOOL X11SalFrame::PostEvent( void *pData )
+{
+ GetDisplay()->SendInternalEvent( this, pData );
+ return 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( USHORT nFlags )
+{
+ if (mpInputContext != NULL)
+ mpInputContext->EndExtTextInput( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+XubString X11SalFrame::GetKeyName( USHORT nKeyCode )
+{
+ return GetDisplay()->GetKeyName( nKeyCode );
+}
+
+XubString X11SalFrame::GetSymbolKeyName( const XubString&, USHORT nKeyCode )
+{
+ return GetKeyName( nKeyCode );
+}
+
+BOOL X11SalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& )
+{
+ // not supported yet
+ return 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( 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( 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( 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 USHORT sal_GetCode( int state )
+{
+ USHORT 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;
+ USHORT 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( 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 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
+{
+ USHORT nKeyCode;
+ sal_Unicode nCharCode;
+ KeyAlternate() : nKeyCode( 0 ), nCharCode( 0 ) {}
+ KeyAlternate( USHORT nKey, sal_Unicode nChar = 0 ) : nKeyCode( nKey ), nCharCode( nChar ) {}
+};
+
+inline KeyAlternate
+GetAlternateKeyCode( const USHORT 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() )
+ {
+ USHORT 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 = 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<USHORT> 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 = 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 )
+ {
+ USHORT 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 = 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;
+ USHORT nKeyCode;
+ USHORT 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.
+ USHORT nExtModMask = 0;
+ USHORT 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 )
+ {
+ USHORT 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 )
+ {
+ 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 };
+ USHORT 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;
+ BOOL bNone = pDisplay_->GetProperties()
+ & PROPERTY_SUPPORT_WM_Parent_Pixmap_None;
+ 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(TRUE) is
+ * immediately followed by Show(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( 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_ = TRUE;
+ bViewable_ = TRUE;
+ nRet = 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 = FALSE;
+ m_bSetFocusOnMap = false;
+ }
+ break;
+
+ case UnmapNotify:
+ if( pEvent->xunmap.window == GetShellWindow() )
+ {
+ bMapped_ = FALSE;
+ bViewable_ = FALSE;
+ nRet = 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 = 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( ULONG nRects )
+{
+ if( m_pClipRectangles )
+ delete [] m_pClipRectangles;
+ if( nRects )
+ m_pClipRectangles = new XRectangle[nRects];
+ else
+ m_pClipRectangles = NULL;
+ m_nMaxClipRect = static_cast<int>(nRects);
+ m_nCurClipRect = 0;
+}
+
+void X11SalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
+{
+ if( m_pClipRectangles && m_nCurClipRect < m_nMaxClipRect )
+ {
+ m_pClipRectangles[m_nCurClipRect].x = nX;
+ m_pClipRectangles[m_nCurClipRect].y = nY;
+ m_pClipRectangles[m_nCurClipRect].width = nWidth;
+ m_pClipRectangles[m_nCurClipRect].height = nHeight;
+ m_nCurClipRect++;
+ }
+}
+
+void X11SalFrame::EndSetClipRegion()
+{
+ const int dest_kind = ShapeBounding;
+ const int ordering = YSorted;
+ const int op = ShapeSet;
+
+ XLIB_Window aShapeWindow = mhShellWindow;
+ XShapeCombineRectangles ( GetDisplay()->GetDisplay(),
+ aShapeWindow,
+ dest_kind,
+ 0, 0, // x_off, y_off
+ m_pClipRectangles,
+ m_nCurClipRect,
+ op, ordering );
+
+}
+
diff --git a/vcl/unx/generic/window/salobj.cxx b/vcl/unx/generic/window/salobj.cxx
new file mode 100644
index 000000000000..6651b5b3eccb
--- /dev/null
+++ b/vcl/unx/generic/window/salobj.cxx
@@ -0,0 +1,567 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+#include <tools/debug.hxx>
+
+#include <vcl/keycodes.hxx>
+
+#include <tools/prex.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/shape.h>
+#include <tools/postx.h>
+
+#include <unx/salunx.h>
+#include <unx/salstd.hxx>
+#include <unx/saldata.hxx>
+#include <unx/salinst.h>
+#include <unx/saldisp.hxx>
+#include <unx/salframe.h>
+#include <unx/salobj.h>
+
+#include <salwtype.hxx>
+
+
+// =======================================================================
+// SalInstance member to create and destroy a SalObject
+
+SalObject* X11SalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, BOOL bShow )
+{
+ return X11SalObject::CreateObject( pParent, pWindowData, bShow );
+}
+
+X11SalObject* X11SalObject::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, BOOL bShow )
+{
+ int error_base, event_base;
+ X11SalObject* pObject = new X11SalObject();
+ SystemChildData* pObjData = const_cast<SystemChildData*>(pObject->GetSystemData());
+
+ if ( ! XShapeQueryExtension( (Display*)pObjData->pDisplay,
+ &event_base, &error_base ) )
+ {
+ delete pObject;
+ return NULL;
+ }
+
+ pObject->mpParent = pParent;
+
+ SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
+ const SystemEnvData* pEnv = pParent->GetSystemData();
+ Display* pDisp = pSalDisp->GetDisplay();
+ XLIB_Window aObjectParent = (XLIB_Window)pEnv->aWindow;
+
+ // find out on which screen that window is
+ XWindowAttributes aParentAttr;
+ XGetWindowAttributes( pDisp, aObjectParent, &aParentAttr );
+ int nScreen = XScreenNumberOfScreen( aParentAttr.screen );
+ Visual* pVisual = (pWindowData && pWindowData->pVisual) ?
+ (Visual*)pWindowData->pVisual :
+ pSalDisp->GetVisual( nScreen ).GetVisual();
+ // get visual info
+ VisualID aVisID = XVisualIDFromVisual( pVisual );
+ XVisualInfo aTemplate;
+ aTemplate.visualid = aVisID;
+ int nVisuals = 0;
+ XVisualInfo* pInfos = XGetVisualInfo( pDisp, VisualIDMask, &aTemplate, &nVisuals );
+ // only one VisualInfo structure can match the visual id
+ DBG_ASSERT( nVisuals == 1, "match count for visual id is not 1" );
+ unsigned int nDepth = pInfos->depth;
+ XFree( pInfos );
+ XSetWindowAttributes aAttribs;
+ aAttribs.event_mask = StructureNotifyMask
+ | ButtonPressMask
+ | ButtonReleaseMask
+ | PointerMotionMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ | FocusChangeMask
+ | ExposureMask
+ ;
+
+ pObject->maPrimary =
+ XCreateSimpleWindow( pDisp,
+ aObjectParent,
+ 0, 0,
+ 1, 1, 0,
+ pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
+ pSalDisp->GetColormap( nScreen ).GetWhitePixel()
+ );
+ if( aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() )
+ {
+ pObject->maSecondary =
+ XCreateSimpleWindow( pDisp,
+ pObject->maPrimary,
+ 0, 0,
+ 1, 1, 0,
+ pSalDisp->GetColormap( nScreen ).GetBlackPixel(),
+ pSalDisp->GetColormap( nScreen ).GetWhitePixel()
+ );
+ }
+ else
+ {
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "visual id of vcl %x, of visual %x\n",
+ static_cast<unsigned int> (pSalDisp->GetVisual( nScreen ).GetVisualId()),
+ static_cast<unsigned int> (aVisID) );
+ #endif
+ pSalDisp->GetXLib()->PushXErrorLevel( true );
+
+ // create colormap for visual - there might not be one
+ pObject->maColormap = aAttribs.colormap = XCreateColormap(
+ pDisp,
+ pSalDisp->GetRootWindow( nScreen ),
+ pVisual,
+ AllocNone );
+
+ pObject->maSecondary =
+ XCreateWindow( pDisp,
+ pSalDisp->GetRootWindow( nScreen ),
+ 0, 0,
+ 1, 1, 0,
+ nDepth, InputOutput,
+ pVisual,
+ CWEventMask|CWColormap, &aAttribs );
+ XSync( pDisp, False );
+ BOOL bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
+ pSalDisp->GetXLib()->PopXErrorLevel();
+ if( bWasXError )
+ {
+ pObject->maSecondary = None;
+ delete pObject;
+ return NULL;
+ }
+ XReparentWindow( pDisp, pObject->maSecondary, pObject->maPrimary, 0, 0 );
+ }
+
+ pSalDisp->GetXLib()->PushXErrorLevel( true );
+ if( bShow ) {
+ XMapWindow( pDisp, pObject->maSecondary );
+ XMapWindow( pDisp, pObject->maPrimary );
+ }
+
+ pObjData->pDisplay = pDisp;
+ pObjData->aWindow = pObject->maSecondary;
+ pObjData->pWidget = NULL;
+ pObjData->pVisual = pVisual;
+ pObjData->nDepth = nDepth;
+ pObjData->aColormap = aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() ?
+ pSalDisp->GetColormap( nScreen ).GetXColormap() : None;
+ pObjData->pAppContext = NULL;
+
+ XSync(pDisp, False);
+ BOOL bWasXError = pSalDisp->GetXLib()->HasXErrorOccured();
+ pSalDisp->GetXLib()->PopXErrorLevel();
+ if( bWasXError )
+ {
+ delete pObject;
+ return NULL;
+ }
+
+ return pObject;
+}
+
+
+void X11SalInstance::DestroyObject( SalObject* pObject )
+{
+ delete pObject;
+}
+
+
+// ======================================================================
+// SalClipRegion is a member of SalObject
+// definition of SalClipRegion my be found in unx/inc/salobj.h
+
+
+SalClipRegion::SalClipRegion()
+{
+ ClipRectangleList = NULL;
+ numClipRectangles = 0;
+ maxClipRectangles = 0;
+ nClipRegionType = SAL_OBJECT_CLIP_INCLUDERECTS;
+}
+
+
+SalClipRegion::~SalClipRegion()
+{
+ if ( ClipRectangleList )
+ delete [] ClipRectangleList;
+}
+
+
+void
+SalClipRegion::BeginSetClipRegion( ULONG nRects )
+{
+ if (ClipRectangleList)
+ delete [] ClipRectangleList;
+
+ ClipRectangleList = new XRectangle[nRects];
+ numClipRectangles = 0;
+ maxClipRectangles = nRects;
+}
+
+
+void
+SalClipRegion::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
+{
+ if ( nWidth && nHeight && (numClipRectangles < maxClipRectangles) )
+ {
+ XRectangle *aRect = ClipRectangleList + numClipRectangles;
+
+ aRect->x = (short) nX;
+ aRect->y = (short) nY;
+ aRect->width = (unsigned short) nWidth;
+ aRect->height= (unsigned short) nHeight;
+
+ numClipRectangles++;
+ }
+}
+
+
+// =======================================================================
+// SalObject Implementation
+
+
+X11SalObject::X11SalObject()
+{
+ maSystemChildData.nSize = sizeof( SystemChildData );
+ maSystemChildData.pDisplay = GetX11SalData()->GetDisplay()->GetDisplay();
+ maSystemChildData.aWindow = None;
+ maSystemChildData.pSalFrame = 0;
+ maSystemChildData.pWidget = 0;
+ maSystemChildData.pVisual = 0;
+ maSystemChildData.nDepth = 0;
+ maSystemChildData.aColormap = 0;
+ maSystemChildData.pAppContext = NULL;
+ maSystemChildData.aShellWindow = 0;
+ maSystemChildData.pShellWidget = NULL;
+ maPrimary = 0;
+ maSecondary = 0;
+ maColormap = 0;
+
+ std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
+ rObjects.push_back( this );
+}
+
+
+X11SalObject::~X11SalObject()
+{
+ std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
+ rObjects.remove( this );
+ SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
+ pSalDisp->GetXLib()->PushXErrorLevel( true );
+ if ( maSecondary )
+ XDestroyWindow( (Display*)maSystemChildData.pDisplay, maSecondary );
+ if ( maPrimary )
+ XDestroyWindow( (Display*)maSystemChildData.pDisplay, maPrimary );
+ if ( maColormap )
+ XFreeColormap((Display*)maSystemChildData.pDisplay, maColormap);
+ XSync( (Display*)maSystemChildData.pDisplay, False );
+ pSalDisp->GetXLib()->PopXErrorLevel();
+}
+
+
+void
+X11SalObject::ResetClipRegion()
+{
+ maClipRegion.ResetClipRegion();
+
+ const int dest_kind = ShapeBounding;
+ const int op = ShapeSet;
+ const int ordering = YSorted;
+
+ XWindowAttributes win_attrib;
+ XRectangle win_size;
+
+ XLIB_Window aShapeWindow = maPrimary;
+
+ XGetWindowAttributes ( (Display*)maSystemChildData.pDisplay,
+ aShapeWindow,
+ &win_attrib );
+
+ win_size.x = 0;
+ win_size.y = 0;
+ win_size.width = win_attrib.width;
+ win_size.height = win_attrib.height;
+
+ XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
+ aShapeWindow,
+ dest_kind,
+ 0, 0, // x_off, y_off
+ &win_size, // list of rectangles
+ 1, // number of rectangles
+ op, ordering );
+}
+
+
+void
+X11SalObject::BeginSetClipRegion( ULONG nRectCount )
+{
+ maClipRegion.BeginSetClipRegion ( nRectCount );
+}
+
+
+void
+X11SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight )
+{
+ maClipRegion.UnionClipRegion ( nX, nY, nWidth, nHeight );
+}
+
+
+void
+X11SalObject::EndSetClipRegion()
+{
+ XRectangle *pRectangles = maClipRegion.EndSetClipRegion ();
+ const int nType = maClipRegion.GetClipRegionType();
+ const int nRectangles = maClipRegion.GetRectangleCount();
+
+ const int dest_kind = ShapeBounding;
+ const int ordering = YSorted;
+ int op;
+
+ switch ( nType )
+ {
+ case SAL_OBJECT_CLIP_INCLUDERECTS :
+ op = ShapeSet;
+ break;
+ case SAL_OBJECT_CLIP_EXCLUDERECTS :
+ op = ShapeSubtract;
+ break;
+ case SAL_OBJECT_CLIP_ABSOLUTE :
+ op = ShapeSet;
+ break;
+ default :
+ op = ShapeUnion;
+ }
+
+ XLIB_Window aShapeWindow = maPrimary;
+
+ XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay,
+ aShapeWindow,
+ dest_kind,
+ 0, 0, // x_off, y_off
+ pRectangles,
+ nRectangles,
+ op, ordering );
+}
+
+
+USHORT
+X11SalObject::GetClipRegionType()
+{
+ return maClipRegion.GetClipRegionType();
+}
+
+// -----------------------------------------------------------------------
+
+void
+X11SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
+{
+ if ( maPrimary && maSecondary && nWidth && nHeight )
+ {
+ XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
+ maPrimary,
+ nX, nY, nWidth, nHeight );
+ XMoveResizeWindow( (Display*)maSystemChildData.pDisplay,
+ maSecondary,
+ 0, 0, nWidth, nHeight );
+ }
+}
+
+
+void
+X11SalObject::Show( BOOL bVisible )
+{
+ if ( ! maSystemChildData.aWindow )
+ return;
+
+ if ( bVisible ) {
+ XMapWindow( (Display*)maSystemChildData.pDisplay,
+ maSecondary );
+ XMapWindow( (Display*)maSystemChildData.pDisplay,
+ maPrimary );
+ } else {
+ XUnmapWindow( (Display*)maSystemChildData.pDisplay,
+ maPrimary );
+ XUnmapWindow( (Display*)maSystemChildData.pDisplay,
+ maSecondary );
+ }
+ mbVisible = bVisible;
+}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::Enable( BOOL )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::GrabFocus()
+{
+ if( mbVisible )
+ XSetInputFocus( (Display*)maSystemChildData.pDisplay,
+ maSystemChildData.aWindow,
+ RevertToNone,
+ CurrentTime );
+}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::SetBackground()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::SetBackground( SalColor )
+{
+}
+
+// -----------------------------------------------------------------------
+
+const SystemChildData* X11SalObject::GetSystemData() const
+{
+ return &maSystemChildData;
+}
+
+static USHORT sal_GetCode( int state )
+{
+ USHORT nCode = 0;
+
+ if( state & Button1Mask )
+ nCode |= MOUSE_LEFT;
+ if( state & Button2Mask )
+ nCode |= MOUSE_MIDDLE;
+ if( state & Button3Mask )
+ nCode |= MOUSE_RIGHT;
+
+ if( state & ShiftMask )
+ nCode |= KEY_SHIFT;
+ if( state & ControlMask )
+ nCode |= KEY_MOD1;
+ if( state & Mod1Mask )
+ nCode |= KEY_MOD2;
+ if( state & Mod3Mask )
+ nCode |= KEY_MOD3;
+
+ return nCode;
+}
+
+long X11SalObject::Dispatch( XEvent* pEvent )
+{
+ std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects();
+
+ for( std::list< SalObject* >::iterator it = rObjects.begin(); it != rObjects.end(); ++it )
+ {
+ X11SalObject* pObject = static_cast<X11SalObject*>(*it);
+ if( pEvent->xany.window == pObject->maPrimary ||
+ pEvent->xany.window == pObject->maSecondary )
+ {
+ if( pObject->IsMouseTransparent() && (
+ pEvent->type == ButtonPress ||
+ pEvent->type == ButtonRelease ||
+ pEvent->type == EnterNotify ||
+ pEvent->type == LeaveNotify ||
+ pEvent->type == MotionNotify
+ )
+ )
+ {
+ SalMouseEvent aEvt;
+ const SystemEnvData* pParentData = pObject->mpParent->GetSystemData();
+ int dest_x, dest_y;
+ XLIB_Window aChild = None;
+ XTranslateCoordinates( pEvent->xbutton.display,
+ pEvent->xbutton.root,
+ pParentData->aWindow,
+ pEvent->xbutton.x_root,
+ pEvent->xbutton.y_root,
+ &dest_x, &dest_y,
+ &aChild );
+ aEvt.mnX = dest_x;
+ aEvt.mnY = dest_y;
+ aEvt.mnTime = pEvent->xbutton.time;
+ aEvt.mnCode = sal_GetCode( pEvent->xbutton.state );
+ aEvt.mnButton = 0;
+ USHORT nEvent = 0;
+ if( pEvent->type == ButtonPress ||
+ pEvent->type == ButtonRelease )
+ {
+ switch( pEvent->xbutton.button )
+ {
+ case Button1: aEvt.mnButton = MOUSE_LEFT;break;
+ case Button2: aEvt.mnButton = MOUSE_MIDDLE;break;
+ case Button3: aEvt.mnButton = MOUSE_RIGHT;break;
+ }
+ nEvent = (pEvent->type == ButtonPress) ?
+ SALEVENT_MOUSEBUTTONDOWN :
+ SALEVENT_MOUSEBUTTONUP;
+ }
+ else if( pEvent->type == EnterNotify )
+ nEvent = SALEVENT_MOUSELEAVE;
+ else
+ nEvent = SALEVENT_MOUSEMOVE;
+ pObject->mpParent->CallCallback( nEvent, &aEvt );
+ }
+ else
+ {
+ switch( pEvent->type )
+ {
+ case UnmapNotify:
+ pObject->mbVisible = FALSE;
+ return 1;
+ case MapNotify:
+ pObject->mbVisible = TRUE;
+ return 1;
+ case ButtonPress:
+ pObject->CallCallback( SALOBJ_EVENT_TOTOP, NULL );
+ return 1;
+ case FocusIn:
+ pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, NULL );
+ return 1;
+ case FocusOut:
+ pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, NULL );
+ return 1;
+ default: break;
+ }
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void X11SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ )
+{
+}
+