Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/vcl/unx/generic/app/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 78 kB image not shown  

Quelle  wmadaptor.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <string_view>

#include <i18nlangtag/languagetag.hxx>
#include <rtl/locale.h>

#include <osl/thread.h>
#include <osl/process.h>
#include <sal/macros.h>
#include <sal/log.hxx>
#include <comphelper/string.hxx>
#include <configsettings.hxx>
#include <o3tl/string_view.hxx>

#include <unx/wmadaptor.hxx>
#include <unx/saldisp.hxx>
#include <unx/salframe.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

namespace vcl_sal {

class NetWMAdaptor : public WMAdaptor
{
    void setNetWMState( X11SalFrame* pFrame ) const;
    void initAtoms();
    virtual bool isValid() const override;
public:
    explicit NetWMAdaptor( SalDisplay* );

    virtual void setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const override;
    virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = truebool bVertical = true ) const override;
    virtual void setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pTransientFrame ) const override;
    virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const override;
    virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const override;
    virtual void showFullScreen( X11SalFrame* pFrame, bool bFullScreen ) const override;
    virtual void frameIsMapping( X11SalFrame* pFrame ) const override;
    virtual void setUserTime( X11SalFrame* i_pFrame, tools::Long i_nUserTime ) const override;
};

class GnomeWMAdaptor : public WMAdaptor
{
    bool m_bValid;

    void setGnomeWMState( X11SalFrame* pFrame ) const;
    void initAtoms();
    virtual bool isValid() const override;
public:
    explicit GnomeWMAdaptor( SalDisplay * );

    virtual void maximizeFrame( X11SalFrame* pFrame, bool bHorizontal = truebool bVertical = true ) const override;
    virtual void enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const override;
    virtual int handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const override;
};

}

using namespace vcl_sal;

namespace {

struct WMAdaptorProtocol
{
    const char* pProtocol;
    int             nProtocol;
};

}

/*
 *  table must be sorted ascending in strings
 *  since it is use with bsearch
 */

