471 lines
12 KiB
C
471 lines
12 KiB
C
/*
|
||
* CDE - Common Desktop Environment
|
||
*
|
||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||
*
|
||
* These libraries and programs are free software; you can
|
||
* redistribute them and/or modify them under the terms of the GNU
|
||
* Lesser General Public License as published by the Free Software
|
||
* Foundation; either version 2 of the License, or (at your option)
|
||
* any later version.
|
||
*
|
||
* These libraries and programs are distributed in the hope that
|
||
* they 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 for more
|
||
* details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with these libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/*
|
||
* (c) Copyright 1989 Sun Microsystems, Inc.
|
||
* (c) Copyright 1993 HEWLETT-PACKARD COMPANY
|
||
* ALL RIGHTS RESERVED
|
||
*/
|
||
|
||
/*
|
||
* Included Files:
|
||
*/
|
||
#include <stdlib.h>
|
||
#include "WmGlobal.h"
|
||
#include "WmOL.h"
|
||
#include "WmProperty.h"
|
||
#include <Xm/AtomMgr.h>
|
||
|
||
#define ValidPropertyList(pcd) ((pcd)->paInitialProperties != NULL)
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* InitOLCompat ()
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Interns the atoms necessary for OL protocols.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
*
|
||
* Outputs:
|
||
* --------
|
||
*
|
||
*************************************<->***********************************/
|
||
void
|
||
InitOLCompat(void)
|
||
{
|
||
wmGD.xa_OL_WIN_ATTR =
|
||
XmInternAtom (DISPLAY, OL_WIN_ATTR, False);
|
||
wmGD.xa_OL_DECOR_RESIZE =
|
||
XmInternAtom (DISPLAY, OL_DECOR_RESIZE, False);
|
||
wmGD.xa_OL_DECOR_HEADER =
|
||
XmInternAtom (DISPLAY, OL_DECOR_HEADER, False);
|
||
wmGD.xa_OL_DECOR_CLOSE =
|
||
XmInternAtom (DISPLAY, OL_DECOR_CLOSE, False);
|
||
wmGD.xa_OL_DECOR_PIN =
|
||
XmInternAtom (DISPLAY, OL_DECOR_PIN, False);
|
||
wmGD.xa_OL_DECOR_ADD =
|
||
XmInternAtom (DISPLAY, OL_DECOR_ADD, False);
|
||
wmGD.xa_OL_DECOR_DEL =
|
||
XmInternAtom (DISPLAY, OL_DECOR_DEL, False);
|
||
wmGD.xa_OL_WT_BASE =
|
||
XmInternAtom (DISPLAY, OL_WT_BASE, False);
|
||
wmGD.xa_OL_WT_COMMAND =
|
||
XmInternAtom (DISPLAY, OL_WT_CMD, False);
|
||
wmGD.xa_OL_WT_HELP =
|
||
XmInternAtom (DISPLAY, OL_WT_HELP, False);
|
||
wmGD.xa_OL_WT_NOTICE =
|
||
XmInternAtom (DISPLAY, OL_WT_NOTICE, False);
|
||
wmGD.xa_OL_WT_OTHER =
|
||
XmInternAtom (DISPLAY, OL_WT_OTHER, False);
|
||
wmGD.xa_OL_PIN_IN =
|
||
XmInternAtom (DISPLAY, OL_PIN_IN, False);
|
||
wmGD.xa_OL_PIN_OUT =
|
||
XmInternAtom (DISPLAY, OL_PIN_OUT, False);
|
||
wmGD.xa_OL_MENU_LIMITED =
|
||
XmInternAtom (DISPLAY, OL_MENU_LIMITED, False);
|
||
wmGD.xa_OL_MENU_FULL =
|
||
XmInternAtom (DISPLAY, OL_MENU_FULL, False);
|
||
|
||
} /* END OF FUNCTION InitOLCompat */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* HasOpenLookHints (pCD)
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Returns True if this client has OpenLook hints on it.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = pointer to client data
|
||
*
|
||
* Outputs:
|
||
* --------
|
||
* Returns True if client has the _OL_WIN_ATTR property on it.
|
||
*
|
||
*************************************<->***********************************/
|
||
Boolean
|
||
HasOpenLookHints(
|
||
ClientData *pCD )
|
||
{
|
||
Boolean rval = False;
|
||
OLWinAttr *property = NULL;
|
||
|
||
if (ValidPropertyList (pCD) &&
|
||
HasProperty(pCD, wmGD.xa_OL_WIN_ATTR))
|
||
{
|
||
rval = True;
|
||
}
|
||
else if ((property=GetOLWinAttr (pCD)) != NULL)
|
||
{
|
||
XFree ((char *) property);
|
||
rval = True;
|
||
}
|
||
|
||
return (rval);
|
||
|
||
} /* END OF FUNCTION HasOpenLookHints */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* GetOLWinAttr (pCD)
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Fetches the OLWinAttr property off of the client
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = pointer to client data
|
||
*
|
||
* Outputs:
|
||
* --------
|
||
* Returns a pointer to the OLWinAttr property if found and valid.
|
||
* (Returned data should be freed with XFree())
|
||
* Returns NULL pointer otherwise.
|
||
*
|
||
*************************************<->***********************************/
|
||
OLWinAttr *
|
||
GetOLWinAttr(
|
||
ClientData *pCD )
|
||
{
|
||
Boolean rval = False;
|
||
OLWinAttr *property = NULL;
|
||
OLWinAttr *prop_new;
|
||
Atom actual_type;
|
||
int actual_format;
|
||
unsigned long nitems;
|
||
unsigned long leftover;
|
||
int ret_val;
|
||
|
||
ret_val = XGetWindowProperty (DISPLAY, pCD->client, wmGD.xa_OL_WIN_ATTR,
|
||
0L, ENTIRE_CONTENTS,
|
||
False, wmGD.xa_OL_WIN_ATTR,
|
||
&actual_type, &actual_format,
|
||
&nitems, &leftover, (unsigned char **)&property);
|
||
|
||
if (ret_val != Success)
|
||
{
|
||
property = NULL;
|
||
}
|
||
else if ((actual_format != 32) ||
|
||
(actual_type != wmGD.xa_OL_WIN_ATTR))
|
||
{
|
||
if (property)
|
||
XFree((char *)property);
|
||
property = NULL;
|
||
}
|
||
|
||
if (property && (nitems == OLDOLWINATTRLENGTH))
|
||
{
|
||
/* Old size, convert to new size */
|
||
/*
|
||
* !!! Should use XAlloc() here, but Xlib doesn't
|
||
* define an inverse function of XFree(). !!!
|
||
*/
|
||
prop_new = (OLWinAttr *) malloc (sizeof(OLWinAttr));
|
||
|
||
prop_new->flags = WA_WINTYPE | WA_MENUTYPE | WA_PINSTATE;
|
||
prop_new->win_type = ((old_OLWinAttr *)property)->win_type;
|
||
prop_new->menu_type = ((old_OLWinAttr *)property)->menu_type;
|
||
prop_new->pin_initial_state =
|
||
((old_OLWinAttr *)property)->pin_initial_state;
|
||
|
||
XFree ((char *) property);
|
||
property = prop_new;
|
||
}
|
||
|
||
/* convert pin state for old clients */
|
||
if (property && (property->flags & WA_PINSTATE))
|
||
{
|
||
if (property->pin_initial_state == wmGD.xa_OL_PIN_IN)
|
||
{
|
||
property->pin_initial_state = PIN_IN;
|
||
}
|
||
else if (property->pin_initial_state == wmGD.xa_OL_PIN_OUT)
|
||
{
|
||
property->pin_initial_state = PIN_OUT;
|
||
}
|
||
}
|
||
|
||
return (property);
|
||
|
||
} /* END OF FUNCTION GetOLWinAttr */
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* GetOLDecorFlags (pCD, property, pDecor)
|
||
*
|
||
* Description:
|
||
* -----------
|
||
* Fetches the _OL_DECOR_ADD or _OL_DECOR_DEL property off of the
|
||
* client and returns OL flavored decor flags.
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = pointer to client data
|
||
* property = property to fetch
|
||
* pDecor = pointer to OL decor flags word
|
||
*
|
||
* Outputs:
|
||
* --------
|
||
* Return = True if property found, False otherwise
|
||
* *pDecor = OL decor flags if valid property found,
|
||
* undefined if property not found.
|
||
*
|
||
*************************************<->***********************************/
|
||
Boolean
|
||
GetOLDecorFlags(
|
||
ClientData *pCD,
|
||
Atom property,
|
||
unsigned long *pDecor)
|
||
{
|
||
int status, i;
|
||
Boolean rval;
|
||
Atom actual_type;
|
||
int actual_format;
|
||
unsigned long nitems;
|
||
unsigned long leftover;
|
||
Atom *pAtoms = NULL;
|
||
|
||
status = XGetWindowProperty (DISPLAY, pCD->client, property,
|
||
0L, ENTIRE_CONTENTS,
|
||
False, XA_ATOM,
|
||
&actual_type, &actual_format,
|
||
&nitems, &leftover, (unsigned char **)&pAtoms);
|
||
|
||
if ((status != Success) ||
|
||
!pAtoms ||
|
||
(nitems == 0) ||
|
||
(actual_type != XA_ATOM) ||
|
||
(actual_format != 32))
|
||
{
|
||
if (pAtoms)
|
||
XFree((char *)pAtoms);
|
||
rval = False;
|
||
}
|
||
else
|
||
{
|
||
*pDecor = 0;
|
||
|
||
/*
|
||
* We only look for the ones we might be interested in.
|
||
* Several OL decoration types are ignored.
|
||
*/
|
||
for (i = 0; i < nitems; i++) {
|
||
if (pAtoms[i] == wmGD.xa_OL_DECOR_RESIZE)
|
||
*pDecor |= OLDecorResizable;
|
||
else if (pAtoms[i] == wmGD.xa_OL_DECOR_HEADER)
|
||
*pDecor |= OLDecorHeader;
|
||
else if (pAtoms[i] == wmGD.xa_OL_DECOR_CLOSE)
|
||
*pDecor |= OLDecorCloseButton;
|
||
else if (pAtoms[i] == wmGD.xa_OL_DECOR_PIN)
|
||
*pDecor |= OLDecorPushPin;
|
||
}
|
||
|
||
XFree((char *)pAtoms);
|
||
rval = True;
|
||
|
||
}
|
||
return (rval);
|
||
|
||
} /* END OF FUNCTION GetOLDecorFlags */
|
||
|
||
|
||
|
||
/*************************************<->*************************************
|
||
*
|
||
* ProcessOLDecoration (pCD)
|
||
*
|
||
* Description:
|
||
* -----------
|
||
*
|
||
* Inputs:
|
||
* ------
|
||
* pCD = pointer to client data
|
||
*
|
||
* Outputs:
|
||
* --------
|
||
* pCD = possibly modified with new decoration info
|
||
*
|
||
*************************************<->***********************************/
|
||
void
|
||
ProcessOLDecoration(
|
||
ClientData *pCD)
|
||
{
|
||
OLWinAttr * pOLWinAttr;
|
||
unsigned long OLdecor;
|
||
long decorMask;
|
||
|
||
if (HasOpenLookHints (pCD) &&
|
||
((pOLWinAttr = GetOLWinAttr (pCD)) != NULL))
|
||
{
|
||
/*
|
||
* This window already has some decoration applied to
|
||
* it based on its ICCCM type (transient or not).
|
||
* Use the OL hints to construct a mask to further
|
||
* modify these decorations.
|
||
*/
|
||
if ((pOLWinAttr->flags & WA_WINTYPE) == 0)
|
||
{
|
||
/*
|
||
* Window type not specified, assume all decorations
|
||
*/
|
||
decorMask = WM_DECOR_ALL;
|
||
}
|
||
else if (pOLWinAttr->win_type == wmGD.xa_OL_WT_BASE)
|
||
{
|
||
/*
|
||
* Base windows can have all decorations
|
||
*/
|
||
decorMask = WM_DECOR_ALL;
|
||
}
|
||
else if (pOLWinAttr->win_type == wmGD.xa_OL_WT_COMMAND)
|
||
{
|
||
/*
|
||
* Command windows have titles, pins (close button), and
|
||
* resize handles.
|
||
*/
|
||
decorMask = WM_DECOR_TITLE | WM_DECOR_SYSTEM | WM_DECOR_RESIZEH;
|
||
}
|
||
else if (pOLWinAttr->win_type == wmGD.xa_OL_WT_HELP)
|
||
{
|
||
/*
|
||
* Help windows have titles and pins (close button).
|
||
* No resize, but give it a border to look nicer.
|
||
*/
|
||
decorMask = (WM_DECOR_TITLE | WM_DECOR_SYSTEM | WM_DECOR_BORDER);
|
||
}
|
||
else if ((pOLWinAttr->win_type == wmGD.xa_OL_WT_NOTICE) &&
|
||
(pOLWinAttr->win_type == wmGD.xa_OL_WT_OTHER))
|
||
{
|
||
decorMask = WM_DECOR_NONE;
|
||
}
|
||
else
|
||
{
|
||
decorMask = WM_DECOR_ALL;
|
||
}
|
||
|
||
if (GetOLDecorAdd(pCD,&OLdecor))
|
||
{
|
||
if (OLdecor & OLDecorResizable)
|
||
{
|
||
decorMask |= WM_DECOR_RESIZEH;
|
||
}
|
||
if (OLdecor & OLDecorHeader)
|
||
{
|
||
decorMask |= WM_DECOR_TITLE;
|
||
}
|
||
if (OLdecor & OLDecorCloseButton)
|
||
{
|
||
/* OL "close" is same as "Motif" minimize */
|
||
decorMask |= MWM_DECOR_MINIMIZE;
|
||
}
|
||
if (OLdecor & OLDecorPushPin)
|
||
{
|
||
/*
|
||
* windows with pins can't be minimized
|
||
*/
|
||
decorMask &= ~MWM_DECOR_MINIMIZE;
|
||
decorMask |= MWM_DECOR_TITLE | MWM_DECOR_MENU;
|
||
}
|
||
}
|
||
|
||
if (GetOLDecorDel(pCD,&OLdecor))
|
||
{
|
||
if (OLdecor & OLDecorResizable)
|
||
{
|
||
decorMask &= ~MWM_DECOR_RESIZEH;
|
||
}
|
||
if (OLdecor & OLDecorHeader)
|
||
{
|
||
decorMask &= ~WM_DECOR_TITLEBAR;
|
||
}
|
||
if (OLdecor & OLDecorCloseButton)
|
||
{
|
||
/* OL "close" is same as "Motif" minimize */
|
||
decorMask &= ~MWM_DECOR_MINIMIZE;
|
||
}
|
||
|
||
/* push pin is ignored here */
|
||
|
||
}
|
||
|
||
/*
|
||
* If the window has a push pin or a limited menu,
|
||
* then consider it very similar to a secondary window.
|
||
*/
|
||
if (((pOLWinAttr->flags & WA_PINSTATE) &&
|
||
(pOLWinAttr->pin_initial_state == PIN_IN)) ||
|
||
((pOLWinAttr->flags & WA_MENUTYPE) &&
|
||
(pOLWinAttr->menu_type == wmGD.xa_OL_MENU_LIMITED)))
|
||
{
|
||
decorMask &= ~(MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE);
|
||
pCD->bPseudoTransient = True;
|
||
pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
|
||
}
|
||
|
||
/*
|
||
* Reduce decoration on this window according to OL hints
|
||
*/
|
||
pCD->clientDecoration &= decorMask;
|
||
|
||
/*
|
||
* Reduce client functions if necessary.
|
||
*/
|
||
if (!(decorMask & MWM_DECOR_MINIMIZE))
|
||
{
|
||
pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
|
||
}
|
||
if (!(decorMask & MWM_DECOR_MAXIMIZE))
|
||
{
|
||
pCD->clientFunctions &= ~MWM_FUNC_MAXIMIZE;
|
||
}
|
||
if (!(decorMask & MWM_DECOR_RESIZEH))
|
||
{
|
||
pCD->clientFunctions &= ~MWM_FUNC_RESIZE;
|
||
}
|
||
|
||
/*
|
||
* Set the clients secondariesOnTop value to false to allow
|
||
* open look transient behaviour (transients below primary).
|
||
*/
|
||
pCD->secondariesOnTop = False;
|
||
|
||
if (pOLWinAttr)
|
||
XFree((char *)pOLWinAttr);
|
||
}
|
||
|
||
} /* END OF FUNCTION ProcessOLDecoration */
|
||
|