/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1989, 1990, 1991, 1992 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * Motif Release 1.2.1 */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$XConsortium: WmIPlace.c /main/4 1995/11/01 11:41:20 rswiston $" #endif #endif /* * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */ /* * Included Files: */ #include "WmGlobal.h" /* * include extern functions */ #include "WmError.h" #include "WmIDecor.h" #include "WmIconBox.h" #include "WmWinConf.h" #ifdef WSM #include "WmWrkspace.h" #endif /* WSM */ /* * Function Declarations: */ #include "WmIPlace.h" /* * Global Variables: */ extern Dimension clipWidth; extern Dimension clipHeight; extern Position clipX; extern Position clipY; /*************************************<->************************************* * * InitIconPlacement () * * * Description: * ----------- * This function intializes icon placement information. * * * Inputs: * ------ * pWS = pointer to workspace data * * * Outputs: * ------- * IconPlacmementData * *************************************<->***********************************/ void InitIconPlacement (WmWorkspaceData *pWS) { Boolean useMargin; int sW; int sH; int iSpaceX; int iSpaceY; int placementW; int placementH; int extraXSpace; int extraYSpace; int xMargin; int yMargin; int extraPX; int extraPY; int i; xMargin = yMargin = extraPX = extraPY = 0; sW = DisplayWidth (DISPLAY, pWS->pSD->screen); sH = DisplayHeight (DISPLAY, pWS->pSD->screen); useMargin = (pWS->pSD->iconPlacementMargin >= 0); pWS->IPData.iconPlacement = pWS->pSD->iconPlacement; if (useMargin) { pWS->IPData.placementCols = (sW - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconWidth; pWS->IPData.placementRows = (sH - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconHeight; } else { pWS->IPData.placementCols = sW / pWS->pSD->iconWidth; pWS->IPData.placementRows = sH / pWS->pSD->iconHeight; } if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT) { iSpaceX = 0; iSpaceY = 0; xMargin = 2; yMargin = 2; } else { do { if (useMargin) { iSpaceX = (sW - (2 * pWS->pSD->iconPlacementMargin) - (pWS->IPData.placementCols * pWS->pSD->iconWidth)) / (pWS->IPData.placementCols - 1); } else { iSpaceX = (sW - (pWS->IPData.placementCols * pWS->pSD->iconWidth)) / pWS->IPData.placementCols; } if (iSpaceX < MINIMUM_ICON_SPACING) { pWS->IPData.placementCols--; } } while (iSpaceX < MINIMUM_ICON_SPACING); do { if (useMargin) { iSpaceY = (sH - (2 * pWS->pSD->iconPlacementMargin) - (pWS->IPData.placementRows * pWS->pSD->iconHeight)) / (pWS->IPData.placementRows - 1); } else { iSpaceY = (sH - (pWS->IPData.placementRows * pWS->pSD->iconHeight)) / pWS->IPData.placementRows; } if (iSpaceY < MINIMUM_ICON_SPACING) { pWS->IPData.placementRows--; } } while (iSpaceY < MINIMUM_ICON_SPACING); } pWS->IPData.iPlaceW = pWS->pSD->iconWidth + iSpaceX; pWS->IPData.iPlaceH = pWS->pSD->iconHeight + iSpaceY; placementW = pWS->IPData.placementCols * pWS->IPData.iPlaceW; placementH = pWS->IPData.placementRows * pWS->IPData.iPlaceH; pWS->IPData.placeIconX = ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) + 1) / 2; pWS->IPData.placeIconY = ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) + 1) / 2; /* * Special case margin handling for TIGHT icon placement */ if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT) { if (useMargin) { xMargin = pWS->pSD->iconPlacementMargin; yMargin = pWS->pSD->iconPlacementMargin; } extraXSpace = 0; extraYSpace = 0; if ((pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) || (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_SECONDARY)) xMargin = sW - placementW - xMargin; if ((pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) || (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_SECONDARY)) yMargin = sH - placementH - yMargin; } else { if (useMargin) { xMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconX; extraXSpace = sW - (2 * pWS->pSD->iconPlacementMargin) - (placementW - iSpaceX); extraPX = (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) ? 1 : (pWS->IPData.placementCols - extraXSpace); yMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconY; extraYSpace = sH - (2 * pWS->pSD->iconPlacementMargin) - (placementH - iSpaceY); extraPY = (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) ? 1 : (pWS->IPData.placementRows - extraYSpace); } else { xMargin = (sW - placementW + ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) & 1)) / 2; extraXSpace = 0; yMargin = (sH - placementH + ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) & 1))/ 2; extraYSpace = 0; if (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) { xMargin = sW - placementW - xMargin; pWS->IPData.placeIconX = pWS->IPData.iPlaceW - pWS->pSD->iconWidth - pWS->IPData.placeIconX; } if (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) { yMargin = sH - placementH - yMargin; pWS->IPData.placeIconY = pWS->IPData.iPlaceH - pWS->pSD->iconHeight - pWS->IPData.placeIconY; } } } /* * Setup array of grid row positions and grid column positions: */ if ((pWS->IPData.placementRowY = (int *)XtMalloc ((pWS->IPData.placementRows+2) * sizeof (int))) == NULL) { Warning (((char *)GETMESSAGE(34, 1, "Insufficient memory for icon placement"))); wmGD.iconAutoPlace = False; return; } else if ((pWS->IPData.placementColX = (int *)XtMalloc ((pWS->IPData.placementCols+2) * sizeof (int))) == NULL) { XtFree ((char *)pWS->IPData.placementRowY); Warning (((char *)GETMESSAGE(34, 2, "Insufficient memory for icon placement"))); wmGD.iconAutoPlace = False; return; } pWS->IPData.placementRowY[0] = yMargin; for (i = 1; i <= pWS->IPData.placementRows; i++) { pWS->IPData.placementRowY[i] = pWS->IPData.placementRowY[i - 1] + pWS->IPData.iPlaceH; if ((extraYSpace > 0) && (i >= extraPY)) { (pWS->IPData.placementRowY[i])++; extraYSpace--; } } pWS->IPData.placementColX[0] = xMargin; for (i = 1; i <= pWS->IPData.placementCols; i++) { pWS->IPData.placementColX[i] = pWS->IPData.placementColX[i - 1] + pWS->IPData.iPlaceW; if ((extraXSpace > 0) && (i >= extraPX)) { (pWS->IPData.placementColX[i])++; extraXSpace--; } } /* * Setup an array of icon places. */ pWS->IPData.totalPlaces = pWS->IPData.placementRows * pWS->IPData.placementCols; if ((pWS->IPData.placeList = (IconInfo *)XtMalloc (pWS->IPData.totalPlaces * sizeof (IconInfo))) == NULL) { Warning (((char *)GETMESSAGE(34, 3, "Insufficient memory for icon placement"))); XtFree ((char *)pWS->IPData.placementRowY); XtFree ((char *)pWS->IPData.placementColX); wmGD.iconAutoPlace = False; return; } memset ((char *)pWS->IPData.placeList, 0, pWS->IPData.totalPlaces * sizeof (IconInfo)); pWS->IPData.onRootWindow = True; } /* END OF FUNCTION InitIconPlacement */ /*************************************<->************************************* * * GetNextIconPlace (pIPD) * * * Description: * ----------- * This function identifies and returns the next free icon grid place. * * * Outputs: * ------- * Return = next free place (index) * *************************************<->***********************************/ int GetNextIconPlace (IconPlacementData *pIPD) { int i; for (i = 0; i < pIPD->totalPlaces; i++) { if (pIPD->placeList[i].pCD == (ClientData *)NULL) { return (i); } } /* * All places are filled! Find an alternative place. */ return (NO_ICON_PLACE); } /* END OF FUNCTION GetNextIconPlace */ /*************************************<->************************************* * * CvtIconPlaceToPosition (pIPD, place, pX, pY) * * * Description: * ----------- * This function converts an icon place (index) into an icon position. * * * Inputs: * ------ * pIPD = ptr to icon placement data * * place = place to be converted * * wmGD = (iconPlacement ...) * * * Outputs: * ------- * pX = pointer to icon place X location * * pY = pointer to icon place Y location * *************************************<->***********************************/ void CvtIconPlaceToPosition (IconPlacementData *pIPD, int place, int *pX, int *pY) { int row; int col; if (pIPD->iconPlacement & (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY)) { col = place % pIPD->placementCols; row = place / pIPD->placementCols; } else { col = place / pIPD->placementRows; row = place % pIPD->placementRows; } if (pIPD->iconPlacement & (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY)) { col = pIPD->placementCols - col - 1; } if (pIPD->iconPlacement & (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY)) { row = pIPD->placementRows - row - 1; } if (pIPD->onRootWindow) { *pX = pIPD->placementColX[col] + pIPD->placeIconX; *pY = pIPD->placementRowY[row] + pIPD->placeIconY; } else { *pX = col * pIPD->iPlaceW; *pY = row * pIPD->iPlaceH; } } /* END OF FUNCTION CvtIconPlaceToPosition */ /*************************************<->************************************* * * FindIconPlace (pCD, pIPD, x, y) * * * Description: * ----------- * This function is used to find a free icon place in the proximity of the * specified position. * * * Inputs: * ------ * pIPD = ptr to icon placement data * * x = desired x location of icon place * * y = desired y location of icon place * * * Outputs: * ------- * Return = icon place (index) * * * Comments: * -------- * Look first for a free icon place at the position passed in. If that place * is taken then look at positions that are +- one half the icon width/height * from the postion passed in. If those positions are taken look at * positions that are +- one half icon placement width/height from the * position passed in. * *************************************<->***********************************/ int FindIconPlace (ClientData *pCD, IconPlacementData *pIPD, int x, int y) { int place; int i; int j; int diffX; int diffY; int altX; int altY; int amt; place = CvtIconPositionToPlace (pIPD, x, y); if (place < pIPD->totalPlaces) { if (pIPD->placeList[place].pCD == (ClientData *)NULL) { return (place); } } else { if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY) { amt = pIPD->placementCols; /* add a new row */ } else { amt = pIPD->placementRows; /* add a new column */ } if (!ExtendIconList (P_ICON_BOX(pCD), amt)) { Warning (((char *)GETMESSAGE(34, 4, "Insufficient memory to create icon box data"))); return (NO_ICON_PLACE); } } /* * The place for the passed in position is in use, look at places for * alternative positions. */ for (i = 0; i < 2; i++) { switch (i) { case 0: { diffX = ICON_WIDTH(pCD) / 2; diffY = ICON_HEIGHT(pCD) / 2; break; } case 1: { diffX = pIPD->iPlaceW / 2; diffY = pIPD->iPlaceH / 2; break; } } for (j = 0; j < 4; j++) { switch (j) { case 0: { if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY) { altX = x - diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY) { altX = x + diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY) { altX = x; altY = y - diffY; } else { altX = x; altY = y + diffY; } break; } case 1: { if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY) { altX = x + diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY) { altX = x - diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY) { altX = x; altY = y + diffY; } else { altX = x; altY = y - diffY; } break; } case 2: { if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY) { altX = x - diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY) { altX = x + diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY) { altX = x; altY = y + diffY; } else { altX = x; altY = y - diffY; } break; } case 3: { if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY) { altX = x + diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY) { altX = x - diffX; altY = y; } else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY) { altX = x; altY = y - diffY; } else { altX = x; altY = y + diffY; } break; } } if (P_ICON_BOX(pCD)) { GetClipDimensions(pCD, False); if (altX < clipX) { return (NO_ICON_PLACE); } if (altY < clipY) { return (NO_ICON_PLACE); } if (((int)altX) > ((int)clipX + (int)clipWidth - ((int)ICON_WIDTH(pCD)))) { return (NO_ICON_PLACE); } if (((int)altY) > ((int)clipY + (int)clipHeight - ((int)ICON_HEIGHT(pCD)))) { return (NO_ICON_PLACE); } } place = CvtIconPositionToPlace (pIPD, altX, altY); if ((pIPD->placeList[place].pCD) == NULL) { return (place); } } } /* * Couldn't find an unoccupied place in the proximity of the passed-in * position. */ return (NO_ICON_PLACE); } /* END OF FUNCTION FindIconPlace */ /*************************************<->************************************* * * CvtIconPostionToPlace (pIPD, x, y) * * * Description: * ----------- * This function converts an icon position to an icon place. * * * Inputs: * ------ * pIPD = ptr to icon placement data * * x,y = location to be converted into an icon place * * * Outputs: * ------- * Return = icon place (index) * *************************************<->***********************************/ int CvtIconPositionToPlace (IconPlacementData *pIPD, int x, int y) { int row; int col; if (pIPD->onRootWindow) { /* * Scan through the root window row/column arrays and find the * placement position. */ for (row = 1; row < pIPD->placementRows; row++) { if (y < pIPD->placementRowY[row]) { break; } } row--; for (col = 1; col < pIPD->placementCols; col++) { if (x < pIPD->placementColX[col]) { break; } } col--; if (pIPD->iconPlacement & (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY)) { col = pIPD->placementCols - col - 1; } if (pIPD->iconPlacement & (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY)) { row = pIPD->placementRows - row - 1; } } else { /* * convert icon box coords */ col = x / pIPD->iPlaceW; row = y / pIPD->iPlaceH; } if (pIPD->iconPlacement & (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY)) { return ((row * pIPD->placementCols) + col); } else { return ((col * pIPD->placementRows) + row); } } /* END OF FUNCTION CvtIconPositionToPlace */ /*************************************<->************************************* * * PackRootIcons () * * * Description: * ----------- * This function packs the icons on the root window * * * Inputs: * ------ * * Outputs: * ------- * * Comments: * --------- * *************************************<->***********************************/ void PackRootIcons (void) { int iOld, iNew; ClientData *pCD; ClientData *pCD_active; int hasActiveText = 1; #ifdef WSM WsClientData *pWsc; #endif /* WSM */ /* * find context of the activeIconTextWin to get pCD and then * if it is the same as this client, hide it. */ if (XFindContext (DISPLAY, ACTIVE_PSD->activeIconTextWin, wmGD.windowContextType, (caddr_t *)&pCD_active)) { hasActiveText = 0; } /* * Traverse the list and pack them together */ if (wmGD.iconAutoPlace) { for (iOld = iNew = 0; iOld < ACTIVE_WS->IPData.totalPlaces; iOld++, iNew++) { if (ACTIVE_WS->IPData.placeList[iOld].pCD == NULL) { /* advance to next non-null entry */ while (++iOld < ACTIVE_WS->IPData.totalPlaces && !ACTIVE_WS->IPData.placeList[iOld].pCD) ; } if (iOld < ACTIVE_WS->IPData.totalPlaces && iOld != iNew) { /* move the icon from its old place to the new place */ MoveIconInfo (&ACTIVE_WS->IPData, iOld, iNew); pCD = ACTIVE_WS->IPData.placeList[iNew].pCD; #ifdef WSM pWsc = GetWsClientData (ACTIVE_WS, pCD); pWsc->iconPlace = iNew; CvtIconPlaceToPosition (&ACTIVE_WS->IPData, pWsc->iconPlace, &pWsc->iconX, &pWsc->iconY); #else /* WSM */ pCD->iconPlace = iNew; CvtIconPlaceToPosition (&ACTIVE_WS->IPData, pCD->iconPlace, &pCD->iconX, &pCD->iconY); #endif /* WSM */ if (hasActiveText && (pCD == pCD_active)) { /* hide activeIconTextWin first */ HideActiveIconText ((WmScreenData *)NULL); #ifdef WSM XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX, pWsc->iconY); #else /* WSM */ XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), pCD->iconX, pCD->iconY); #endif /* WSM */ ShowActiveIconText (pCD); } else { #ifdef WSM XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX, pWsc->iconY); #else /* WSM */ XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), pCD->iconX, pCD->iconY); #endif /* WSM */ } } } } } /* END OF FUNCTION PackRootIcons */ /*************************************<->************************************* * * MoveIconInfo (pIPD, p1, p2) * * * Description: * ----------- * Move icon info from place 1 to place 2 in the placement list. * * * Inputs: * ------ * pIPD - ptr to icon placement data * p1 - placement index 1 (source) * p2 - placement index 2 (destination) * * Outputs: * ------- * * Comments: * -------- * *************************************<->***********************************/ void MoveIconInfo (IconPlacementData *pIPD, int p1, int p2) { #ifdef WSM WsClientData *pWsc; #endif /* WSM */ /* only move if destination is empty */ if (pIPD->placeList[p2].pCD == NULL) { pIPD->placeList[p2].pCD = pIPD->placeList[p1].pCD; pIPD->placeList[p2].theWidget = pIPD->placeList[p1].theWidget; #ifdef WSM pWsc = GetWsClientData (pIPD->placeList[p2].pCD->pSD->pActiveWS, pIPD->placeList[p2].pCD); pWsc->iconPlace = p2; #else /* WSM */ pIPD->placeList[p2].pCD->iconPlace = p2; #endif /* WSM */ pIPD->placeList[p1].pCD = NULL; pIPD->placeList[p1].theWidget = NULL; } } #ifdef WSM /**************************** eof ***************************/ #endif /* WSM */