const WMAdaptorProtocol aProtocolTab[] =
{
    { "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE", WMAdaptor::KDE_NET_WM_WINDOW_TYPE_OVERRIDE },
    { "_NET_ACTIVE_WINDOW", WMAdaptor::NET_ACTIVE_WINDOW },
    { "_NET_CURRENT_DESKTOP", WMAdaptor::NET_CURRENT_DESKTOP },
    { "_NET_NUMBER_OF_DESKTOPS", WMAdaptor::NET_NUMBER_OF_DESKTOPS },
    { "_NET_WM_DESKTOP", WMAdaptor::NET_WM_DESKTOP },
    { "_NET_WM_ICON", WMAdaptor::NET_WM_ICON },
    { "_NET_WM_ICON_NAME", WMAdaptor::NET_WM_ICON_NAME },
    { "_NET_WM_PING", WMAdaptor::NET_WM_PING },
    { "_NET_WM_STATE", WMAdaptor::NET_WM_STATE },
    { "_NET_WM_STATE_ABOVE", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
    { "_NET_WM_STATE_FULLSCREEN", WMAdaptor::NET_WM_STATE_FULLSCREEN },
    { "_NET_WM_STATE_MAXIMIZED_HORIZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ }, // common bug in e.g. older kwin and sawfish implementations
    { "_NET_WM_STATE_MAXIMIZED_HORZ", WMAdaptor::NET_WM_STATE_MAXIMIZED_HORZ },
    { "_NET_WM_STATE_MAXIMIZED_VERT", WMAdaptor::NET_WM_STATE_MAXIMIZED_VERT },
    { "_NET_WM_STATE_MODAL", WMAdaptor::NET_WM_STATE_MODAL },
    { "_NET_WM_STATE_SKIP_PAGER", WMAdaptor::NET_WM_STATE_SKIP_PAGER },
    { "_NET_WM_STATE_SKIP_TASKBAR", WMAdaptor::NET_WM_STATE_SKIP_TASKBAR },
    { "_NET_WM_STATE_STAYS_ON_TOP", WMAdaptor::NET_WM_STATE_STAYS_ON_TOP },
    { "_NET_WM_STATE_STICKY", WMAdaptor::NET_WM_STATE_STICKY },
    { "_NET_WM_STRUT", WMAdaptor::NET_WM_STRUT },
    { "_NET_WM_STRUT_PARTIAL", WMAdaptor::NET_WM_STRUT_PARTIAL },
    { "_NET_WM_WINDOW_TYPE", WMAdaptor::NET_WM_WINDOW_TYPE },
    { "_NET_WM_WINDOW_TYPE_DESKTOP", WMAdaptor::NET_WM_WINDOW_TYPE_DESKTOP },
    { "_NET_WM_WINDOW_TYPE_DIALOG", WMAdaptor::NET_WM_WINDOW_TYPE_DIALOG },
    { "_NET_WM_WINDOW_TYPE_DOCK", WMAdaptor::NET_WM_WINDOW_TYPE_DOCK },
    { "_NET_WM_WINDOW_TYPE_MENU", WMAdaptor::NET_WM_WINDOW_TYPE_MENU },
    { "_NET_WM_WINDOW_TYPE_NORMAL", WMAdaptor::NET_WM_WINDOW_TYPE_NORMAL },
    { "_NET_WM_WINDOW_TYPE_SPLASH", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH },
    { "_NET_WM_WINDOW_TYPE_SPLASHSCREEN", WMAdaptor::NET_WM_WINDOW_TYPE_SPLASH }, // bug in Metacity 2.4.1
    { "_NET_WM_WINDOW_TYPE_TOOLBAR", WMAdaptor::NET_WM_WINDOW_TYPE_TOOLBAR },
    { "_NET_WM_WINDOW_TYPE_UTILITY", WMAdaptor::NET_WM_WINDOW_TYPE_UTILITY },
    { "_NET_WORKAREA", WMAdaptor::NET_WORKAREA },
    { "_WIN_APP_STATE", WMAdaptor::WIN_APP_STATE },
    { "_WIN_CLIENT_LIST", WMAdaptor::WIN_CLIENT_LIST },
    { "_WIN_EXPANDED_SIZE", WMAdaptor::WIN_EXPANDED_SIZE },
    { "_WIN_HINTS", WMAdaptor::WIN_HINTS },
    { "_WIN_ICONS", WMAdaptor::WIN_ICONS },
    { "_WIN_LAYER", WMAdaptor::WIN_LAYER },
    { "_WIN_STATE", WMAdaptor::WIN_STATE },
    { "_WIN_WORKSPACE", WMAdaptor::WIN_WORKSPACE },
    { "_WIN_WORKSPACE_COUNT", WMAdaptor::WIN_WORKSPACE_COUNT }
};

/*
 *  table containing atoms to get anyway
 */


const WMAdaptorProtocol aAtomTab[] =
{
    { "WM_STATE", WMAdaptor::WM_STATE },
    { "_MOTIF_WM_HINTS", WMAdaptor::MOTIF_WM_HINTS },
    { "WM_PROTOCOLS", WMAdaptor::WM_PROTOCOLS },
    { "WM_DELETE_WINDOW", WMAdaptor::WM_DELETE_WINDOW },
    { "WM_TAKE_FOCUS", WMAdaptor::WM_TAKE_FOCUS },
    { "WM_COMMAND", WMAdaptor::WM_COMMAND },
    { "WM_CLIENT_LEADER", WMAdaptor::WM_CLIENT_LEADER },
    { "WM_LOCALE_NAME", WMAdaptor::WM_LOCALE_NAME },
    { "WM_TRANSIENT_FOR", WMAdaptor::WM_TRANSIENT_FOR },
    { "SAL_QUITEVENT", WMAdaptor::SAL_QUITEVENT },
    { "SAL_USEREVENT", WMAdaptor::SAL_USEREVENT },
    { "SAL_EXTTEXTEVENT", WMAdaptor::SAL_EXTTEXTEVENT },
    { "SAL_GETTIMEEVENT", WMAdaptor::SAL_GETTIMEEVENT },
    { "VCL_SYSTEM_SETTINGS", WMAdaptor::VCL_SYSTEM_SETTINGS },
    { "_XSETTINGS_SETTINGS", WMAdaptor::XSETTINGS },
    { "_XEMBED", WMAdaptor::XEMBED },
    { "_XEMBED_INFO", WMAdaptor::XEMBED_INFO },
    { "_NET_WM_USER_TIME", WMAdaptor::NET_WM_USER_TIME },
    { "_NET_WM_PID", WMAdaptor::NET_WM_PID }
};

extern "C" {
static int compareProtocol( const void* pLeft, const void* pRight )
{
    return strcmp( static_cast<const WMAdaptorProtocol*>(pLeft)->pProtocol, static_cast<const WMAdaptorProtocol*>(pRight)->pProtocol );
}
}

std::unique_ptr<WMAdaptor> WMAdaptor::createWMAdaptor( SalDisplay* pSalDisplay )
{
    std::unique_ptr<WMAdaptor> pAdaptor;

    // try a NetWM
    pAdaptor.reset(new NetWMAdaptor( pSalDisplay ));
    if( ! pAdaptor->isValid() )
    {
        pAdaptor.reset();
    }
#if OSL_DEBUG_LEVEL > 1
    else
        SAL_INFO("vcl.app""WM supports extended WM hints.");
#endif

    // try a GnomeWM
    if( ! pAdaptor )
    {
        pAdaptor.reset(new GnomeWMAdaptor( pSalDisplay ));
        if( ! pAdaptor->isValid() )
        {
            pAdaptor.reset();
        }
#if OSL_DEBUG_LEVEL > 1
        else
            SAL_INFO("vcl.app""WM supports GNOME WM hints.");
#endif
    }

    if( ! pAdaptor )
        pAdaptor.reset(new WMAdaptor( pSalDisplay ));

#if OSL_DEBUG_LEVEL > 1
    SAL_INFO("vcl.app""Window Manager's name is \""
            << pAdaptor->getWindowManagerName()
            << "\".");
#endif
    return pAdaptor;
}

/*
 *  WMAdaptor constructor
 */


WMAdaptor::WMAdaptor( SalDisplay* pDisplay ) :
        m_pSalDisplay( pDisplay ),
        m_bEnableAlwaysOnTopWorks( false ),
        m_bLegacyPartialFullscreen( false ),
        m_nWinGravity( StaticGravity ),
        m_nInitWinGravity( StaticGravity ),
        m_bWMshouldSwitchWorkspace( true ),
        m_bWMshouldSwitchWorkspaceInit( false )
{
    Atom                aRealType   = None;
    int                 nFormat     = 8;
    unsigned long       nItems      = 0;
    unsigned long       nBytesLeft  = 0;
    unsigned char*  pProperty   = nullptr;

    // default desktops
    m_nDesktops = 1;
    m_aWMWorkAreas = ::std::vector< AbsoluteScreenPixelRectangle >
        ( 1, AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint(), m_pSalDisplay->GetScreenSize( m_pSalDisplay->GetDefaultXScreen() ) ) );
    m_bEqualWorkAreas = true;

    memset( m_aWMAtoms, 0, sizeof( m_aWMAtoms ) );
    m_pDisplay = m_pSalDisplay->GetDisplay();

    initAtoms();
    getNetWmName(); // try to discover e.g. Sawfish

    if( m_aWMName.isEmpty() )
    {
        // check for ReflectionX wm (as it needs a workaround in Windows mode
        Atom aRwmRunning = XInternAtom( m_pDisplay, "RWM_RUNNING"True );
        if( aRwmRunning != None &&
            XGetWindowProperty( m_pDisplay,
                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                aRwmRunning,
                                0, 32,
                                False,
                                aRwmRunning,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty ) == 0 )
        {
            if( aRealType == aRwmRunning )
                m_aWMName = "ReflectionX";
            XFree( pProperty );
        }
        else
        {
            aRwmRunning = XInternAtom( m_pDisplay, "_WRQ_WM_RUNNING"True );
            if( aRwmRunning != None &&
                XGetWindowProperty( m_pDisplay,
                                    m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                    aRwmRunning,
                                    0, 32,
                                    False,
                                    XA_STRING,
                                    &aRealType,
                                    &nFormat,
                                    &nItems,
                                    &nBytesLeft,
                                    &pProperty ) == 0 )
            {
                if( aRealType == XA_STRING )
                    m_aWMName = "ReflectionX Windows";
                XFree( pProperty );
            }
        }
    }
    if( !m_aWMName.isEmpty() )
        return;

    Atom aTTAPlatform = XInternAtom( m_pDisplay, "TTA_CLIENT_PLATFORM"True );
    if( aTTAPlatform == None ||
        XGetWindowProperty( m_pDisplay,
                            m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                            aTTAPlatform,
                            0, 32,
                            False,
                            XA_STRING,
                            &aRealType,
                            &nFormat,
                            &nItems,
                            &nBytesLeft,
                            &pProperty ) != 0 )
        return;

    if( aRealType == XA_STRING )
    {
        m_aWMName = "Tarantella";
        // #i62319# pretend that AlwaysOnTop works since
        // the alwaysontop workaround in salframe.cxx results
        // in a raise/lower loop on a Windows tarantella client
        // FIXME: this property contains an identification string that
        // in theory should be good enough to recognize running on a
        // Windows client; however this string does not seem to be
        // documented as well as the property itself.
        m_bEnableAlwaysOnTopWorks = true;
    }
    XFree( pProperty );
}

/*
 *  WMAdaptor destructor
 */


WMAdaptor::~WMAdaptor()
{
}

/*
 *  NetWMAdaptor constructor
 */


NetWMAdaptor::NetWMAdaptor( SalDisplay* pSalDisplay ) :
        WMAdaptor( pSalDisplay )
{
    // currently all _NET WMs do transient like expected

    Atom                aRealType   = None;
    int                 nFormat     = 8;
    unsigned long       nItems      = 0;
    unsigned long       nBytesLeft  = 0;
    unsigned char*  pProperty   = nullptr;

    initAtoms();

    // check for NetWM
    bool bNetWM = getNetWmName();
    if( bNetWM
        && XGetWindowProperty( m_pDisplay,
                               m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                               m_aWMAtoms[ NET_SUPPORTED ],
                               0, 0,
                               False,
                               XA_ATOM,
                               &aRealType,
                               &nFormat,
                               &nItems,
                               &nBytesLeft,
                               &pProperty ) == 0
        && aRealType == XA_ATOM
        && nFormat == 32
        )
    {
        if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
        // collect supported protocols
        if( XGetWindowProperty( m_pDisplay,
                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                m_aWMAtoms[ NET_SUPPORTED ],
                                0, nBytesLeft/4,
                                False,
                                XA_ATOM,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty ) == 0
            && nItems
            )
        {
            Atom* pAtoms = reinterpret_cast<Atom*>(pProperty);
            char** pAtomNames = static_cast<char**>(alloca( sizeof(char*)*nItems ));
            if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
            {
#if OSL_DEBUG_LEVEL > 1
                SAL_INFO("vcl.app""supported protocols:");
#endif
                forunsigned long i = 0; i < nItems; i++ )
                {
                    // #i80971# protect against invalid atoms
                    if( pAtomNames[i] == nullptr )
                        continue;

                    WMAdaptorProtocol aSearch;
                    aSearch.pProtocol = pAtomNames[i];
                    WMAdaptorProtocol* pMatch = static_cast<WMAdaptorProtocol*>(
                        bsearch( &aSearch,
                                 aProtocolTab,
                                 SAL_N_ELEMENTS( aProtocolTab ),
                                 sizeofstruct WMAdaptorProtocol ),
                                 compareProtocol ));
                    if( pMatch )
                    {
                        m_aWMAtoms[ pMatch->nProtocol ] = pAtoms[ i ];
                        if( pMatch->nProtocol == NET_WM_STATE_STAYS_ON_TOP )
                            m_bEnableAlwaysOnTopWorks = true;
                    }
#if OSL_DEBUG_LEVEL > 1
                    SAL_INFO("vcl.app"" "
                            << pAtomNames[i]
                            << (((pMatch)&&(pMatch->nProtocol != -1)) ?
                                "" : " (unsupported)"));
#endif
                    XFree( pAtomNames[i] );
                }
            }
            XFree( pProperty );
            pProperty = nullptr;
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }

        // get number of desktops
        if( m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ]
            && XGetWindowProperty( m_pDisplay,
                                   m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                   m_aWMAtoms[ NET_NUMBER_OF_DESKTOPS ],
                                   0, 1,
                                   False,
                                   XA_CARDINAL,
                                   &aRealType,
                                   &nFormat,
                                   &nItems,
                                   &nBytesLeft,
                                   &pProperty ) == 0
            && pProperty
            )
        {
            m_nDesktops = *reinterpret_cast<long*>(pProperty);
            XFree( pProperty );
            pProperty = nullptr;
            // get work areas
            if( m_aWMAtoms[ NET_WORKAREA ]
                && XGetWindowProperty( m_pDisplay,
                                       m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                       m_aWMAtoms[ NET_WORKAREA ],
                                       0, 4*m_nDesktops,
                                       False,
                                       XA_CARDINAL,
                                       &aRealType,
                                       &nFormat,
                                       &nItems,
                                       &nBytesLeft,
                                       &pProperty
                                       ) == 0
                && nItems == 4*static_cast<unsigned>(m_nDesktops)
                )
            {
                m_aWMWorkAreas = ::std::vector< AbsoluteScreenPixelRectangle > ( m_nDesktops );
                tools::Long* pValues = reinterpret_cast<long*>(pProperty);
                forint i = 0; i < m_nDesktops; i++ )
                {
                    AbsoluteScreenPixelPoint aPoint( pValues[4*i],
                                  pValues[4*i+1] );
                    AbsoluteScreenPixelSize aSize( pValues[4*i+2],
                                pValues[4*i+3] );
                    AbsoluteScreenPixelRectangle aWorkArea( aPoint, aSize );
                    m_aWMWorkAreas[i] = aWorkArea;
                    if( aWorkArea != m_aWMWorkAreas[0] )
                        m_bEqualWorkAreas = false;
#if OSL_DEBUG_LEVEL > 1
                    SAL_INFO("vcl.app""workarea " << i
                            << ": " << m_aWMWorkAreas[i].GetWidth()
                            << "x"  << m_aWMWorkAreas[i].GetHeight()
                            << "+"  << m_aWMWorkAreas[i].Left()
                            << "+"  << m_aWMWorkAreas[i].Top());
#endif
                }
                XFree( pProperty );
            }
            else
            {
#if OSL_DEBUG_LEVEL > 1
                SAL_INFO("vcl.app", nItems/4 << " workareas for "
                        << m_nDesktops << " desktops !");
#endif
                if( pProperty )
                {
                    XFree(pProperty);
                    pProperty = nullptr;
                }
            }
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
    }
    else if( pProperty )
    {
        XFree( pProperty );
        pProperty = nullptr;
    }
}

