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 libraries 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.
31 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
40 * include extern functions
45 #include "WmIconBox.h"
46 #include "WmWinConf.h"
47 #include "WmWrkspace.h"
51 * Function Declarations:
59 extern Dimension clipWidth;
60 extern Dimension clipHeight;
61 extern Position clipX;
62 extern Position clipY;
64 /*************************************<->*************************************
66 * InitIconPlacement ()
71 * This function intializes icon placement information.
76 * pWS = pointer to workspace data
83 *************************************<->***********************************/
85 void InitIconPlacement (WmWorkspaceData *pWS)
103 xMargin = yMargin = extraPX = extraPY = 0;
105 sW = DisplayWidth (DISPLAY, pWS->pSD->screen);
106 sH = DisplayHeight (DISPLAY, pWS->pSD->screen);
107 useMargin = (pWS->pSD->iconPlacementMargin >= 0);
108 pWS->IPData.iconPlacement = pWS->pSD->iconPlacement;
112 pWS->IPData.placementCols =
113 (sW - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconWidth;
114 pWS->IPData.placementRows =
115 (sH - (2 * pWS->pSD->iconPlacementMargin)) / pWS->pSD->iconHeight;
119 pWS->IPData.placementCols = sW / pWS->pSD->iconWidth;
120 pWS->IPData.placementRows = sH / pWS->pSD->iconHeight;
123 if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT)
137 (sW - (2 * pWS->pSD->iconPlacementMargin) -
138 (pWS->IPData.placementCols * pWS->pSD->iconWidth)) /
139 (pWS->IPData.placementCols - 1);
144 (sW - (pWS->IPData.placementCols * pWS->pSD->iconWidth)) /
145 pWS->IPData.placementCols;
147 if (iSpaceX < MINIMUM_ICON_SPACING)
149 pWS->IPData.placementCols--;
152 while (iSpaceX < MINIMUM_ICON_SPACING);
158 iSpaceY = (sH - (2 * pWS->pSD->iconPlacementMargin) -
159 (pWS->IPData.placementRows * pWS->pSD->iconHeight)) /
160 (pWS->IPData.placementRows - 1);
165 (sH - (pWS->IPData.placementRows * pWS->pSD->iconHeight)) /
166 pWS->IPData.placementRows;
168 if (iSpaceY < MINIMUM_ICON_SPACING)
170 pWS->IPData.placementRows--;
173 while (iSpaceY < MINIMUM_ICON_SPACING);
176 pWS->IPData.iPlaceW = pWS->pSD->iconWidth + iSpaceX;
177 pWS->IPData.iPlaceH = pWS->pSD->iconHeight + iSpaceY;
179 placementW = pWS->IPData.placementCols * pWS->IPData.iPlaceW;
180 placementH = pWS->IPData.placementRows * pWS->IPData.iPlaceH;
182 pWS->IPData.placeIconX =
183 ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) + 1) / 2;
184 pWS->IPData.placeIconY =
185 ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) + 1) / 2;
188 * Special case margin handling for TIGHT icon placement
190 if (pWS->IPData.iconPlacement & ICON_PLACE_TIGHT)
194 xMargin = pWS->pSD->iconPlacementMargin;
195 yMargin = pWS->pSD->iconPlacementMargin;
201 if ((pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) ||
202 (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_SECONDARY))
203 xMargin = sW - placementW - xMargin;
205 if ((pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) ||
206 (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_SECONDARY))
207 yMargin = sH - placementH - yMargin;
213 xMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconX;
214 extraXSpace = sW - (2 * pWS->pSD->iconPlacementMargin) -
215 (placementW - iSpaceX);
216 extraPX = (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY) ?
217 1 : (pWS->IPData.placementCols - extraXSpace);
219 yMargin = pWS->pSD->iconPlacementMargin - pWS->IPData.placeIconY;
220 extraYSpace = sH - (2 * pWS->pSD->iconPlacementMargin) -
221 (placementH - iSpaceY);
222 extraPY = (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY) ?
223 1 : (pWS->IPData.placementRows - extraYSpace);
227 xMargin = (sW - placementW +
228 ((pWS->IPData.iPlaceW - pWS->pSD->iconWidth) & 1)) / 2;
230 yMargin = (sH - placementH +
231 ((pWS->IPData.iPlaceH - pWS->pSD->iconHeight) & 1))/ 2;
234 if (pWS->IPData.iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
236 xMargin = sW - placementW - xMargin;
237 pWS->IPData.placeIconX = pWS->IPData.iPlaceW -
238 pWS->pSD->iconWidth -
239 pWS->IPData.placeIconX;
241 if (pWS->IPData.iconPlacement & ICON_PLACE_BOTTOM_PRIMARY)
243 yMargin = sH - placementH - yMargin;
244 pWS->IPData.placeIconY = pWS->IPData.iPlaceH -
245 pWS->pSD->iconHeight -
246 pWS->IPData.placeIconY;
252 * Setup array of grid row positions and grid column positions:
255 if ((pWS->IPData.placementRowY =
256 (int *)XtMalloc ((pWS->IPData.placementRows+2) * sizeof (int)))
259 Warning (((char *)GETMESSAGE(34, 1, "Insufficient memory for icon placement")));
260 wmGD.iconAutoPlace = False;
263 else if ((pWS->IPData.placementColX =
264 (int *)XtMalloc ((pWS->IPData.placementCols+2) * sizeof (int)))
267 XtFree ((char *)pWS->IPData.placementRowY);
268 Warning (((char *)GETMESSAGE(34, 2, "Insufficient memory for icon placement")));
269 wmGD.iconAutoPlace = False;
273 pWS->IPData.placementRowY[0] = yMargin;
274 for (i = 1; i <= pWS->IPData.placementRows; i++)
276 pWS->IPData.placementRowY[i] = pWS->IPData.placementRowY[i - 1] +
278 if ((extraYSpace > 0) && (i >= extraPY))
280 (pWS->IPData.placementRowY[i])++;
285 pWS->IPData.placementColX[0] = xMargin;
286 for (i = 1; i <= pWS->IPData.placementCols; i++)
288 pWS->IPData.placementColX[i] = pWS->IPData.placementColX[i - 1] +
290 if ((extraXSpace > 0) && (i >= extraPX))
292 (pWS->IPData.placementColX[i])++;
299 * Setup an array of icon places.
302 pWS->IPData.totalPlaces =
303 pWS->IPData.placementRows * pWS->IPData.placementCols;
305 if ((pWS->IPData.placeList =
306 (IconInfo *)XtMalloc (pWS->IPData.totalPlaces * sizeof (IconInfo)))
309 Warning (((char *)GETMESSAGE(34, 3, "Insufficient memory for icon placement")));
310 XtFree ((char *)pWS->IPData.placementRowY);
311 XtFree ((char *)pWS->IPData.placementColX);
312 wmGD.iconAutoPlace = False;
316 memset ((char *)pWS->IPData.placeList, 0,
317 pWS->IPData.totalPlaces * sizeof (IconInfo));
319 pWS->IPData.onRootWindow = True;
322 } /* END OF FUNCTION InitIconPlacement */
326 /*************************************<->*************************************
328 * GetNextIconPlace (pIPD)
333 * This function identifies and returns the next free icon grid place.
338 * Return = next free place (index)
340 *************************************<->***********************************/
342 int GetNextIconPlace (IconPlacementData *pIPD)
347 for (i = 0; i < pIPD->totalPlaces; i++)
349 if (pIPD->placeList[i].pCD == (ClientData *)NULL)
356 * All places are filled! Find an alternative place.
359 return (NO_ICON_PLACE);
361 } /* END OF FUNCTION GetNextIconPlace */
365 /*************************************<->*************************************
367 * CvtIconPlaceToPosition (pIPD, place, pX, pY)
372 * This function converts an icon place (index) into an icon position.
377 * pIPD = ptr to icon placement data
379 * place = place to be converted
381 * wmGD = (iconPlacement ...)
386 * pX = pointer to icon place X location
388 * pY = pointer to icon place Y location
390 *************************************<->***********************************/
392 void CvtIconPlaceToPosition (IconPlacementData *pIPD, int place, int *pX, int *pY)
398 if (pIPD->iconPlacement &
399 (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY))
401 col = place % pIPD->placementCols;
402 row = place / pIPD->placementCols;
406 col = place / pIPD->placementRows;
407 row = place % pIPD->placementRows;
410 if (pIPD->iconPlacement &
411 (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY))
413 col = pIPD->placementCols - col - 1;
415 if (pIPD->iconPlacement &
416 (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY))
418 row = pIPD->placementRows - row - 1;
421 if (pIPD->onRootWindow)
423 *pX = pIPD->placementColX[col] + pIPD->placeIconX;
424 *pY = pIPD->placementRowY[row] + pIPD->placeIconY;
428 *pX = col * pIPD->iPlaceW;
429 *pY = row * pIPD->iPlaceH;
432 } /* END OF FUNCTION CvtIconPlaceToPosition */
436 /*************************************<->*************************************
438 * FindIconPlace (pCD, pIPD, x, y)
443 * This function is used to find a free icon place in the proximity of the
444 * specified position.
449 * pIPD = ptr to icon placement data
451 * x = desired x location of icon place
453 * y = desired y location of icon place
458 * Return = icon place (index)
463 * Look first for a free icon place at the position passed in. If that place
464 * is taken then look at positions that are +- one half the icon width/height
465 * from the postion passed in. If those positions are taken look at
466 * positions that are +- one half icon placement width/height from the
467 * position passed in.
469 *************************************<->***********************************/
471 int FindIconPlace (ClientData *pCD, IconPlacementData *pIPD, int x, int y)
483 place = CvtIconPositionToPlace (pIPD, x, y);
485 if (place < pIPD->totalPlaces)
487 if (pIPD->placeList[place].pCD == (ClientData *)NULL)
494 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
496 amt = pIPD->placementCols; /* add a new row */
500 amt = pIPD->placementRows; /* add a new column */
503 if (!ExtendIconList (P_ICON_BOX(pCD), amt))
505 Warning (((char *)GETMESSAGE(34, 4, "Insufficient memory to create icon box data")));
506 return (NO_ICON_PLACE);
510 * The place for the passed in position is in use, look at places for
511 * alternative positions.
514 for (i = 0; i < 2; i++)
520 diffX = ICON_WIDTH(pCD) / 2;
521 diffY = ICON_HEIGHT(pCD) / 2;
527 diffX = pIPD->iPlaceW / 2;
528 diffY = pIPD->iPlaceH / 2;
534 for (j = 0; j < 4; j++)
540 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
545 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
550 else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY)
565 if (pIPD->iconPlacement & ICON_PLACE_LEFT_PRIMARY)
570 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_PRIMARY)
575 else if (pIPD->iconPlacement & ICON_PLACE_TOP_PRIMARY)
590 if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY)
595 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY)
600 else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY)
615 if (pIPD->iconPlacement & ICON_PLACE_LEFT_SECONDARY)
620 else if (pIPD->iconPlacement & ICON_PLACE_RIGHT_SECONDARY)
625 else if (pIPD->iconPlacement & ICON_PLACE_TOP_SECONDARY)
641 GetClipDimensions(pCD, False);
644 return (NO_ICON_PLACE);
648 return (NO_ICON_PLACE);
650 if (((int)altX) > ((int)clipX +
651 (int)clipWidth - ((int)ICON_WIDTH(pCD))))
653 return (NO_ICON_PLACE);
655 if (((int)altY) > ((int)clipY +
656 (int)clipHeight - ((int)ICON_HEIGHT(pCD))))
658 return (NO_ICON_PLACE);
662 place = CvtIconPositionToPlace (pIPD, altX, altY);
663 if ((pIPD->placeList[place].pCD) == NULL)
672 * Couldn't find an unoccupied place in the proximity of the passed-in
676 return (NO_ICON_PLACE);
679 } /* END OF FUNCTION FindIconPlace */
683 /*************************************<->*************************************
685 * CvtIconPostionToPlace (pIPD, x, y)
690 * This function converts an icon position to an icon place.
695 * pIPD = ptr to icon placement data
697 * x,y = location to be converted into an icon place
702 * Return = icon place (index)
704 *************************************<->***********************************/
706 int CvtIconPositionToPlace (IconPlacementData *pIPD, int x, int y)
712 if (pIPD->onRootWindow)
715 * Scan through the root window row/column arrays and find the
716 * placement position.
719 for (row = 1; row < pIPD->placementRows; row++)
721 if (y < pIPD->placementRowY[row])
728 for (col = 1; col < pIPD->placementCols; col++)
730 if (x < pIPD->placementColX[col])
738 if (pIPD->iconPlacement &
739 (ICON_PLACE_RIGHT_PRIMARY | ICON_PLACE_RIGHT_SECONDARY))
741 col = pIPD->placementCols - col - 1;
743 if (pIPD->iconPlacement &
744 (ICON_PLACE_BOTTOM_PRIMARY | ICON_PLACE_BOTTOM_SECONDARY))
746 row = pIPD->placementRows - row - 1;
752 * convert icon box coords
754 col = x / pIPD->iPlaceW;
755 row = y / pIPD->iPlaceH;
759 if (pIPD->iconPlacement &
760 (ICON_PLACE_LEFT_PRIMARY | ICON_PLACE_RIGHT_PRIMARY))
762 return ((row * pIPD->placementCols) + col);
766 return ((col * pIPD->placementRows) + row);
770 } /* END OF FUNCTION CvtIconPositionToPlace */
776 /*************************************<->*************************************
783 * This function packs the icons on the root window
795 *************************************<->***********************************/
797 void PackRootIcons (void)
801 ClientData *pCD_active;
802 int hasActiveText = 1;
806 * find context of the activeIconTextWin to get pCD and then
807 * if it is the same as this client, hide it.
810 if (XFindContext (DISPLAY, ACTIVE_PSD->activeIconTextWin,
811 wmGD.windowContextType, (caddr_t *)&pCD_active))
817 * Traverse the list and pack them together
820 if (wmGD.iconAutoPlace)
822 for (iOld = iNew = 0; iOld < ACTIVE_WS->IPData.totalPlaces;
825 if (ACTIVE_WS->IPData.placeList[iOld].pCD == NULL)
827 /* advance to next non-null entry */
828 while (++iOld < ACTIVE_WS->IPData.totalPlaces &&
829 !ACTIVE_WS->IPData.placeList[iOld].pCD)
833 if (iOld < ACTIVE_WS->IPData.totalPlaces && iOld != iNew)
835 /* move the icon from its old place to the new place */
837 MoveIconInfo (&ACTIVE_WS->IPData, iOld, iNew);
839 pCD = ACTIVE_WS->IPData.placeList[iNew].pCD;
840 pWsc = GetWsClientData (ACTIVE_WS, pCD);
841 pWsc->iconPlace = iNew;
842 CvtIconPlaceToPosition (&ACTIVE_WS->IPData,
843 pWsc->iconPlace, &pWsc->iconX, &pWsc->iconY);
845 if (hasActiveText && (pCD == pCD_active))
847 /* hide activeIconTextWin first */
848 HideActiveIconText ((WmScreenData *)NULL);
849 XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX,
851 ShowActiveIconText (pCD);
855 XMoveWindow (DISPLAY, pWsc->iconFrameWin, pWsc->iconX,
861 } /* END OF FUNCTION PackRootIcons */
865 /*************************************<->*************************************
867 * MoveIconInfo (pIPD, p1, p2)
872 * Move icon info from place 1 to place 2 in the placement list.
877 * pIPD - ptr to icon placement data
878 * p1 - placement index 1 (source)
879 * p2 - placement index 2 (destination)
887 *************************************<->***********************************/
889 void MoveIconInfo (IconPlacementData *pIPD, int p1, int p2)
893 /* only move if destination is empty */
894 if (pIPD->placeList[p2].pCD == NULL)
896 pIPD->placeList[p2].pCD = pIPD->placeList[p1].pCD;
897 pIPD->placeList[p2].theWidget = pIPD->placeList[p1].theWidget;
899 pWsc = GetWsClientData (pIPD->placeList[p2].pCD->pSD->pActiveWS,
900 pIPD->placeList[p2].pCD);
901 pWsc->iconPlace = p2;
903 pIPD->placeList[p1].pCD = NULL;
904 pIPD->placeList[p1].theWidget = NULL;
908 /**************************** eof ***************************/