/*
* Motif
*
* Copyright (c) 1987-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 librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* Motif Release 1.2.1
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$XConsortium: WmWinState.c /main/6 1996/06/20 09:39:39 rswiston $"
#endif
#endif
/*
* (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
/*
* Included Files:
*/
#include "WmGlobal.h"
#include "WmICCC.h"
#include "WmProtocol.h"
/*
* include extern functions
*/
#include "WmCDecor.h"
#include "WmFunction.h"
#include "WmIDecor.h"
#include "WmIPlace.h"
#include "WmIconBox.h"
#include "WmKeyFocus.h"
#ifdef PANELIST
#include "WmPanelP.h" /* for typedef in WmManage.h */
#endif /* PANELIST */
#include "WmManage.h"
#include "WmProperty.h"
#include "WmWinInfo.h"
#include "WmWinList.h"
#ifdef WSM
#include "WmWrkspace.h"
#endif /* WSM */
/*
* Function Declarations:
*/
#include "WmWinState.h"
#ifdef PANELIST
static void SlideWindowOut (ClientData *pCD);
#endif /* PANELIST */
static void UnmapClients (ClientData *pCD, unsigned int event_mask);
static void SetupWindowStateWithEventMask (ClientData *pCD, int newState, Time setTime, unsigned int event_mask);
/*
* Global Variables:
*/
extern int firstTime;
/******************************<->*************************************
*
* SetClientState (pCD, newState, setTime)
*
*
* Description:
* -----------
* This function is used to change the state of a client window (between
* withdrawn, normal, minimized, maximized).
*
*
* Inputs:
* ------
* pCD = This is a pointer to the window data for the window that
* is to have its state changed. The fields that are used
* are clientState, ...
*
* newState = This is the state that the client window is to be changed to.
*
* setTime = timestamp for state setting operations
*
*
* Outputs:
* -------
* pCD.clientState = new client state
*
******************************<->***********************************/
void SetClientState (ClientData *pCD, int newState, Time setTime)
{
SetClientStateWithEventMask(pCD, newState, setTime, (unsigned int)0);
} /* END OF FUNCTION SetClientState */
void SetClientStateWithEventMask (ClientData *pCD, int newState, Time setTime, unsigned int event_mask)
{
ClientData *pcdLeader;
int currentState;
WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
#ifdef WSM
Boolean notShowing = (newState & UNSEEN_STATE);
#endif /* WSM */
currentState = pCD->clientState;
if (currentState == newState)
{
/* no change in state */
return;
}
/*
* Undo the old state and setup the new state. If this is a transient
* window then insure that it is put in a state that is compatible
* with its transient leader (e.g., it cannot be minimized separately).
*/
pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
#ifdef WSM
SetClientWsIndex (pCD);
#endif /* WSM */
if (pCD->transientLeader)
{
if ((pcdLeader->clientState == MINIMIZED_STATE) &&
(newState != WITHDRAWN_STATE))
{
newState = MINIMIZED_STATE;
#ifdef WSM
if (notShowing)
{
newState |= UNSEEN_STATE;
}
#endif /* WSM */
}
else if ((newState == MINIMIZED_STATE) &&
(pcdLeader->clientState != MINIMIZED_STATE))
{
if (currentState == WITHDRAWN_STATE)
{
newState = NORMAL_STATE;
#ifdef WSM
if (notShowing)
{
newState |= UNSEEN_STATE;
}
#endif /* WSM */
}
else
{
newState = currentState;
#ifdef WSM
if (notShowing)
{
newState |= UNSEEN_STATE;
}
#endif /* WSM */
}
}
if (newState == currentState)
{
return;
}
}
switch (newState)
{
#ifdef WSM
case UNSEEN_STATE | WITHDRAWN_STATE:
#else
case WITHDRAWN_STATE:
#endif /* WSM */
{
/*
* Free window manager resources (frame and icon). The
* WM_STATE property is set in WithdrawWindow.
*/
UnManageWindow (pCD);
break;
}
case NORMAL_STATE:
case MAXIMIZED_STATE:
{
SetupWindowStateWithEventMask (pCD, newState, setTime, event_mask);
#ifdef WSM
XMapWindow (DISPLAY, pCD->client);
XMapWindow (DISPLAY, pCD->clientFrameWin);
#if defined(PANELIST)
WmStopWaiting(); /* in WmIPC.c */
#endif /* PANELIST */
#endif /* WSM */
break;
}
case MINIMIZED_STATE:
{
Boolean clientHasFocus;
/*
* Transient windows are minimized with the rest of the transient
* tree, including the transient leader.
*/
if ((pCD->clientState == NORMAL_STATE) ||
(pCD->clientState == MAXIMIZED_STATE))
{
if ((wmGD.keyboardFocus == pCD) ||
(pCD->transientChildren && wmGD.keyboardFocus &&
(pCD == FindTransientTreeLeader (wmGD.keyboardFocus))))
{
clientHasFocus = True;
}
else
{
clientHasFocus = False;
}
if (clientHasFocus ||
((wmGD.nextKeyboardFocus == pCD) ||
(pCD->transientChildren && wmGD.keyboardFocus &&
(pCD == FindTransientTreeLeader (wmGD.nextKeyboardFocus)))))
{
/*
* Give up the keyboard focus when minimized (including
* the case in which an associated transient window has
* the focus). Immediately remove the focus indication
* from the window being minimized.
*/
if (wmGD.autoKeyFocus &&
(wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
{
AutoResetKeyFocus (pcdLeader, setTime);
}
else
{
Do_Focus_Key (NULL, setTime,
ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
}
if (clientHasFocus)
{
SetKeyboardFocus (NULL, 0);
}
}
/* unmap main client and all transients */
UnmapClients (pCD, event_mask);
}
/*
* Display the icon for the minimized client.
*/
if (ICON_FRAME_WIN(pCD))
{
#ifdef WSM
if (pCD->clientState & UNSEEN_STATE)
{
if (pCD->iconWindow)
{
XMapWindow (DISPLAY, pCD->iconWindow);
}
XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
}
ShowAllIconsForMinimizedClient (pCD);
#else /* WSM */
ShowIconForMinimizedClient (pSD->pActiveWS, pCD);
#endif /* WSM */
}
SetClientWMState (pCD, IconicState, MINIMIZED_STATE);
if ((pSD->useIconBox) && P_ICON_BOX(pCD))
{
if ((pCD->clientFlags & ICON_BOX) && ACTIVE_ICON_TEXT_WIN)
{
/*
* Hide active icon text window and reparent it to
* root
*/
HideActiveIconText((WmScreenData *)NULL);
pSD->activeLabelParent = ACTIVE_ROOT;
XReparentWindow(DISPLAY, ACTIVE_ICON_TEXT_WIN ,
ACTIVE_ROOT, 0, 0 );
}
if (ICON_FRAME_WIN(pCD))
{
/*
* force icon appearance in icon box to change
*/
IconExposureProc (pCD, True);
}
}
break;
}
#ifdef WSM
case UNSEEN_STATE | NORMAL_STATE:
case UNSEEN_STATE | MAXIMIZED_STATE:
case UNSEEN_STATE | MINIMIZED_STATE:
{
if (wmGD.keyboardFocus == pCD)
{
/*
* Give up the keyboard focus
*/
Do_Focus_Key ((ClientData *)NULL,
CurrentTime, ALWAYS_SET_FOCUS);
SetKeyboardFocus (NULL, 0);
}
if (!(pCD->clientState & UNSEEN_STATE) &&
(((pCD->clientState & ~UNSEEN_STATE) == NORMAL_STATE) ||
((pCD->clientState & ~UNSEEN_STATE) == MAXIMIZED_STATE)))
{
/* unmap main client and all transients */
UnmapClients (pcdLeader, event_mask);
}
if (pCD->clientFrameWin)
{
if (!P_ICON_BOX(pCD))
{
if (ICON_FRAME_WIN(pCD))
{
XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
}
if (pCD->iconWindow)
XUnmapWindow (DISPLAY, pCD->iconWindow);
}
}
switch (newState & ~UNSEEN_STATE)
{
case MINIMIZED_STATE:
SetClientWMState (pCD, IconicState, newState);
break;
case NORMAL_STATE:
case MAXIMIZED_STATE:
default:
SetClientWMState (pCD, NormalState, newState);
break;
}
}
break;
#endif /* WSM */
}
} /* END OF FUNCTION SetClientStateWithEventMask */
/*************************************<->*************************************
*
* SetupWindowStateWithEventMask (pCD, newState, setTime, event_mask)
*
*
* Description:
* -----------
* This function is used to setup a client window in the Normal or Maximized
* state.
*
*
* Inputs:
* ------
* pCD = This is a pointer to the window data for the window that
* is to have its state changed.
*
* newState = This is the state that the client window is to be changed to.
*
* setTime = timestamp for state setting operations
*
* event_mask = what to grab to prevent stray events going somewhere
*
* Outputs:
* -------
* pCD.clientState = new client state
*
*************************************<->***********************************/
static void SetupWindowStateWithEventMask (ClientData *pCD, int newState,
Time setTime, unsigned int event_mask)
{
int currentState;
#ifdef WSM
int wsI, iplace;
WmWorkspaceData *pWS_i;
#else /* WSM */
WmWorkspaceData *pWS = PSD_FOR_CLIENT(pCD)->pActiveWS;
#endif /* WSM */
WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
currentState = pCD->clientState;
/*
* A transient window is not restored or maximized if the transient leader
* is minimized.
*/
if (newState == NORMAL_STATE)
{
if (pCD->maxConfig == True)
{
/*
* The configuration function uses maxConfig to determine
* what the current configuration is (and then resets
* maxConfig) and uses the state paramenter to determine
* what the new configuration is.
*/
ConfigureNewState (pCD);
}
}
else /* MAXIMIZED_STATE */
{
if (pCD->maxConfig == False)
{
ConfigureNewState (pCD);
}
}
if (currentState == MINIMIZED_STATE)
{
Boolean clearIconFocus;
/*
* give up keyboard focus
*/
if ((wmGD.keyboardFocus == pCD) ||
(wmGD.nextKeyboardFocus == pCD))
{
Do_Focus_Key (NULL, setTime, ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
}
if (wmGD.keyboardFocus == pCD)
{
clearIconFocus = True;
}
else
{
clearIconFocus = False;
}
/*
* The wm icon frame window and the client icon window
* (if it is being used) are mapped and the client window and
* client frame are unmapped.
*/
if (ICON_FRAME_WIN(pCD))
{
if (pSD->useIconBox && P_ICON_BOX(pCD) &&
!(pCD->clientFlags & ICON_BOX))
{
ShowClientIconState(pCD, newState);
}
else
{
Boolean doGrab = False;
if (event_mask)
doGrab = (Success == XGrabPointer
(DISPLAY, DefaultRootWindow(DISPLAY),
False, event_mask, GrabModeAsync, GrabModeAsync,
None, None, CurrentTime));
XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
if (pCD->iconWindow)
{
XUnmapWindow (DISPLAY, pCD->iconWindow);
}
if (event_mask && doGrab)
{
XEvent event;
XMaskEvent(DISPLAY, event_mask, &event);
XUngrabPointer(DISPLAY,CurrentTime);
}
#ifdef WSM
if (wmGD.iconAutoPlace)
{
for (wsI = 0; wsI < pCD->numInhabited; wsI++)
{
iplace = pCD->pWsList[wsI].iconPlace;
if (iplace != NO_ICON_PLACE)
{
pWS_i = GetWorkspaceData (pCD->pSD,
pCD->pWsList[wsI].wsID);
pWS_i->IPData.placeList[iplace].pCD =
NULL;
}
}
}
#else /* WSM */
if ((wmGD.iconAutoPlace) && (ICON_PLACE(pCD) != NO_ICON_PLACE))
{
pWS->IPData.placeList[ICON_PLACE(pCD)].pCD =
NULL;
}
#endif /* WSM */
}
if (clearIconFocus)
{
ClearFocusIndication (pCD, False /*no refresh*/);
wmGD.keyboardFocus = NULL;
}
}
}
if ((currentState != NORMAL_STATE) && (currentState != MAXIMIZED_STATE))
{
/*
* Note that maximized state is considered a NormalState in
* the ICCC. SetClientWMState also sets the state in the
* client data.
*/
if (currentState == MINIMIZED_STATE)
{
/*
* Raise the window(s) when they are deiconified.
*/
pCD->clientState = newState;
#ifdef WSM
wmGD.bSuspendSecondaryRestack = True;
#endif /* WSM */
F_Raise (NULL, pCD, NULL);
#ifdef WSM
wmGD.bSuspendSecondaryRestack = False;
#endif /* WSM */
}
if ( (!(pCD->clientFlags & ICON_BOX)) ||
((pCD->clientFlags & ICON_BOX) && (!(firstTime))) )
{
#ifdef PANELIST
if ((currentState == WITHDRAWN_STATE) &&
(pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) &&
!(pCD->transientChildren))
{
if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
{
pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUB_RESTORED;
pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
XMapWindow (DISPLAY, pCD->client);
XMapWindow (DISPLAY, pCD->clientFrameWin);
}
else
{
SlideWindowOut (pCD);
}
}
else
#endif /* PANELIST */
MapClientWindows (pCD);
}
/*
* Set the WM_STATE property of the window and any associated
* transients, along with the clientState value. The call
* is made with an indication of NORMAL_STATE to insure
* that transient window clientState values are setup
* correctly. The top-level window clientState is set later.
*/
SetClientWMState (pCD, NormalState, NORMAL_STATE);
}
pCD->clientState = newState;
if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
(currentState == MINIMIZED_STATE) && wmGD.deiconifyKeyFocus)
{
ClientData *pcdFocus;
pcdFocus = FindTransientFocus (pCD);
if (pcdFocus)
{
Do_Focus_Key (pcdFocus, setTime, ALWAYS_SET_FOCUS);
}
}
if ( pSD->useIconBox && P_ICON_BOX(pCD) &&
(!(pCD->clientFlags & ICON_BOX)) && (ICON_FRAME_WIN(pCD)))
{
/*
* force icon appearance in icon box to change
*/
IconExposureProc (pCD, True);
}
} /* END OF FUNCTION SetupWindowStateWithEventMask */
/*************************************<->*************************************
*
* ConfigureNewState (pcd)
*
*
* Description:
* -----------
* Configure the window to a new state
*
*
* Inputs:
* ------
* pcd - pointer to client data
*
* Outputs:
* -------
*
*
* Comments:
* --------
* o This is only good for going between NORMAL and MAXIMIZED state.
*
*************************************<->***********************************/
void ConfigureNewState (ClientData *pcd)
{
if (pcd->maxConfig)
{
pcd->maxConfig = FALSE;
RegenerateClientFrame(pcd);
XResizeWindow (DISPLAY, pcd->client,
(unsigned int) pcd->clientWidth,
(unsigned int) pcd->clientHeight);
}
else
{
XResizeWindow (DISPLAY, pcd->client,
(unsigned int) pcd->maxWidth,
(unsigned int) pcd->maxHeight);
pcd->maxConfig = TRUE;
RegenerateClientFrame(pcd);
}
SendConfigureNotify (pcd);
/*
* Force repaint if size doesn't change to update frame appearance.
*/
if ((pcd->clientWidth == pcd->maxWidth) &&
(pcd->clientHeight == pcd->maxHeight))
{
FrameExposureProc (pcd);
}
} /* END OF FUNCTION ConfigureNewState */
/*************************************<->*************************************
*
* UnmapClients (pCD, event_mask)
*
*
* Description:
* -----------
* Unmap the window(s). The indicated client may be the head of a transient
* tree - if it is unmap all windows in the transient tree.
*
*
* Inputs:
* ------
* pCD = pointer to client data of window(s) to be unmapped
* event_mask = what to grab to prevent stray events going somewhere. Our
* passive grab has just been activated -- but it is dropped when the
* window is unmapped and the ButtonRelease event can go to the window
* now exposed. Avoid this by grabbing the ButtonRelease before the unmap
* and swallowing it.
* Also done for icon being unmapped.
*
*************************************<->***********************************/
static void UnmapClients (ClientData *pCD, unsigned int event_mask)
{
ClientData *pNext;
Boolean doGrab = False;
pNext = pCD->transientChildren;
while (pNext)
{
/* unmap all children first */
if (pNext->transientChildren)
UnmapClients (pNext, (unsigned int) 0);
/* then unmap all siblings at this level */
XUnmapWindow (DISPLAY, pNext->clientFrameWin);
XUnmapWindow (DISPLAY, pNext->client);
pNext->wmUnmapCount++;
pNext = pNext->transientSiblings;
}
if (event_mask)
doGrab = (Success == XGrabPointer (DISPLAY, DefaultRootWindow(DISPLAY),
False, event_mask, GrabModeAsync, GrabModeAsync,
None, None, CurrentTime));
/* unmap this primary window */
XUnmapWindow (DISPLAY, pCD->clientFrameWin);
XUnmapWindow (DISPLAY, pCD->client);
if (event_mask && doGrab)
{
XEvent event;
XMaskEvent(DISPLAY, event_mask, &event);
XUngrabPointer(DISPLAY,CurrentTime);
}
pCD->wmUnmapCount++;
} /* END OF FUNCTION UnmapClients */
/*************************************<->*************************************
*
* SetClientWMState (pCD, wmState, mwmState)
*
*
* Description:
* -----------
* Set a new window manage state for a client window or a tree of transient
* client windows.
*
* Inputs:
* ------
* pCD = pointer to client data
*
* wmState = new state for WM_STATE property
*
* mwmState = mwm client state
*
*************************************<->***********************************/
void SetClientWMState (ClientData *pCD, int wmState, int mwmState)
{
ClientData *pNext;
#ifdef WSM
Boolean bToUnseen;
bToUnseen = (mwmState & UNSEEN_STATE) != 0;
mwmState &= ~UNSEEN_STATE;
#endif /* WSM */
#ifdef WSM
SetClientWsIndex (pCD);
#endif /* WSM */
pNext = pCD->transientChildren;
while (pNext)
{
if (pNext->transientChildren)
{
SetClientWMState (pNext, wmState, mwmState);
}
#ifdef WSM
SetClientWsIndex (pNext);
#endif /* WSM */
SetWMState (pNext->client, wmState, ICON_FRAME_WIN(pNext));
if (pNext->maxConfig && mwmState == NORMAL_STATE)
{
pNext->clientState = MAXIMIZED_STATE;
}
#ifdef WSM
else if (!pNext->maxConfig && mwmState == MAXIMIZED_STATE)
{
pNext->clientState = NORMAL_STATE;
}
#endif /* WSM */
else
{
pNext->clientState = mwmState;
}
#ifdef WSM
if (bToUnseen)
pNext->clientState |= UNSEEN_STATE;
#endif /* WSM */
pNext = pNext->transientSiblings;
}
SetWMState (pCD->client, wmState, ICON_FRAME_WIN(pCD));
pCD->clientState = mwmState;
#ifdef WSM
if (bToUnseen)
pCD->clientState |= UNSEEN_STATE;
#endif /* WSM */
} /* END OF FUNCTION SetClientWMState */
#ifdef PANELIST
#define SLIDE_UP_PERCENTAGE 5
#define SLIDE_UP_DIVISOR (100/SLIDE_UP_PERCENTAGE)
#define SLIDE_UP_INTERVAL 15
/******************************<->*************************************
*
* void SlideOutTimerProc (client_data, id)
*
* Description:
* -----------
* An XtTimerCallbackProc to process slide up mapping of a panel
*
* Inputs:
* ------
* client_data = pointer to a SlideOutRec
*
* Outputs:
* -------
*
*
* Comments:
* --------
******************************<->***********************************/
void
SlideOutTimerProc ( XtPointer client_data, XtIntervalId *id)
{
SlideOutRec *pSOR = (SlideOutRec *) client_data;
Boolean bDone = False;
if (pSOR)
{
/*
* compute next increment;
*/
switch (pSOR->direction)
{
case SLIDE_NORTH:
if (pSOR->mapping)
{
pSOR->currY -= pSOR->incHeight;
pSOR->currHeight += pSOR->incHeight;
if ((pSOR->currY < pSOR->pCD->frameInfo.y) ||
(pSOR->currHeight > pSOR->pCD->frameInfo.height))
{
pSOR->currY = pSOR->pCD->frameInfo.y;
pSOR->currHeight = pSOR->pCD->frameInfo.height;
}
bDone = (pSOR->currY == pSOR->pCD->frameInfo.y);
}
else
{
pSOR->currY += pSOR->incHeight;
if (pSOR->incHeight >= pSOR->currHeight)
{
pSOR->currHeight = 0;
bDone = True;
}
else
{
pSOR->currHeight -= pSOR->incHeight;
}
}
break;
case SLIDE_SOUTH:
if (pSOR->mapping)
{
pSOR->currHeight += pSOR->incHeight;
if (pSOR->currHeight > pSOR->pCD->frameInfo.height)
{
pSOR->currHeight = pSOR->pCD->frameInfo.height;
}
bDone =
(pSOR->currHeight == pSOR->pCD->frameInfo.height);
}
else
{
if (pSOR->incHeight >= pSOR->currHeight)
{
pSOR->currHeight = 0;
bDone = True;
}
else
{
pSOR->currHeight -= pSOR->incHeight;
}
}
break;
}
/*
* do next slide-up
*/
if (pSOR->currHeight > 0)
{
XMoveResizeWindow (DISPLAY, pSOR->coverWin,
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight);
XMoveResizeWindow (DISPLAY, pSOR->pCD->clientFrameWin,
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight);
}
/*
* See if we need to continue
*/
if (bDone)
{
if (!pSOR->mapping)
{
/* Time to really unmanage the slide-up */
XtUnmanageChild (pSOR->wSubpanel);
}
else
{
WmSubpanelPosted (DISPLAY1, pSOR->pCD->client);
SendConfigureNotify(pSOR->pCD);
}
/* done! clean up */
XDestroyWindow (DISPLAY, pSOR->coverWin);
pSOR->pCD->pSOR = NULL;
XtFree ((char *)pSOR);
wmGD.iSlideUpsInProgress -= 1;
}
else
{
/* re-arm the timer */
XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
SlideOutTimerProc, (XtPointer)pSOR);
XSync (DISPLAY, False);
}
}
} /* END OF FUNCTION SlideOutTimerProc */
/*************************************<->*************************************
*
* SlideWindowOut (pCD)
*
*
* Description:
* -----------
* Maps a window with a slide-out effect.
*
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Comment:
* -------
* Only supports slide-up or slide-down
*
*************************************<->***********************************/
static void
SlideWindowOut (ClientData *pCD)
{
SlideOutRec *pSOR;
if (pCD->pSOR)
{
pSOR = pCD->pSOR;
/*
* Hmmm. We're already sliding this window.
* If we're supposed to go in the other direction,
* then turn it around.
*/
if (pSOR->mapping == True)
{
/*
* We're already mapping this guy, ignore this
* and finish what we've already got going.
*/
return;
}
else
{
/*
* We're not mapping this guy. Reverse course!!
*/
pSOR->mapping = True;
/* insure the client window is mapped */
XMapWindow (DISPLAY, pCD->client);
/* handle the rest on the next timeout */
return;
}
}
/* map the primary window */
XMapWindow (DISPLAY, pCD->client);
pSOR = (SlideOutRec *) XtMalloc (sizeof(SlideOutRec));
if (pSOR)
{
/*
* Compute this ahead of time so we can check against
* the window size. If the window is short, we'll
* just map it, avoiding a lot of processing.
*/
pSOR->incHeight = (Dimension) (DisplayHeight(DISPLAY,
SCREEN_FOR_CLIENT(pCD))/SLIDE_UP_DIVISOR);
}
if ((pCD->slideDirection != SLIDE_NOT) && pSOR &&
(pSOR->incHeight < pCD->frameInfo.height))
{
XSetWindowAttributes window_attribs;
XWindowChanges window_changes;
unsigned long mask;
/*
* Set up data for processing slide up
*/
pSOR->pCD = pCD;
pSOR->interval = SLIDE_UP_INTERVAL;
pSOR->direction = pCD->slideDirection;
pSOR->mapping = True;
pSOR->wSubpanel = NULL;
pSOR->pCD->pSOR = pSOR;
switch (pSOR->direction)
{
case SLIDE_NORTH:
pSOR->incWidth = 0;
pSOR->currWidth = pCD->frameInfo.width;
pSOR->currHeight = pSOR->incHeight;
pSOR->currX = pCD->frameInfo.x;
pSOR->currY = pCD->frameInfo.y +
(pCD->frameInfo.height - pSOR->currHeight);
break;
case SLIDE_SOUTH:
pSOR->incWidth = 0;
pSOR->currWidth = pCD->frameInfo.width;
pSOR->currHeight = pSOR->incHeight;
pSOR->currX = pCD->frameInfo.x;
pSOR->currY = pCD->frameInfo.y;
break;
}
/*
* Create screening window to hide the slide-up from button
* events until it is all the way up.
*/
mask = CWOverrideRedirect;
window_attribs.override_redirect = True;
pSOR->coverWin = XCreateWindow(DISPLAY,
RootWindow (DISPLAY, SCREEN_FOR_CLIENT(pCD)),
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight, 0,
CopyFromParent,InputOnly,CopyFromParent,
mask, &window_attribs);
/*
* Put screen window above the slide-up client
*/
mask = CWStackMode | CWSibling;
window_changes.stack_mode = Above;
window_changes.sibling = pCD->clientFrameWin;
XConfigureWindow (DISPLAY, pSOR->coverWin, mask, &window_changes);
/*
* Start slide-up processing
*/
XMoveResizeWindow (DISPLAY, pSOR->coverWin, pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight);
XMoveResizeWindow (DISPLAY, pCD->clientFrameWin,
pSOR->currX, pSOR->currY, pSOR->currWidth, pSOR->currHeight);
XMapWindow (DISPLAY, pSOR->coverWin);
XMapWindow (DISPLAY, pCD->clientFrameWin);
XSync (DISPLAY, False);
XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
SlideOutTimerProc, (XtPointer)pSOR);
wmGD.iSlideUpsInProgress += 1;
}
else
{
/*
* Not sliding because no direction specified or our window
* is just a little guy.
*/
XMapWindow (DISPLAY, pCD->clientFrameWin);
if (pSOR)
{
XtFree ((char *) pSOR);
pCD->pSOR = NULL;
}
}
} /* END OF FUNCTION SlideOutWindow */
/*************************************<->*************************************
*
* SlideSubpanelBackIn (pCD, wSubpanel)
*
*
* Description:
* -----------
* Slides a subpanel back in
*
*
* Inputs:
* ------
* pCD = pointer to client data
* wSubpanel = subpanel widget to unmanage
*
* Comment:
* -------
*
*************************************<->***********************************/
void
SlideSubpanelBackIn (ClientData *pCD, Widget wSubpanel)
{
SlideOutRec *pSOR;
if (pCD->pSOR)
{
pSOR = pCD->pSOR;
/*
* Hmmm. We're already sliding this window.
* If we're supposed to go in the other direction,
* then turn it around.
*/
if (pSOR->mapping == False)
{
/*
* We're already unmapping this guy, ignore this
* and finish what we've already got going.
*/
return;
}
else
{
/*
* We're mapping this guy. Reverse course!!
*/
pSOR->mapping = False;
pSOR->wSubpanel = wSubpanel;
/* handle the rest on the next timeout */
return;
}
}
pSOR = (SlideOutRec *) XtMalloc (sizeof(SlideOutRec));
if (pSOR)
{
/*
* Compute this ahead of time to check if our window
* is short. If it is, we'll just unmap it, avoiding
* a lot of extra work.
*/
pSOR->incHeight = (Dimension) (DisplayHeight(DISPLAY,
SCREEN_FOR_CLIENT(pCD))/SLIDE_UP_DIVISOR);
}
if ((pCD->slideDirection != SLIDE_NOT) && pSOR &&
(pSOR->incHeight < pCD->frameInfo.height))
{
XSetWindowAttributes window_attribs;
XWindowChanges window_changes;
unsigned long mask;
/*
* Set up data for processing slide up
*/
pSOR->pCD = pCD;
pSOR->interval = SLIDE_UP_INTERVAL;
pSOR->direction = pCD->slideDirection;
pSOR->mapping = False;
pSOR->wSubpanel = wSubpanel;
pSOR->pCD->pSOR = pSOR;
pSOR->incWidth = 0;
pSOR->currWidth = pCD->frameInfo.width;
pSOR->currHeight = pCD->frameInfo.height;
pSOR->currX = pCD->frameInfo.x;
pSOR->currY = pCD->frameInfo.y;
switch (pSOR->direction)
{
case SLIDE_NORTH:
pSOR->currHeight -= pSOR->incHeight;
pSOR->currY += pSOR->incHeight;
break;
case SLIDE_SOUTH:
pSOR->currHeight -= pSOR->incHeight;
break;
}
/*
* Create screening window to hide the slide-up from button
* events until it is all the way up.
*/
mask = CWOverrideRedirect;
window_attribs.override_redirect = True;
pSOR->coverWin = XCreateWindow(DISPLAY,
RootWindow (DISPLAY, SCREEN_FOR_CLIENT(pCD)),
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight, 0,
CopyFromParent,InputOnly,CopyFromParent,
mask, &window_attribs);
/*
* Put screen window above the slide-up client
*/
mask = CWStackMode | CWSibling;
window_changes.stack_mode = Above;
window_changes.sibling = pCD->clientFrameWin;
XConfigureWindow (DISPLAY, pSOR->coverWin, mask, &window_changes);
/*
* Start slide-up processing
*/
XMapWindow (DISPLAY, pSOR->coverWin);
if (pSOR->currHeight > 0)
{
XMoveResizeWindow (DISPLAY, pCD->clientFrameWin,
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight);
XMoveResizeWindow (DISPLAY, pSOR->coverWin,
pSOR->currX, pSOR->currY,
pSOR->currWidth, pSOR->currHeight);
XSync (DISPLAY, False);
}
XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
SlideOutTimerProc, (XtPointer)pSOR);
wmGD.iSlideUpsInProgress += 1;
}
else
{
/*
* Not sliding because no direction specified or our window
* is just a little guy.
*/
/* Just unmanage the slide-up */
XtUnmanageChild (wSubpanel);
if (pSOR)
{
XtFree ((char *) pSOR);
pCD->pSOR = NULL;
}
}
} /* END OF FUNCTION SlideOutWindow */
#endif /* PANELIST */
/*************************************<->*************************************
*
* MapClientWindows (pCD)
*
*
* Description:
* -----------
* Maps the window. If this is a transient tree then all the windows in
* the transient tree are mapped.
*
*
* Inputs:
* ------
* pCD = pointer to client data
*
*************************************<->***********************************/
void MapClientWindows (ClientData *pCD)
{
ClientData *pNext;
pNext = pCD->transientChildren;
while (pNext)
{
/* map all transient children first */
if (pNext->transientChildren)
{
MapClientWindows (pNext);
}
/* then map all siblings at this level */
XMapWindow (DISPLAY, pNext->client);
XMapWindow (DISPLAY, pNext->clientFrameWin);
pNext = pNext->transientSiblings;
}
/* map the primary window */
XMapWindow (DISPLAY, pCD->client);
XMapWindow (DISPLAY, pCD->clientFrameWin);
} /* END OF FUNCTION MapClientWindows */
/*************************************<->*************************************
*
* ShowIconForMinimizedClient (pWS, pCD)
*
*
* Description:
* -----------
* This function shows the icon for the specified client. If the icon
* is in an icon box then the "minimized" icon is displayed. If the icon
* is on the root window it is mapped.
*
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pCD = pointer to client data
*
*************************************<->***********************************/
void ShowIconForMinimizedClient (WmWorkspaceData *pWS, ClientData *pCD)
{
WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
/*
* Handle auto-placement for root icons (icons not in an icon
* box).
*/
if (wmGD.iconAutoPlace && !P_ICON_BOX(pCD))
{
if ((ICON_PLACE(pCD) == NO_ICON_PLACE) ||
((pWS->IPData.placeList[ICON_PLACE(pCD)].pCD) &&
(pWS->IPData.placeList[ICON_PLACE(pCD)].pCD != pCD)))
{
/*
* Icon place not defined or occupied by another client,
* find a free place to put the icon.
*/
if ((ICON_PLACE(pCD) = GetNextIconPlace (&pWS->IPData))
== NO_ICON_PLACE)
{
ICON_PLACE(pCD) =
CvtIconPositionToPlace (&pWS->IPData,
pCD->clientX,
pCD->clientY);
}
CvtIconPlaceToPosition (&pWS->IPData, ICON_PLACE(pCD),
&ICON_X(pCD), &ICON_Y(pCD));
#ifndef WSM
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD),
ICON_X(pCD), ICON_Y(pCD));
#endif /* WSM */
}
pWS->IPData.placeList[ICON_PLACE(pCD)].pCD = pCD;
}
#ifdef WSM
/*
* If icon on root window and this workspace is active, the
* make sure it's in the right place.
*/
if ((pWS == pSD->pActiveWS) && !P_ICON_BOX(pCD))
{
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD),
ICON_X(pCD), ICON_Y(pCD));
}
#endif /* WSM */
if (pCD->iconWindow)
{
XMapWindow (DISPLAY, pCD->iconWindow);
}
if ((pSD->useIconBox) && P_ICON_BOX(pCD))
{
ShowClientIconState (pCD, MINIMIZED_STATE );
}
else
{
XWindowChanges windowChanges;
/*
* Map the icon on the screen at the appropriate place in the
* window stack.
*/
if (wmGD.lowerOnIconify)
{
if ((&pCD->iconEntry != pSD->lastClient) &&
(pSD->lastClient))
{
if (pSD->lastClient->type == MINIMIZED_STATE)
{
windowChanges.sibling =
ICON_FRAME_WIN(pSD->lastClient->pCD);
}
else
{
windowChanges.sibling =
pSD->lastClient->pCD->clientFrameWin;
}
windowChanges.stack_mode = Below;
XConfigureWindow (DISPLAY, ICON_FRAME_WIN(pCD),
(CWSibling | CWStackMode), &windowChanges);
MoveEntryInList (pWS, &pCD->iconEntry,
False /*on bottom*/, NULL);
}
}
else
{
windowChanges.sibling = pCD->clientFrameWin;
windowChanges.stack_mode = Below;
XConfigureWindow (DISPLAY, ICON_FRAME_WIN(pCD),
(CWSibling | CWStackMode), &windowChanges);
MoveEntryInList (pWS, &pCD->iconEntry, False /*below*/,
&pCD->clientEntry);
}
#ifdef WSM
if (pWS == pSD->pActiveWS)
{
XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
}
#else /* WSM */
XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
#endif /* WSM */
}
} /* END OF FUNCTION ShowIconForMinimizedClient */
#ifdef WSM
/*************************************<->*************************************
*
* ShowAllIconsForMinimizedClient (pCD)
*
*
* Description:
* -----------
* This function places icons in all the workspaces for the minimized
* client. Since there is only one clientState per client (not per
* workspace), this loops over all workspace in which the client
* resides and places an icon in each.
*
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Comments:
* ---------
* This operates by setting up the currentWsc index for each workspace
* and calling ShowIconForMinimizedClient, which makes heavy use of
* the macros that use the currentWsc index.
*
*************************************<->***********************************/
void ShowAllIconsForMinimizedClient (ClientData *pCD)
{
int saveWsc = pCD->currentWsc;
int tmpWsc;
WmWorkspaceData *pWS;
for (tmpWsc = 0; tmpWsc < pCD->numInhabited; tmpWsc++)
{
pCD->currentWsc = tmpWsc;
pWS = GetWorkspaceData (PSD_FOR_CLIENT(pCD),
pCD->pWsList[tmpWsc].wsID);
ShowIconForMinimizedClient(pWS, pCD);
}
pCD->currentWsc = saveWsc;
} /* END OF FUNCTION ShowAllIconsForMinimizedClient */
#endif /* WSM */