/*
 *  GnomeWMAdaptor constructor
 */


GnomeWMAdaptor::GnomeWMAdaptor( SalDisplay* pSalDisplay ) :
        WMAdaptor( pSalDisplay ),
        m_bValid( false )
{
    // currently all Gnome WMs do transient like expected

    Atom                aRealType   = None;
    int                 nFormat     = 8;
    unsigned long       nItems      = 0;
    unsigned long       nBytesLeft  = 0;
    unsigned char*  pProperty   = nullptr;

    initAtoms();

    // check for GnomeWM
    if( m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ WIN_PROTOCOLS ] )
    {
        if( XGetWindowProperty( m_pDisplay,
                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
                                0, 1,
                                False,
                                XA_CARDINAL,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty ) == 0
            && aRealType == XA_CARDINAL
            && nFormat == 32
            && nItems != 0
            )
        {
            ::Window aWMChild = *reinterpret_cast< ::Window* >(pProperty);
            XFree( pProperty );
            pProperty = nullptr;
            GetGenericUnixSalData()->ErrorTrapPush();
            if( XGetWindowProperty( m_pDisplay,
                                    aWMChild,
                                    m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ],
                                    0, 1,
                                    False,
                                    XA_CARDINAL,
                                    &aRealType,
                                    &nFormat,
                                    &nItems,
                                    &nBytesLeft,
                                    &pProperty ) == 0
                && aRealType == XA_CARDINAL
                && nFormat == 32
                && nItems != 0 )
            {
                if (! GetGenericUnixSalData()->ErrorTrapPop( false ) )
                {
                    GetGenericUnixSalData()->ErrorTrapPush();

                    ::Window aCheckWindow =  *reinterpret_cast< ::Window* >(pProperty);
                    XFree( pProperty );
                    pProperty = nullptr;
                    if( aCheckWindow == aWMChild )
                    {
                        m_bValid = true;
                        /*
                         *  get name of WM
                         *  this is NOT part of the GNOME WM hints, but e.g. Sawfish
                         *  already supports this part of the extended WM hints
                         */

                        m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING"False );
                        getNetWmName();
                    }
                }
                else
                    GetGenericUnixSalData()->ErrorTrapPush();
            }
            GetGenericUnixSalData()->ErrorTrapPop();
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
    }
    if( m_bValid
        && XGetWindowProperty( m_pDisplay,
                               m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                               m_aWMAtoms[ WIN_PROTOCOLS ],
                               0, 0,
                               False,
                               XA_ATOM,
                               &aRealType,
                               &nFormat,
                               &nItems,
                               &nBytesLeft,
                               &pProperty ) == 0
        && aRealType == XA_ATOM
        && nFormat == 32
        )
    {
        if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
        // collect supported protocols
        if( XGetWindowProperty( m_pDisplay,
                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                m_aWMAtoms[ WIN_PROTOCOLS ],
                                0, nBytesLeft/4,
                                False,
                                XA_ATOM,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty ) == 0
            && pProperty
            )
        {
            Atom* pAtoms = reinterpret_cast<Atom*>(pProperty);
            char** pAtomNames = static_cast<char**>(alloca( sizeof(char*)*nItems ));
            if( XGetAtomNames( m_pDisplay, pAtoms, nItems, pAtomNames ) )
            {
#if OSL_DEBUG_LEVEL > 1
                SAL_INFO("vcl.app""supported protocols:");
#endif
                forunsigned long i = 0; i < nItems; i++ )
                {
                    // #i80971# protect against invalid atoms
                    if( pAtomNames[i] == nullptr )
                        continue;

                    WMAdaptorProtocol aSearch;
                    aSearch.pProtocol = pAtomNames[i];
                    WMAdaptorProtocol* pMatch = static_cast<WMAdaptorProtocol*>(
                        bsearch( &aSearch,
                                 aProtocolTab,
                                 SAL_N_ELEMENTS( aProtocolTab ),
                                 sizeofstruct WMAdaptorProtocol ),
                                 compareProtocol ));
                    if( pMatch )
                    {
                        m_aWMAtoms[ pMatch->nProtocol ] = pAtoms[ i ];
                        if( pMatch->nProtocol == WIN_LAYER )
                            m_bEnableAlwaysOnTopWorks = true;
                    }
                    if( strncmp( "_ICEWM_TRAY", pAtomNames[i], 11 ) == 0 )
                    {
                        m_aWMName = "IceWM";
                        m_nWinGravity = NorthWestGravity;
                        m_nInitWinGravity = NorthWestGravity;
                    }
#if OSL_DEBUG_LEVEL > 1
                    SAL_INFO("vcl.app"" "
                            << pAtomNames[i]
                            << (((pMatch) && (pMatch->nProtocol != -1)) ?
                                "" : " (unsupported)"));
#endif
                    XFree( pAtomNames[i] );
                }
            }
            XFree( pProperty );
            pProperty = nullptr;
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }

        // get number of desktops
        if( m_aWMAtoms[ WIN_WORKSPACE_COUNT ]
            && XGetWindowProperty( m_pDisplay,
                                   m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                   m_aWMAtoms[ WIN_WORKSPACE_COUNT ],
                                   0, 1,
                                   False,
                                   XA_CARDINAL,
                                   &aRealType,
                                   &nFormat,
                                   &nItems,
                                   &nBytesLeft,
                                   &pProperty ) == 0
            && pProperty
            )
        {
            m_nDesktops = *reinterpret_cast<long*>(pProperty);
            XFree( pProperty );
            pProperty = nullptr;
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
    }
    else if( pProperty )
    {
        XFree( pProperty );
        pProperty = nullptr;
    }
}

