2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$XConsortium: WmIPlace.c /main/4 1995/11/01 11:41:20 rswiston $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
45 * include extern functions
50 #include "WmIconBox.h"
51 #include "WmWinConf.h"
53 #include "WmWrkspace.h"
58 * Function Declarations:
66 extern Dimension clipWidth;
67 extern Dimension clipHeight;
68 extern Position clipX;
69 extern Position clipY;
71 /*************************************<->*************************************
73 * InitIconPlacement ()
78 * This function intializes icon placement information.
83 * pWS = pointer to workspace data
90 *************************************<->***********************************/
92 void InitIconPlacement (WmWorkspaceData *pWS)
110 xMargin = yMargin = extraPX = extraPY = 0;
112 sW = DisplayWidth (DISPLAY, pWS->pSD->screen);
113 sH = DisplayHeight (DISPLAY, pWS->pSD->screen);
114 useMargin = (pWS->pSD->iconPlacementMargin >= 0);
115 pWS->IPData.iconPlacement = pWS->pSD->iconPlacement;
119 pWS->IPData.placementCols =
120 (sW - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconWidth;
121 pWS->IPData.placementRows =
122 (sH - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconHeight;
126 pWS->IPData.placementCols = sW / pWS->pSD->iconWidth;
127 pWS->IPData.placementRows = sH / pWS->pSD->iconHeight;
130 if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT)
144 (sW - (2 * pWS->pSD->iconPlacementMargin) -
145 (pWS->IPData.placementCols * pWS->pSD->iconWidth)) /
146 (pWS->IPData.placementCols - 1);
151 (sW - (pWS->IPData.placementCols * pWS->pSD->iconWidth)) /
152 pWS->IPData.placementCols;
154 if (iSpaceX < MINIMUM_ICON_SPACING)
156 pWS->IPData.placementCols--;
159 while (iSpaceX < MINIMUM_ICON_SPACING);
165 iSpaceY = (sH - (2 * pWS->pSD->iconPlacementMargin) -
166 (pWS->IPData.placementRows * pWS->pSD->iconHeight)) /
167 (pWS->IPData.placementRows - 1);
172 (sH - (pWS->IPData.placementRows * pWS->pSD->iconHeight)) /
173 pWS->IPData.placementRows;
175 if (iSpaceY < MINIMUM_ICON_SPACING)
177 pWS->IPData.placementRows--;
180 while (iSpaceY < MINIMUM_ICON_SPACING);
183 pWS->IPData.iPlaceW = pWS->pSD->iconWidth + iSpaceX;
184 pWS->IPData.iPlaceH = pWS->pSD->iconHeight + iSpaceY;
186 placementW = pWS->IPData.placementCols * pWS->IPData.iPlaceW;
187 placementH = pWS->IPData.placementRows * pWS->IPData.iPlaceH;
189 pWS->IPData.placeIconX =
190 ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) + 1) / 2;
191 pWS->IPData.placeIconY =
192 ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) + 1) / 2;
195 * Special case margin handling for TIGHT icon placement
197 if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT)
201 xMargin = pWS->pSD->iconPlacementMargin;
202 yMargin = pWS->pSD->iconPlacementMargin;
208 if ((pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) ||
209 (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_SECONDARY))
210 xMargin = sW - placementW - xMargin;
212 if ((pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) ||
213 (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_SECONDARY))
214 yMargin = sH - placementH - yMargin;
220 xMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconX;
221 extraXSpace = sW - (2 * pWS->pSD->iconPlacementMargin) -
222 (placementW - iSpaceX);
223 extraPX = (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) ?
224 1 : (pWS->IPData.placementCols - extraXSpace);
226 yMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconY;
227 extraYSpace = sH - (2 * pWS->pSD->iconPlacementMargin) -
228 (placementH - iSpaceY);
229 extraPY = (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) ?
230 1 : (pWS->IPData.placementRows - extraYSpace);
234 xMargin = (sW - placementW +
235 ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) & 1)) / 2;
237 yMargin = (sH - placementH +
238 ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) & 1))/ 2;
241 if (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
243 xMargin = sW - placementW - xMargin;
244 pWS->IPData.placeIconX = pWS->IPData.iPlaceW -
245 pWS->pSD->iconWidth -
246 pWS->IPData.placeIconX;
248 if (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY)
250 yMargin = sH - placementH - yMargin;
251 pWS->IPData.placeIconY = pWS->IPData.iPlaceH -
252 pWS->pSD->iconHeight -
253 pWS->IPData.placeIconY;
259 * Setup array of grid row positions and grid column positions:
262 if ((pWS->IPData.placementRowY =
263 (int *)XtMalloc ((pWS->IPData.placementRows+2) * sizeof (int)))
266 Warning (((char *)GETMESSAGE(34, 1, "Insufficient memory for icon placement")));
267 wmGD.iconAutoPlace = False;
270 else if ((pWS->IPData.placementColX =
271 (int *)XtMalloc ((pWS->IPData.placementCols+2) * sizeof (int)))
274 XtFree ((char *)pWS->IPData.placementRowY);
275 Warning (((char *)GETMESSAGE(34, 2, "Insufficient memory for icon placement")));
276 wmGD.iconAutoPlace = False;
280 pWS->IPData.placementRowY[0] = yMargin;
281 for (i = 1; i <= pWS->IPData.placementRows; i++)
283 pWS->IPData.placementRowY[i] = pWS->IPData.placementRowY[i - 1] +
285 if ((extraYSpace > 0) && (i >= extraPY))
287 (pWS->IPData.placementRowY[i])++;
292 pWS->IPData.placementColX[0] = xMargin;
293 for (i = 1; i <= pWS->IPData.placementCols; i++)
295 pWS->IPData.placementColX[i] = pWS->IPData.placementColX[i - 1] +
297 if ((extraXSpace > 0) && (i >= extraPX))
299 (pWS->IPData.placementColX[i])++;
306 * Setup an array of icon places.
309 pWS->IPData.totalPlaces =
310 pWS->IPData.placementRows * pWS->IPData.placementCols;
312 if ((pWS->IPData.placeList =
313 (IconInfo *)XtMalloc (pWS->IPData.totalPlaces * sizeof (IconInfo)))
316 Warning (((char *)GETMESSAGE(34, 3, "Insufficient memory for icon placement")));
317 XtFree ((char *)pWS->IPData.placementRowY);
318 XtFree ((char *)pWS->IPData.placementColX);
319 wmGD.iconAutoPlace = False;
323 memset ((char *)pWS->IPData.placeList, 0,
324 pWS->IPData.totalPlaces * sizeof (IconInfo));
326 pWS->IPData.onRootWindow = True;
329 } /* END OF FUNCTION InitIconPlacement */
333 /*************************************<->*************************************
335 * GetNextIconPlace (pIPD)
340 * This function identifies and returns the next free icon grid place.
345 * Return = next free place (index)
347 *************************************<->***********************************/
349 int GetNextIconPlace (IconPlacementData *pIPD)
354 for (i = 0; i < pIPD->totalPlaces; i++)
356 if (pIPD->placeList[i].pCD == (ClientData *)NULL)
363 * All places are filled! Find an alternative place.
366 return (NO_ICON_PLACE);
368 } /* END OF FUNCTION GetNextIconPlace */
372 /*************************************<->*************************************
374 * CvtIconPlaceToPosition (pIPD, place, pX, pY)
379 * This function converts an icon place (index) into an icon position.
384 * pIPD = ptr to icon placement data
386 * place = place to be converted
388 * wmGD = (iconPlacement ...)
393 * pX = pointer to icon place X location
395 * pY = pointer to icon place Y location
397 *************************************<->***********************************/
399 void CvtIconPlaceToPosition (IconPlacementData *pIPD, int place, int *pX, int *pY)
405 if (pIPD->iconPlacement &
406 (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY))
408 col = place % pIPD->placementCols;
409 row = place / pIPD->placementCols;
413 col = place / pIPD->placementRows;
414 row = place % pIPD->placementRows;
417 if (pIPD->iconPlacement &
418 (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY))
420 col = pIPD->placementCols - col - 1;
422 if (pIPD->iconPlacement &
423 (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY))
425 row = pIPD->placementRows - row - 1;
428 if (pIPD->onRootWindow)
430 *pX = pIPD->placementColX[col] + pIPD->placeIconX;
431 *pY = pIPD->placementRowY[row] + pIPD->placeIconY;
435 *pX = col * pIPD->iPlaceW;
436 *pY = row * pIPD->iPlaceH;
439 } /* END OF FUNCTION CvtIconPlaceToPosition */
443 /*************************************<->*************************************
445 * FindIconPlace (pCD, pIPD, x, y)
450 * This function is used to find a free icon place in the proximity of the
451 * specified position.
456 * pIPD = ptr to icon placement data
458 * x = desired x location of icon place
460 * y = desired y location of icon place
465 * Return = icon place (index)
470 * Look first for a free icon place at the position passed in. If that place
471 * is taken then look at positions that are +- one half the icon width/height
472 * from the postion passed in. If those positions are taken look at
473 * positions that are +- one half icon placement width/height from the
474 * position passed in.
476 *************************************<->***********************************/
478 int FindIconPlace (ClientData *pCD, IconPlacementData *pIPD, int x, int y)
490 place = CvtIconPositionToPlace (pIPD, x, y);
492 if (place < pIPD->totalPlaces)
494 if (pIPD->placeList[place].pCD == (ClientData *)NULL)
501 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
503 amt = pIPD->placementCols; /* add a new row */
507 amt = pIPD->placementRows; /* add a new column */
510 if (!ExtendIconList (P_ICON_BOX(pCD), amt))
512 Warning (((char *)GETMESSAGE(34, 4, "Insufficient memory to create icon box data")));
513 return (NO_ICON_PLACE);
517 * The place for the passed in position is in use, look at places for
518 * alternative positions.
521 for (i = 0; i < 2; i++)
527 diffX = ICON_WIDTH(pCD) / 2;
528 diffY = ICON_HEIGHT(pCD) / 2;
534 diffX = pIPD->iPlaceW / 2;
535 diffY = pIPD->iPlaceH / 2;
541 for (j = 0; j < 4; j++)
547 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
552 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
557 else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY)
572 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
577 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
582 else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY)
597 if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY)
602 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY)
607 else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY)
622 if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY)
627 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY)
632 else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY)
648 GetClipDimensions(pCD, False);
651 return (NO_ICON_PLACE);
655 return (NO_ICON_PLACE);
657 if (((int)altX) > ((int)clipX +
658 (int)clipWidth - ((int)ICON_WIDTH(pCD))))
660 return (NO_ICON_PLACE);
662 if (((int)altY) > ((int)clipY +
663 (int)clipHeight - ((int)ICON_HEIGHT(pCD))))
665 return (NO_ICON_PLACE);
669 place = CvtIconPositionToPlace (pIPD, altX, altY);
670 if ((pIPD->placeList[place].pCD) == NULL)
679 * Couldn't find an unoccupied place in the proximity of the passed-in
683 return (NO_ICON_PLACE);
686 } /* END OF FUNCTION FindIconPlace */
690 /*************************************<->*************************************
692 * CvtIconPostionToPlace (pIPD, x, y)
697 * This function converts an icon position to an icon place.
702 * pIPD = ptr to icon placement data
704 * x,y = location to be converted into an icon place
709 * Return = icon place (index)
711 *************************************<->***********************************/
713 int CvtIconPositionToPlace (IconPlacementData *pIPD, int x, int y)
719 if (pIPD->onRootWindow)
722 * Scan through the root window row/column arrays and find the
723 * placement position.
726 for (row = 1; row < pIPD->placementRows; row++)
728 if (y < pIPD->placementRowY[row])
735 for (col = 1; col < pIPD->placementCols; col++)
737 if (x < pIPD->placementColX[col])
745 if (pIPD->iconPlacement &
746 (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY))
748 col = pIPD->placementCols - col - 1;
750 if (pIPD->iconPlacement &
751 (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY))
753 row = pIPD->placementRows - row - 1;
759 * convert icon box coords
761 col = x / pIPD->iPlaceW;
762 row = y / pIPD->iPlaceH;
766 if (pIPD->iconPlacement &
767 (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY))
769 return ((row * pIPD->placementCols) + col);
773 return ((col * pIPD->placementRows) + row);
777 } /* END OF FUNCTION CvtIconPositionToPlace */
783 /*************************************<->*************************************
790 * This function packs the icons on the root window
802 *************************************<->***********************************/
804 void PackRootIcons (void)
808 ClientData *pCD_active;
809 int hasActiveText = 1;
815 * find context of the activeIconTextWin to get pCD and then
816 * if it is the same as this client, hide it.
819 if (XFindContext (DISPLAY, ACTIVE_PSD->activeIconTextWin,
820 wmGD.windowContextType, (caddr_t *)&pCD_active))
826 * Traverse the list and pack them together
829 if (wmGD.iconAutoPlace)
831 for (iOld = iNew = 0; iOld < ACTIVE_WS->IPData.totalPlaces;
834 if (ACTIVE_WS->IPData.placeList[iOld].pCD == NULL)
836 /* advance to next non-null entry */
837 while (++iOld < ACTIVE_WS->IPData.totalPlaces &&
838 !ACTIVE_WS->IPData.placeList[iOld].pCD)
842 if (iOld < ACTIVE_WS->IPData.totalPlaces && iOld != iNew)
844 /* move the icon from its old place to the new place */
846 MoveIconInfo (&ACTIVE_WS->IPData, iOld, iNew);
848 pCD = ACTIVE_WS->IPData.placeList[iNew].pCD;
850 pWsc = GetWsClientData (ACTIVE_WS, pCD);
851 pWsc->iconPlace = iNew;
852 CvtIconPlaceToPosition (&ACTIVE_WS->IPData,
853 pWsc->iconPlace, &pWsc->iconX, &pWsc->iconY);
855 pCD->iconPlace = iNew;
856 CvtIconPlaceToPosition (&ACTIVE_WS->IPData,
857 pCD->iconPlace, &pCD->iconX, &pCD->iconY);
860 if (hasActiveText && (pCD == pCD_active))
862 /* hide activeIconTextWin first */
863 HideActiveIconText ((WmScreenData *)NULL);
865 XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX,
868 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), pCD->iconX,
871 ShowActiveIconText (pCD);
876 XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX,
879 XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), pCD->iconX,
886 } /* END OF FUNCTION PackRootIcons */
890 /*************************************<->*************************************
892 * MoveIconInfo (pIPD, p1, p2)
897 * Move icon info from place 1 to place 2 in the placement list.
902 * pIPD - ptr to icon placement data
903 * p1 - placement index 1 (source)
904 * p2 - placement index 2 (destination)
912 *************************************<->***********************************/
914 void MoveIconInfo (IconPlacementData *pIPD, int p1, int p2)
920 /* only move if destination is empty */
921 if (pIPD->placeList[p2].pCD == NULL)
923 pIPD->placeList[p2].pCD = pIPD->placeList[p1].pCD;
924 pIPD->placeList[p2].theWidget = pIPD->placeList[p1].theWidget;
927 pWsc = GetWsClientData (pIPD->placeList[p2].pCD->pSD->pActiveWS,
928 pIPD->placeList[p2].pCD);
929 pWsc->iconPlace = p2;
931 pIPD->placeList[p2].pCD->iconPlace = p2;
934 pIPD->placeList[p1].pCD = NULL;
935 pIPD->placeList[p1].theWidget = NULL;
939 /**************************** eof ***************************/