/*
 *  getNetWmName()
 */

bool WMAdaptor::getNetWmName()
{
    Atom                aRealType   = None;
    int                 nFormat     = 8;
    unsigned long       nItems      = 0;
    unsigned long       nBytesLeft  = 0;
    unsigned char*  pProperty   = nullptr;
    bool                bNetWM      = false;

    if( m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ] && m_aWMAtoms[ NET_WM_NAME ] )
    {
        if( XGetWindowProperty( m_pDisplay,
                                m_pSalDisplay->GetRootWindow( m_pSalDisplay->GetDefaultXScreen() ),
                                m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
                                0, 1,
                                False,
                                XA_WINDOW,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty ) == 0
            && aRealType == XA_WINDOW
            && nFormat == 32
            && nItems != 0
            )
        {
            ::Window aWMChild = *reinterpret_cast< ::Window* >(pProperty);
            XFree( pProperty );
            pProperty = nullptr;
            GetGenericUnixSalData()->ErrorTrapPush();
            if( XGetWindowProperty( m_pDisplay,
                                    aWMChild,
                                    m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ],
                                    0, 1,
                                    False,
                                    XA_WINDOW,
                                    &aRealType,
                                    &nFormat,
                                    &nItems,
                                    &nBytesLeft,
                                    &pProperty ) == 0
                && aRealType == XA_WINDOW
                && nFormat == 32
                && nItems != 0 )
            {
                    if ( ! GetGenericUnixSalData()->ErrorTrapPop( false ) )
                    {
                        GetGenericUnixSalData()->ErrorTrapPush();
                        ::Window aCheckWindow =  *reinterpret_cast< ::Window* >(pProperty);
                        XFree( pProperty );
                        pProperty = nullptr;
                        if( aCheckWindow == aWMChild )
                        {
                            bNetWM = true;
                            // get name of WM
                            m_aWMAtoms[ UTF8_STRING ] = XInternAtom( m_pDisplay, "UTF8_STRING"False );
                            if( XGetWindowProperty( m_pDisplay,
                                                    aWMChild,
                                                    m_aWMAtoms[ NET_WM_NAME ],
                                                    0, 256,
                                                    False,
                                                    AnyPropertyType, /* m_aWMAtoms[ UTF8_STRING ],*/
                                                    &aRealType,
                                                    &nFormat,
                                                    &nItems,
                                                    &nBytesLeft,
                                                    &pProperty ) == 0
                                && nItems != 0
                                )
                            {
                                if (aRealType == m_aWMAtoms[ UTF8_STRING ])
                                    m_aWMName = OUString( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_UTF8 );
                                else if (aRealType == XA_STRING)
                                    m_aWMName = OUString( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_ISO_8859_1 );

                                XFree( pProperty );
                                pProperty = nullptr;
                            }
                            else if( pProperty )
                            {
                                XFree( pProperty );
                                pProperty = nullptr;
                            }

                            // if this is metacity, check for version to enable a legacy workaround
                            if( m_aWMName == "Metacity" )
                            {
                                int nVersionMajor = 0, nVersionMinor = 0;
                                Atom nVersionAtom = XInternAtom( m_pDisplay, "_METACITY_VERSION"True );
                                if( nVersionAtom )
                                {
                                    if( XGetWindowProperty( m_pDisplay,
                                                            aWMChild,
                                                            nVersionAtom,
                                                            0, 256,
                                                            False,
                                                            m_aWMAtoms[ UTF8_STRING ],
                                                            &aRealType,
                                                            &nFormat,
                                                            &nItems,
                                                            &nBytesLeft,
                                                            &pProperty ) == 0
                                        && nItems != 0
                                        )
                                    {
                                        OUString aMetaVersion( reinterpret_cast<char*>(pProperty), nItems, RTL_TEXTENCODING_UTF8 );
                                        sal_Int32 nIdx {0};
                                        nVersionMajor = o3tl::toInt32(o3tl::getToken(aMetaVersion, 0, '.', nIdx));
                                        nVersionMinor = o3tl::toInt32(o3tl::getToken(aMetaVersion, 0, '.', nIdx));
                                    }
                                    if( pProperty )
                                    {
                                        XFree( pProperty );
                                        pProperty = nullptr;
                                    }
                                }
                                if( nVersionMajor < 2 || (nVersionMajor == 2 && nVersionMinor < 12) )
                                    m_bLegacyPartialFullscreen = true;
                            }
                        }
                    }
                    else
                    {
                        if( pProperty )
                        {
                            XFree( pProperty );
                            pProperty = nullptr;
                        }
                        GetGenericUnixSalData()->ErrorTrapPush();
                    }
            }

            GetGenericUnixSalData()->ErrorTrapPop();
        }
        else if( pProperty )
        {
            XFree( pProperty );
            pProperty = nullptr;
        }
    }
    return bNetWM;
}

bool WMAdaptor::getWMshouldSwitchWorkspace() const
{
    if( ! m_bWMshouldSwitchWorkspaceInit )
    {
        WMAdaptor * pWMA = const_cast<WMAdaptor*>(this);

        pWMA->m_bWMshouldSwitchWorkspace = true;
        vcl::SettingsConfigItem* pItem = vcl::SettingsConfigItem::get();
        OUString aSetting( pItem->getValue( u"WM"_ustr,
                                                 u"ShouldSwitchWorkspace"_ustr ) );
        if( aSetting.isEmpty() )
        {
            if( m_aWMName == "awesome" )
            {
                pWMA->m_bWMshouldSwitchWorkspace = false;
            }
        }
        else
            pWMA->m_bWMshouldSwitchWorkspace = aSetting.toBoolean();
        pWMA->m_bWMshouldSwitchWorkspaceInit = true;
    }
    return m_bWMshouldSwitchWorkspace;
}

/*
 *  WMAdaptor::isValid()
 */

bool WMAdaptor::isValid() const
{
    return true;
}

/*
 *  NetWMAdaptor::isValid()
 */

bool NetWMAdaptor::isValid() const
{
    // some necessary sanity checks; there are WMs out there
    // which implement some of the WM hints spec without
    // real functionality
    return
        m_aWMAtoms[ NET_SUPPORTED ]
        && m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]
        && m_aWMAtoms[ NET_WM_NAME ]
        && m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ]
        && m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ]
        ;
}

/*
 *  GnomeWMAdaptor::isValid()
 */

bool GnomeWMAdaptor::isValid() const
{
    return m_bValid;
}

/*
 *  WMAdaptor::initAtoms
 */


void WMAdaptor::initAtoms()
{
    // get basic atoms
    for(const WMAdaptorProtocol & i : aAtomTab)
        m_aWMAtoms[ i.nProtocol ] = XInternAtom( m_pDisplay, i.pProtocol, False );
    m_aWMAtoms[ NET_SUPPORTING_WM_CHECK ]   = XInternAtom( m_pDisplay, "_NET_SUPPORTING_WM_CHECK"True );
    m_aWMAtoms[ NET_WM_NAME ]               = XInternAtom( m_pDisplay, "_NET_WM_NAME"True );
}

/*
 *  NetWMAdaptor::initAtoms
 */


void NetWMAdaptor::initAtoms()
{
    WMAdaptor::initAtoms();

    m_aWMAtoms[ NET_SUPPORTED ]             = XInternAtom( m_pDisplay, "_NET_SUPPORTED"True );
}

/*
 *  GnomeWMAdaptor::initAtoms
 */


void GnomeWMAdaptor::initAtoms()
{
    WMAdaptor::initAtoms();

    m_aWMAtoms[ WIN_PROTOCOLS ]             = XInternAtom( m_pDisplay, "_WIN_PROTOCOLS"True );
    m_aWMAtoms[ WIN_SUPPORTING_WM_CHECK ]   = XInternAtom( m_pDisplay, "_WIN_SUPPORTING_WM_CHECK"True );
}

/*
 *  WMAdaptor::setWMName
 *  sets WM_NAME
 *       WM_ICON_NAME
 */


void WMAdaptor::setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const
{
    OString aTitle(OUStringToOString(rWMName,
        osl_getThreadTextEncoding()));

    OString aWMLocale;
    rtl_Locale* pLocale = nullptr;
    osl_getProcessLocale( &pLocale );
    if( pLocale )
    {
        OUString aLocaleString(
            LanguageTag( *pLocale).getGlibcLocaleString( std::u16string_view()));
        aWMLocale = OUStringToOString( aLocaleString, RTL_TEXTENCODING_ISO_8859_1 );
    }
    else
    {
        static const char* pLang = getenv( "LANG" );
        aWMLocale = pLang ? pLang : "C";
    }

    char* pT = const_cast<char*>(aTitle.getStr());
    XTextProperty aProp = { nullptr, None, 0, 0 };
    XmbTextListToTextProperty( m_pDisplay,
                               &pT,
                               1,
                               XStdICCTextStyle,
                               &aProp );

    unsigned char const * pData = aProp.nitems ? aProp.value : reinterpret_cast<unsigned char const *>(aTitle.getStr());
    Atom nType = aProp.nitems ? aProp.encoding : XA_STRING;
    int nFormat = aProp.nitems ? aProp.format : 8;
    int nBytes = aProp.nitems ? aProp.nitems : aTitle.getLength();
    ::Window aShellWindow = pFrame->GetShellWindow();
    XChangeProperty( m_pDisplay,
                     aShellWindow,
                     XA_WM_NAME,
                     nType,
                     nFormat,
                     PropModeReplace,
                     pData,
                     nBytes );
    XChangeProperty( m_pDisplay,
                     aShellWindow,
                     XA_WM_ICON_NAME,
                     nType,
                     nFormat,
                     PropModeReplace,
                     pData,
                     nBytes );
    XChangeProperty( m_pDisplay,
                     aShellWindow,
                     m_aWMAtoms[ WM_LOCALE_NAME ],
                     XA_STRING,
                     8,
                     PropModeReplace,
                     reinterpret_cast<unsigned char const *>(aWMLocale.getStr()),
                     aWMLocale.getLength() );
    if (aProp.value != nullptr)
        XFree( aProp.value );
}

/*
 *  NetWMAdaptor::setWMName
 *  sets WM_NAME
 *       _NET_WM_NAME
 *       WM_ICON_NAME
 *       _NET_WM_ICON_NAME
 */

void NetWMAdaptor::setWMName( X11SalFrame* pFrame, const OUString& rWMName ) const
{
    WMAdaptor::setWMName( pFrame, rWMName );

    OString aTitle(OUStringToOString(rWMName, RTL_TEXTENCODING_UTF8));
    ::Window aShellWindow = pFrame->GetShellWindow();
    if( m_aWMAtoms[ NET_WM_NAME ] )
        XChangeProperty( m_pDisplay,
                         aShellWindow,
                         m_aWMAtoms[ NET_WM_NAME ],
                         m_aWMAtoms[ UTF8_STRING ],
                         8,
                         PropModeReplace,
                         reinterpret_cast<unsigned char const *>(aTitle.getStr()),
                         aTitle.getLength() );
    if( m_aWMAtoms[ NET_WM_ICON_NAME ] )
        XChangeProperty( m_pDisplay,
                         aShellWindow,
                         m_aWMAtoms[ NET_WM_ICON_NAME ],
                         m_aWMAtoms[ UTF8_STRING ],
                         8,
                         PropModeReplace,
                         reinterpret_cast<unsigned char const *>(aTitle.getStr()),
                         aTitle.getLength() );
}

/*
 *  NetWMAdaptor::setNetWMState
 *  sets _NET_WM_STATE
 */

void NetWMAdaptor::setNetWMState( X11SalFrame* pFrame ) const
{
    if( !(m_aWMAtoms[ NET_WM_STATE ]) )
        return;

    Atom aStateAtoms[ 10 ];
    int nStateAtoms = 0;

    // set NET_WM_STATE_MODAL
    if( pFrame->mbMaximizedVert
        && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] )
        aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
    if( pFrame->mbMaximizedHorz
        && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ] )
        aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
    if( pFrame->bAlwaysOnTop_ && m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ] )
        aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
    if( pFrame->mbFullScreen && m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ] )
        aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_FULLSCREEN ];
    if( pFrame->meWindowType == WMWindowType::Utility && m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ] )
        aStateAtoms[ nStateAtoms++ ] = m_aWMAtoms[ NET_WM_STATE_SKIP_TASKBAR ];

    if( nStateAtoms )
    {
        XChangeProperty( m_pDisplay,
                         pFrame->GetShellWindow(),
                         m_aWMAtoms[ NET_WM_STATE ],
                         XA_ATOM,
                         32,
                         PropModeReplace,
                         reinterpret_cast<unsigned char*>(aStateAtoms),
                         nStateAtoms
                         );
    }
    else
        XDeleteProperty( m_pDisplay,
                         pFrame->GetShellWindow(),
                         m_aWMAtoms[ NET_WM_STATE ] );
    if( !pFrame->mbMaximizedHorz
       || !pFrame->mbMaximizedVert
       || ( pFrame->nStyle_ & SalFrameStyleFlags::SIZEABLE ) )
        return;

    /*
     *  for maximizing use NorthWestGravity (including decoration)
     */

    XSizeHints  hints;
    tools::Long        supplied;
    bool bHint = false;
    if( XGetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints,
                           &supplied ) )
    {
        bHint = true;
        hints.flags |= PWinGravity;
        hints.win_gravity = NorthWestGravity;
        XSetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints );
        XSync( m_pDisplay, False );
    }

    // SetPosSize necessary to set width/height, min/max w/h
    sal_Int32 nCurrent = 0;
    /*
     *  get current desktop here if work areas have different size
     *  (does this happen on any platform ?)
     */

    if( ! m_bEqualWorkAreas )
    {
        nCurrent = getCurrentWorkArea();
        if( nCurrent < 0 )
            nCurrent = 0;
    }
    AbsoluteScreenPixelRectangle aPosSize = m_aWMWorkAreas[nCurrent];
    const SalFrameGeometry aGeom( pFrame->GetUnmirroredGeometry() );
    aPosSize = AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint( aPosSize.Left() + aGeom.leftDecoration(),
                                 aPosSize.Top()  + aGeom.topDecoration() ),
                          AbsoluteScreenPixelSize( aPosSize.GetWidth()
                                - aGeom.leftDecoration()
                                - aGeom.rightDecoration(),
                                aPosSize.GetHeight()
                                - aGeom.topDecoration()
                                - aGeom.bottomDecoration() )
                          );
    pFrame->SetPosSize( aPosSize );

    /*
     *  reset gravity hint to static gravity
     *  (this should not move window according to ICCCM)
     */

    if( bHint && pFrame->nShowState_ != X11ShowState::Unknown )
    {
        hints.win_gravity = StaticGravity;
        XSetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints );
    }
}

/*
 *  GnomeWMAdaptor::setNetWMState
 *  sets _WIN_STATE
 */

void GnomeWMAdaptor::setGnomeWMState( X11SalFrame* pFrame ) const
{
    if( !(m_aWMAtoms[ WIN_STATE ]) )
        return;

    sal_uInt32 nWinWMState = 0;

    if( pFrame->mbMaximizedVert )
        nWinWMState |= 1 << 2;
    if( pFrame->mbMaximizedHorz )
        nWinWMState |= 1 << 3;

    XChangeProperty( m_pDisplay,
                     pFrame->GetShellWindow(),
                     m_aWMAtoms[ WIN_STATE ],
                     XA_CARDINAL,
                     32,
                     PropModeReplace,
                     reinterpret_cast<unsigned char*>(&nWinWMState),
                     1
                     );
    if( !pFrame->mbMaximizedHorz
       || !pFrame->mbMaximizedVert
       || ( pFrame->nStyle_ & SalFrameStyleFlags::SIZEABLE ) )
        return;

    /*
     *  for maximizing use NorthWestGravity (including decoration)
     */

    XSizeHints  hints;
    tools::Long        supplied;
    bool bHint = false;
    if( XGetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints,
                           &supplied ) )
    {
        bHint = true;
        hints.flags |= PWinGravity;
        hints.win_gravity = NorthWestGravity;
        XSetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints );
        XSync( m_pDisplay, False );
    }

    // SetPosSize necessary to set width/height, min/max w/h
    sal_Int32 nCurrent = 0;
    /*
     *  get current desktop here if work areas have different size
     *  (does this happen on any platform ?)
     */

    if( ! m_bEqualWorkAreas )
    {
        nCurrent = getCurrentWorkArea();
        if( nCurrent < 0 )
            nCurrent = 0;
    }
    AbsoluteScreenPixelRectangle aPosSize = m_aWMWorkAreas[nCurrent];
    const SalFrameGeometry aGeom( pFrame->GetUnmirroredGeometry() );
    aPosSize = AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint( aPosSize.Left() + aGeom.leftDecoration(),
                                 aPosSize.Top()  + aGeom.topDecoration() ),
                          AbsoluteScreenPixelSize( aPosSize.GetWidth()
                                - aGeom.leftDecoration()
                                - aGeom.rightDecoration(),
                                aPosSize.GetHeight()
                                - aGeom.topDecoration()
                                - aGeom.bottomDecoration() )
                          );
    pFrame->SetPosSize( aPosSize );

    /*
     *  reset gravity hint to static gravity
     *  (this should not move window according to ICCCM)
     */

    if( bHint && pFrame->nShowState_ != X11ShowState::Unknown )
    {
        hints.win_gravity = StaticGravity;
        XSetWMNormalHints( m_pDisplay,
                           pFrame->GetShellWindow(),
                           &hints );
    }
}

/*
 *  WMAdaptor::setFrameDecoration
 *  sets _MOTIF_WM_HINTS
 *       WM_TRANSIENT_FOR
 */


void WMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eType, int nDecorationFlags, X11SalFrame* pReferenceFrame ) const
{
    pFrame->meWindowType        = eType;

    if( ! pFrame->mbFullScreen )
    {
        // set mwm hints
        struct _mwmhints {
            unsigned long flags, func, deco;
            tools::Long input_mode;
            unsigned long status;
        } aHint;

        aHint.flags = 15; /* flags for functions, decoration, input mode and status */
        aHint.deco = 0;
        aHint.func = 1 << 2;
        aHint.status = 0;
        aHint.input_mode = 0;

        // evaluate decoration flags
        if( nDecorationFlags & decoration_All )
        {
            aHint.deco = 1;
            aHint.func = 1;
        }
        else
        {
            if( nDecorationFlags & decoration_Title )
                aHint.deco |= 1 << 3;
            if( nDecorationFlags & decoration_Border )
                aHint.deco |= 1 << 1;
            if( nDecorationFlags & decoration_Resize )
            {
                aHint.deco |= 1 << 2;
                aHint.func |= 1 << 1;
            }
            if( nDecorationFlags & decoration_MinimizeBtn )
            {
                aHint.deco |= 1 << 5;
                aHint.func |= 1 << 3;
            }
            if( nDecorationFlags & decoration_MaximizeBtn )
            {
                aHint.deco |= 1 << 6;
                aHint.func |= 1 << 4;
            }
            if( nDecorationFlags & decoration_CloseBtn )
            {
                aHint.deco |= 1 << 4;
                aHint.func |= 1 << 5;
            }
        }

        // set the hint
        XChangeProperty( m_pDisplay,
                         pFrame->GetShellWindow(),
                         m_aWMAtoms[ MOTIF_WM_HINTS ],
                         m_aWMAtoms[ MOTIF_WM_HINTS ],
                         32,
                         PropModeReplace,
                         reinterpret_cast<unsigned char*>(&aHint),
                         5 );
    }

    // set transientFor hint
    /*  #91030# dtwm will not map a dialogue if the transient
     *  window is iconified. This is deemed undesirable because
     *  message boxes do not get mapped, so use the root as transient
     *  instead.
     */

    if( pReferenceFrame )
    {
        XSetTransientForHint( m_pDisplay,
                              pFrame->GetShellWindow(),
                              pReferenceFrame->bMapped_ ?
                              pReferenceFrame->GetShellWindow() :
                              m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() )
                              );
        if( ! pReferenceFrame->bMapped_ )
            pFrame->mbTransientForRoot = true;
    }
}

/*
 *  NetWMAdaptor::setFrameDecoration
 *  sets _MOTIF_WM_HINTS
 *       _NET_WM_WINDOW_TYPE
 *       _NET_WM_STATE
 *       WM_TRANSIENT_FOR
 */


void NetWMAdaptor::setFrameTypeAndDecoration( X11SalFrame* pFrame, WMWindowType eTypeint nDecorationFlags, X11SalFrame* pReferenceFrame ) const
{
    WMAdaptor::setFrameTypeAndDecoration( pFrame, eType, nDecorationFlags, pReferenceFrame );

    setNetWMState( pFrame );

    // set NET_WM_WINDOW_TYPE
    if( m_aWMAtoms[ NET_WM_WINDOW_TYPE ] )
    {
        Atom aWindowTypes[4];
        int nWindowTypes = 0;
        switch( eType )
        {
            case WMWindowType::Utility:
                aWindowTypes[nWindowTypes++] =
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] ?
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_UTILITY ] :
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
                break;
            case WMWindowType::ModelessDialogue:
                aWindowTypes[nWindowTypes++] =
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_DIALOG ];
                break;
            case WMWindowType::Splash:
                aWindowTypes[nWindowTypes++] =
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] ?
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_SPLASH ] :
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
                break;
            case WMWindowType::Toolbar:
                if( m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ] )
                    aWindowTypes[nWindowTypes++] = m_aWMAtoms[ KDE_NET_WM_WINDOW_TYPE_OVERRIDE ];
                aWindowTypes[nWindowTypes++] =
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] ?
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_TOOLBAR ] :
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
                break;
            case WMWindowType::Dock:
                aWindowTypes[nWindowTypes++] =
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] ?
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_DOCK ] :
                    m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL];
                break;
            default:
                aWindowTypes[nWindowTypes++] = m_aWMAtoms[ NET_WM_WINDOW_TYPE_NORMAL ];
                break;
        }
        XChangeProperty( m_pDisplay,
                         pFrame->GetShellWindow(),
                         m_aWMAtoms[ NET_WM_WINDOW_TYPE ],
                         XA_ATOM,
                         32,
                         PropModeReplace,
                         reinterpret_cast<unsigned char*>(aWindowTypes),
                         nWindowTypes );
    }
    if( ( eType == WMWindowType::ModelessDialogue )
        && ! pReferenceFrame )
    {
        XSetTransientForHint( m_pDisplay,
                              pFrame->GetShellWindow(),
                              m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ) );
        pFrame->mbTransientForRoot = true;
    }
}

/*
 *  WMAdaptor::maximizeFrame
 */


void WMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
{
    pFrame->mbMaximizedVert = bVertical;
    pFrame->mbMaximizedHorz = bHorizontal;

    const SalFrameGeometry aGeom( pFrame->GetUnmirroredGeometry() );

    // discard pending configure notifies for this frame
    XSync( m_pDisplay, False );
    XEvent aDiscard;
    while( XCheckTypedWindowEvent( m_pDisplay,
                                   pFrame->GetShellWindow(),
                                   ConfigureNotify,
                                   &aDiscard ) )
        ;
    while( XCheckTypedWindowEvent( m_pDisplay,
                                   pFrame->GetWindow(),
                                   ConfigureNotify,
                                   &aDiscard ) )
        ;

    if( bHorizontal || bVertical )
    {
        AbsoluteScreenPixelSize aScreenSize( m_pSalDisplay->GetScreenSize( pFrame->GetScreenNumber() ) );
        AbsoluteScreenPixelPoint aTL( aGeom.leftDecoration(), aGeom.topDecoration() );
        if( m_pSalDisplay->IsXinerama() )
        {
            AbsoluteScreenPixelPoint aMed( aTL.X() + aGeom.width()/2, aTL.Y() + aGeom.height()/2 );
            const std::vector< AbsoluteScreenPixelRectangle >& rScreens = m_pSalDisplay->GetXineramaScreens();
            for(const auto & rScreen : rScreens)
                if( rScreen.Contains( aMed ) )
                {
                    aTL += rScreen.TopLeft();
                    aScreenSize = rScreen.GetSize();
                    break;
                }
        }
        AbsoluteScreenPixelRectangle aTarget( aTL,
                           AbsoluteScreenPixelSize( aScreenSize.Width() - aGeom.leftDecoration() - aGeom.topDecoration(),
                                 aScreenSize.Height() - aGeom.topDecoration() - aGeom.bottomDecoration() )
                           );

        const AbsoluteScreenPixelRectangle aReferenceGeometry = !pFrame->maRestorePosSize.IsEmpty() ?
                                                    pFrame->maRestorePosSize : AbsoluteScreenPixelRectangle(aGeom.posSize());
        if( ! bHorizontal )
        {
            aTarget.SetSize({ aReferenceGeometry.GetWidth(), aTarget.GetHeight() });
            aTarget.SetLeft(aReferenceGeometry.Left());
        }
        else if( ! bVertical )
        {
            aTarget.SetSize({ aTarget.GetWidth(), aReferenceGeometry.GetHeight() });
            aTarget.SetTop(aReferenceGeometry.Top());
        }

        AbsoluteScreenPixelRectangle aRestore(aGeom.posSize());
        if( pFrame->bMapped_ )
        {
            XSetInputFocus( m_pDisplay,
                            pFrame->GetShellWindow(),
                            RevertToNone,
                            CurrentTime
                            );
        }

        if( pFrame->maRestorePosSize.IsEmpty() )
            pFrame->maRestorePosSize = aRestore;

        pFrame->SetPosSize( aTarget );
        pFrame->nWidth_     = aTarget.GetWidth();
        pFrame->nHeight_    = aTarget.GetHeight();
        XRaiseWindow( m_pDisplay,
                      pFrame->GetShellWindow()
                      );
        if( pFrame->GetStackingWindow() )
            XRaiseWindow( m_pDisplay,
                          pFrame->GetStackingWindow()
                          );

    }
    else
    {
        pFrame->SetPosSize( pFrame->maRestorePosSize );
        pFrame->maRestorePosSize = AbsoluteScreenPixelRectangle();
        pFrame->nWidth_             = aGeom.width();
        pFrame->nHeight_            = aGeom.height();
    }
}

/*
 *  NetWMAdaptor::maximizeFrame
 *  changes _NET_WM_STATE by sending a client message
 */


void NetWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical const
{
    pFrame->mbMaximizedVert = bVertical;
    pFrame->mbMaximizedHorz = bHorizontal;

    if( m_aWMAtoms[ NET_WM_STATE ]
        && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ]
        && m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ]
        && ( pFrame->nStyle_ & ~SalFrameStyleFlags::DEFAULT )
        )
    {
        if( pFrame->bMapped_ )
        {
            // window already mapped, send WM a message
            XEvent aEvent;
            aEvent.type                 = ClientMessage;
            aEvent.xclient.display      = m_pDisplay;
            aEvent.xclient.window       = pFrame->GetShellWindow();
            aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
            aEvent.xclient.format       = 32;
            aEvent.xclient.data.l[0]    = bHorizontal ? 1 : 0;
            aEvent.xclient.data.l[1]    = m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_HORZ ];
            aEvent.xclient.data.l[2]    = bHorizontal == bVertical ? m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ] : 0;
            aEvent.xclient.data.l[3]    = 0;
            aEvent.xclient.data.l[4]    = 0;
            XSendEvent( m_pDisplay,
                        m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
                        False,
                        SubstructureNotifyMask | SubstructureRedirectMask,
                        &aEvent
                        );
            if( bHorizontal != bVertical )
            {
                aEvent.xclient.data.l[0]= bVertical ? 1 : 0;
                aEvent.xclient.data.l[1]= m_aWMAtoms[ NET_WM_STATE_MAXIMIZED_VERT ];
                aEvent.xclient.data.l[2]= 0;
                XSendEvent( m_pDisplay,
                            m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
                            False,
                            SubstructureNotifyMask | SubstructureRedirectMask,
                            &aEvent
                            );
            }
        }
        else
        {
            // window not mapped yet, set _NET_WM_STATE directly
            setNetWMState( pFrame );
        }
        if( !bHorizontal && !bVertical )
            pFrame->maRestorePosSize = AbsoluteScreenPixelRectangle();
        else if( pFrame->maRestorePosSize.IsEmpty() )
        {
            const SalFrameGeometry aGeom( pFrame->GetUnmirroredGeometry() );
            pFrame->maRestorePosSize =
                AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint( aGeom.x(), aGeom.y() ), AbsoluteScreenPixelSize( aGeom.width(), aGeom.height() ) );
        }
    }
    else
        WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
}

/*
 *  GnomeWMAdaptor::maximizeFrame
 *  changes _WIN_STATE by sending a client message
 */


void GnomeWMAdaptor::maximizeFrame( X11SalFrame* pFrame, bool bHorizontal, bool bVertical ) const
{
    pFrame->mbMaximizedVert = bVertical;
    pFrame->mbMaximizedHorz = bHorizontal;

    if( m_aWMAtoms[ WIN_STATE ]
        && ( pFrame->nStyle_ & ~SalFrameStyleFlags::DEFAULT )
        )
    {
        if( pFrame->bMapped_ )
        {
             // window already mapped, send WM a message
            XEvent aEvent;
            aEvent.type                 = ClientMessage;
            aEvent.xclient.display      = m_pDisplay;
            aEvent.xclient.window       = pFrame->GetShellWindow();
            aEvent.xclient.message_type = m_aWMAtoms[ WIN_STATE ];
            aEvent.xclient.format       = 32;
            aEvent.xclient.data.l[0]    = (1<<2)|(1<<3);
            aEvent.xclient.data.l[1]    =
                (bVertical ? (1<<2) : 0)
                | (bHorizontal ? (1<<3) : 0);
            aEvent.xclient.data.l[2]    = 0;
            aEvent.xclient.data.l[3]    = 0;
            aEvent.xclient.data.l[4]    = 0;
            XSendEvent( m_pDisplay,
                        m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
                        False,
                        SubstructureNotifyMask,
                        &aEvent
                        );
        }
        else
            // window not mapped yet, set _WIN_STATE directly
            setGnomeWMState( pFrame );

        if( !bHorizontal && !bVertical )
            pFrame->maRestorePosSize = AbsoluteScreenPixelRectangle();
        else if( pFrame->maRestorePosSize.IsEmpty() )
        {
            const SalFrameGeometry aGeom( pFrame->GetUnmirroredGeometry() );
            pFrame->maRestorePosSize =
                AbsoluteScreenPixelRectangle( AbsoluteScreenPixelPoint( aGeom.x(), aGeom.y() ), AbsoluteScreenPixelSize( aGeom.width(), aGeom.height() ) );
        }
    }
    else
        WMAdaptor::maximizeFrame( pFrame, bHorizontal, bVertical );
}

/*
 *  WMAdaptor::enableAlwaysOnTop
 */

void WMAdaptor::enableAlwaysOnTop( X11SalFrame*, bool /*bEnable*/ ) const
{
}

/*
 *  NetWMAdaptor::enableAlwaysOnTop
 */

void NetWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
{
    pFrame->bAlwaysOnTop_ = bEnable;
    if( !(m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ]) )
        return;

    if( pFrame->bMapped_ )
    {
        // window already mapped, send WM a message
        XEvent aEvent;
        aEvent.type                 = ClientMessage;
        aEvent.xclient.display      = m_pDisplay;
        aEvent.xclient.window       = pFrame->GetShellWindow();
        aEvent.xclient.message_type = m_aWMAtoms[ NET_WM_STATE ];
        aEvent.xclient.format       = 32;
        aEvent.xclient.data.l[0]    = bEnable ? 1 : 0;
        aEvent.xclient.data.l[1]    = m_aWMAtoms[ NET_WM_STATE_STAYS_ON_TOP ];
        aEvent.xclient.data.l[2]    = 0;
        aEvent.xclient.data.l[3]    = 0;
        aEvent.xclient.data.l[4]    = 0;
        XSendEvent( m_pDisplay,
                    m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
                    False,
                    SubstructureNotifyMask | SubstructureRedirectMask,
                    &aEvent
                    );
    }
    else
        setNetWMState( pFrame );
}

/*
 *  GnomeWMAdaptor::enableAlwaysOnTop
 */

void GnomeWMAdaptor::enableAlwaysOnTop( X11SalFrame* pFrame, bool bEnable ) const
{
    pFrame->bAlwaysOnTop_ = bEnable;
    if( !(m_aWMAtoms[ WIN_LAYER ]) )
        return;

    if( pFrame->bMapped_ )
    {
        // window already mapped, send WM a message
        XEvent aEvent;
        aEvent.type                 = ClientMessage;
        aEvent.xclient.display      = m_pDisplay;
        aEvent.xclient.window       = pFrame->GetShellWindow();
        aEvent.xclient.message_type = m_aWMAtoms[ WIN_LAYER ];
        aEvent.xclient.format       = 32;
        aEvent.xclient.data.l[0]    = bEnable ? 6 : 4;
        aEvent.xclient.data.l[1]    = 0;
        aEvent.xclient.data.l[2]    = 0;
        aEvent.xclient.data.l[3]    = 0;
        aEvent.xclient.data.l[4]    = 0;
        XSendEvent( m_pDisplay,
                    m_pSalDisplay->GetRootWindow( pFrame->GetScreenNumber() ),
                    False,
                    SubstructureNotifyMask | SubstructureRedirectMask,
                    &aEvent
                    );
    }
    else
    {
        sal_uInt32 nNewLayer = bEnable ? 6 : 4;
        XChangeProperty( m_pDisplay,
                         pFrame->GetShellWindow(),
                         m_aWMAtoms[ WIN_LAYER ],
                         XA_CARDINAL,
                         32,
                         PropModeReplace,
                         reinterpret_cast<unsigned char*>(&nNewLayer),
                         1
                         );
    }
}

/*
 *  WMAdaptor::changeReferenceFrame
 */

void WMAdaptor::changeReferenceFrame( X11SalFrame* pFrame, X11SalFrame const * pReferenceFrame ) const
{
    if(  ( pFrame->nStyle_ & SalFrameStyleFlags::PLUG )
        || pFrame->IsOverrideRedirect()
        || pFrame->IsFloatGrabWindow()
        )
        return;

    ::Window aTransient = pFrame->pDisplay_->GetRootWindow( pFrame->GetScreenNumber() );
    pFrame->mbTransientForRoot = true;
    if( pReferenceFrame )
    {
        aTransient = pReferenceFrame->GetShellWindow();
        pFrame->mbTransientForRoot = false;
    }
    XSetTransientForHint( m_pDisplay,
                          pFrame->GetShellWindow(),
                          aTransient );
}

/*
 *  WMAdaptor::handlePropertyNotify
 */

int WMAdaptor::handlePropertyNotify( X11SalFrame*, XPropertyEvent* ) const
{
    return 0;
}

/*
 *  NetWMAdaptor::handlePropertyNotify
 */

int NetWMAdaptor::handlePropertyNotify( X11SalFrame* pFrame, XPropertyEvent* pEvent ) const
{
    int nHandled = 1;
    if( pEvent->atom == m_aWMAtoms[ NET_WM_STATE ] )
    {
        pFrame->mbMaximizedHorz = pFrame->mbMaximizedVert = false;

        if( pEvent->state == PropertyNewValue )
        {
            Atom nType, *pStates;
            int nFormat;
            unsigned long nItems, nBytesLeft;
            unsigned char* pData = nullptr;
            tools::Long nOffset = 0;
            do
            {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.23 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.