13e747e6dSmrg/* 2ffd25bcaSmrg * 33e747e6dSmrgCopyright 1989,1998 The Open Group 43e747e6dSmrg 53e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its 63e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that 73e747e6dSmrgthe above copyright notice appear in all copies and that both that 83e747e6dSmrgcopyright notice and this permission notice appear in supporting 93e747e6dSmrgdocumentation. 103e747e6dSmrg 113e747e6dSmrgThe above copyright notice and this permission notice shall be included in 123e747e6dSmrgall copies or substantial portions of the Software. 133e747e6dSmrg 143e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 153e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 163e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 173e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 183e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 193e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 203e747e6dSmrg 213e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be 223e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings 233e747e6dSmrgin this Software without prior written authorization from The Open Group. 243e747e6dSmrg * */ 253e747e6dSmrg 263e747e6dSmrg/*********************************************************************** 273e747e6dSmrg * 283e747e6dSmrg * Icon Manager routines 293e747e6dSmrg * 30f66df612Smrg * 09-Mar-89 Tom LaStrange File Created 313e747e6dSmrg * 323e747e6dSmrg ***********************************************************************/ 333e747e6dSmrg 343e747e6dSmrg#include <stdio.h> 353e747e6dSmrg#include "twm.h" 363e747e6dSmrg#include "util.h" 373e747e6dSmrg#include "parse.h" 383e747e6dSmrg#include "screen.h" 393e747e6dSmrg#include "resize.h" 403e747e6dSmrg#include "add_window.h" 413e747e6dSmrg#include "siconify.bm" 423e747e6dSmrg#include <X11/Xos.h> 433e747e6dSmrg#include <X11/Xmu/CharSet.h> 44c2535118Smrg 45f66df612Smrgstatic void InsertInIconManager(IconMgr *ip, WList *tmp, TwmWindow *tmp_win); 463e747e6dSmrg 47f66df612Smrgint iconmgr_textx = siconify_width + 11; 48c2535118Smrgstatic WList *Active = NULL; 493e747e6dSmrgWList *DownIconManager = NULL; 503e747e6dSmrgint iconifybox_width = siconify_width; 513e747e6dSmrgint iconifybox_height = siconify_height; 523e747e6dSmrg 533e747e6dSmrg/** 543e747e6dSmrg * create all the icon manager windows for this screen. 553e747e6dSmrg */ 56c2535118Smrgvoid 57c2535118SmrgCreateIconManagers(void) 583e747e6dSmrg{ 593e747e6dSmrg IconMgr *p; 603e747e6dSmrg char str[100]; 613e747e6dSmrg char str1[100]; 623e747e6dSmrg Pixel background; 63f66df612Smrg const char *icon_name; 643e747e6dSmrg 653e747e6dSmrg if (Scr->NoIconManagers) 66f66df612Smrg return; 673e747e6dSmrg 68f66df612Smrg if (Scr->siconifyPm == None) { 69f66df612Smrg Scr->siconifyPm = XCreatePixmapFromBitmapData(dpy, Scr->Root, 70f66df612Smrg (char *) siconify_bits, 71f66df612Smrg siconify_width, 72f66df612Smrg siconify_height, 1, 0, 1); 733e747e6dSmrg } 743e747e6dSmrg 75f66df612Smrg for (p = &Scr->iconmgr; p != NULL; p = p->next) { 766d8e82c3Smrg int x = 0; 776d8e82c3Smrg int y = 0; 786d8e82c3Smrg int mask = XParseGeometry(p->geometry, &x, &y, 79f66df612Smrg (unsigned int *) &p->width, 80f66df612Smrg (unsigned int *) &p->height); 813e747e6dSmrg 82f66df612Smrg if (mask & XNegative) 836d8e82c3Smrg x += Scr->MyDisplayWidth - p->width - (2 * Scr->BorderWidth); 843e747e6dSmrg 85f66df612Smrg if (mask & YNegative) 866d8e82c3Smrg y += Scr->MyDisplayHeight - p->height - (2 * Scr->BorderWidth); 873e747e6dSmrg 88f66df612Smrg background = Scr->IconManagerC.back; 89f66df612Smrg GetColorFromList(Scr->IconManagerBL, p->name, (XClassHint *) NULL, 90f66df612Smrg &background); 913e747e6dSmrg 926d8e82c3Smrg p->w = XCreateSimpleWindow(dpy, Scr->Root, x, y, 936d8e82c3Smrg (unsigned) p->width, (unsigned) p->height, 946d8e82c3Smrg 1, Scr->Black, background); 953e747e6dSmrg 96f66df612Smrg snprintf(str, sizeof(str), "%s Icon Manager", p->name); 97f66df612Smrg snprintf(str1, sizeof(str1), "%s Icons", p->name); 98f66df612Smrg if (p->icon_name) 99f66df612Smrg icon_name = p->icon_name; 100f66df612Smrg else 101f66df612Smrg icon_name = str1; 1023e747e6dSmrg 103f66df612Smrg XSetStandardProperties(dpy, p->w, str, icon_name, None, NULL, 0, NULL); 1043e747e6dSmrg 105f66df612Smrg p->twm_win = AddWindow(p->w, TRUE, p); 106f66df612Smrg SetMapStateProp(p->twm_win, WithdrawnState); 1073e747e6dSmrg } 108f66df612Smrg for (p = &Scr->iconmgr; p != NULL; p = p->next) { 109f66df612Smrg GrabButtons(p->twm_win); 110f66df612Smrg GrabKeys(p->twm_win); 1113e747e6dSmrg } 1123e747e6dSmrg} 1133e747e6dSmrg 1143e747e6dSmrg/** 1153e747e6dSmrg * allocate a new icon manager 1163e747e6dSmrg * 1173e747e6dSmrg * \param name the name of this icon manager 1183e747e6dSmrg * \param con_name the name of the associated icon 119f66df612Smrg * \param geom a geometry string to eventually parse 120f66df612Smrg * \param columns the number of columns this icon manager has 1213e747e6dSmrg */ 122f66df612SmrgIconMgr * 123f66df612SmrgAllocateIconManager(char *name, char *icon_name, char *geom, int columns) 1243e747e6dSmrg{ 1253e747e6dSmrg IconMgr *p; 1263e747e6dSmrg 1273e747e6dSmrg#ifdef DEBUG_ICONMGR 1283e747e6dSmrg fprintf(stderr, "AllocateIconManager\n"); 1293e747e6dSmrg fprintf(stderr, " name=\"%s\" icon_name=\"%s\", geom=\"%s\", col=%d\n", 130f66df612Smrg name, icon_name ? icon_name : "<null>", geom, columns); 1313e747e6dSmrg#endif 1323e747e6dSmrg 1333e747e6dSmrg if (Scr->NoIconManagers) 134f66df612Smrg return NULL; 1353e747e6dSmrg 1366d8e82c3Smrg p = (IconMgr *) malloc(sizeof(IconMgr)); 1373e747e6dSmrg p->name = name; 1383e747e6dSmrg p->icon_name = icon_name; 1393e747e6dSmrg p->geometry = geom; 1403e747e6dSmrg p->columns = columns; 1413e747e6dSmrg p->first = NULL; 1423e747e6dSmrg p->last = NULL; 1433e747e6dSmrg p->active = NULL; 1443e747e6dSmrg p->scr = Scr; 1453e747e6dSmrg p->count = 0; 1463e747e6dSmrg p->x = 0; 1473e747e6dSmrg p->y = 0; 1483e747e6dSmrg p->width = 150; 1493e747e6dSmrg p->height = 10; 1503e747e6dSmrg 1513e747e6dSmrg Scr->iconmgr.lasti->next = p; 1523e747e6dSmrg p->prev = Scr->iconmgr.lasti; 1533e747e6dSmrg Scr->iconmgr.lasti = p; 1543e747e6dSmrg p->next = NULL; 1553e747e6dSmrg 156f66df612Smrg return (p); 1573e747e6dSmrg} 1583e747e6dSmrg 1593e747e6dSmrg/** 1603e747e6dSmrg * move the pointer around in an icon manager 1613e747e6dSmrg * 1623e747e6dSmrg * \param dir one of the following: 1633e747e6dSmrg * - F_FORWICONMGR: forward in the window list 1643e747e6dSmrg * - F_BACKICONMGR: backward in the window list 1653e747e6dSmrg * - F_UPICONMGR: up one row 1663e747e6dSmrg * - F_DOWNICONMG: down one row 1673e747e6dSmrg * - F_LEFTICONMGR: left one column 1683e747e6dSmrg * - F_RIGHTICONMGR: right one column 1693e747e6dSmrg */ 170f66df612Smrgvoid 171f66df612SmrgMoveIconManager(int dir) 1723e747e6dSmrg{ 1733e747e6dSmrg IconMgr *ip; 1743e747e6dSmrg WList *tmp = NULL; 1753e747e6dSmrg int cur_row, cur_col, new_row, new_col; 1763e747e6dSmrg int row_inc, col_inc; 1773e747e6dSmrg int got_it; 1783e747e6dSmrg 179f66df612Smrg if (!Active) 180f66df612Smrg return; 1813e747e6dSmrg 1823e747e6dSmrg cur_row = Active->row; 1833e747e6dSmrg cur_col = Active->col; 1843e747e6dSmrg ip = Active->iconmgr; 1853e747e6dSmrg 1863e747e6dSmrg row_inc = 0; 1873e747e6dSmrg col_inc = 0; 1883e747e6dSmrg got_it = FALSE; 1893e747e6dSmrg 190f66df612Smrg switch (dir) { 191f66df612Smrg case F_FORWICONMGR: 192f66df612Smrg if ((tmp = Active->next) == NULL) 193f66df612Smrg tmp = ip->first; 194f66df612Smrg got_it = TRUE; 195f66df612Smrg break; 196f66df612Smrg 197f66df612Smrg case F_BACKICONMGR: 198f66df612Smrg if ((tmp = Active->prev) == NULL) 199f66df612Smrg tmp = ip->last; 200f66df612Smrg got_it = TRUE; 201f66df612Smrg break; 202f66df612Smrg 203f66df612Smrg case F_UPICONMGR: 204f66df612Smrg row_inc = -1; 205f66df612Smrg break; 206f66df612Smrg 207f66df612Smrg case F_DOWNICONMGR: 208f66df612Smrg row_inc = 1; 209f66df612Smrg break; 210f66df612Smrg 211f66df612Smrg case F_LEFTICONMGR: 212f66df612Smrg col_inc = -1; 213f66df612Smrg break; 214f66df612Smrg 215f66df612Smrg case F_RIGHTICONMGR: 216f66df612Smrg col_inc = 1; 217f66df612Smrg break; 2183e747e6dSmrg } 2193e747e6dSmrg 2203e747e6dSmrg /* If got_it is FALSE ast this point then we got a left, right, 2213e747e6dSmrg * up, or down, command. We will enter this loop until we find 2223e747e6dSmrg * a window to warp to. 2233e747e6dSmrg */ 2243e747e6dSmrg new_row = cur_row; 2253e747e6dSmrg new_col = cur_col; 2263e747e6dSmrg 227f66df612Smrg while (!got_it) { 228f66df612Smrg new_row += row_inc; 229f66df612Smrg new_col += col_inc; 230f66df612Smrg if (new_row < 0) 231f66df612Smrg new_row = ip->cur_rows - 1; 232f66df612Smrg if (new_col < 0) 233f66df612Smrg new_col = ip->cur_columns - 1; 234f66df612Smrg if (new_row >= ip->cur_rows) 235f66df612Smrg new_row = 0; 236f66df612Smrg if (new_col >= ip->cur_columns) 237f66df612Smrg new_col = 0; 238f66df612Smrg 239f66df612Smrg /* Now let's go through the list to see if there is an entry with this 240f66df612Smrg * new position 241f66df612Smrg */ 242f66df612Smrg for (tmp = ip->first; tmp != NULL; tmp = tmp->next) { 243f66df612Smrg if (tmp->row == new_row && tmp->col == new_col) { 244f66df612Smrg got_it = TRUE; 245f66df612Smrg break; 246f66df612Smrg } 247f66df612Smrg } 2483e747e6dSmrg } 2493e747e6dSmrg 250f66df612Smrg if (!got_it) { 251f66df612Smrg twmWarning("unable to find window (%d, %d) in icon manager", 252f66df612Smrg new_row, new_col); 253f66df612Smrg return; 2543e747e6dSmrg } 2553e747e6dSmrg 2563e747e6dSmrg if (tmp == NULL) 257f66df612Smrg return; 2583e747e6dSmrg 2593e747e6dSmrg /* raise the frame so the icon manager is visible */ 2603e747e6dSmrg if (ip->twm_win->mapped) { 261f66df612Smrg XRaiseWindow(dpy, ip->twm_win->frame); 262f66df612Smrg XWarpPointer(dpy, None, tmp->icon, 0, 0, 0, 0, 5, 5); 263f66df612Smrg } 264f66df612Smrg else { 265f66df612Smrg if (tmp->twm->title_height) { 266f66df612Smrg int tbx = Scr->TBInfo.titlex; 267f66df612Smrg int x = tmp->twm->highlightx; 268f66df612Smrg 269f66df612Smrg XWarpPointer(dpy, None, tmp->twm->title_w, 0, 0, 0, 0, 270f66df612Smrg tbx + (x - tbx) / 2, Scr->TitleHeight / 4); 271f66df612Smrg } 272f66df612Smrg else { 273f66df612Smrg XWarpPointer(dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5); 274f66df612Smrg } 2753e747e6dSmrg } 2763e747e6dSmrg} 2773e747e6dSmrg 2783e747e6dSmrg/** 2793e747e6dSmrg * jump from one icon manager to another, possibly even on another screen 2803e747e6dSmrg * \param dir one of the following: 281ffd25bcaSmrg * - F_NEXTICONMGR - go to the next icon manager 2823e747e6dSmrg * - F_PREVICONMGR - go to the previous one 2833e747e6dSmrg */ 2843e747e6dSmrg 285f66df612Smrgvoid 286f66df612SmrgJumpIconManager(int dir) 2873e747e6dSmrg{ 2883e747e6dSmrg IconMgr *ip, *tmp_ip = NULL; 2893e747e6dSmrg int got_it = FALSE; 2903e747e6dSmrg 291f66df612Smrg if (!Active) 292f66df612Smrg return; 2933e747e6dSmrg 2943e747e6dSmrg#define ITER(i) (dir == F_NEXTICONMGR ? (i)->next : (i)->prev) 2953e747e6dSmrg#define IPOFSP(sp) (dir == F_NEXTICONMGR ? &(sp->iconmgr) : sp->iconmgr.lasti) 2963e747e6dSmrg#define TEST(ip) if ((ip)->count != 0 && (ip)->twm_win->mapped) \ 297f66df612Smrg { got_it = TRUE; break; } 2983e747e6dSmrg 2993e747e6dSmrg ip = Active->iconmgr; 3003e747e6dSmrg for (tmp_ip = ITER(ip); tmp_ip; tmp_ip = ITER(tmp_ip)) { 301f66df612Smrg TEST(tmp_ip); 3023e747e6dSmrg } 3033e747e6dSmrg 3043e747e6dSmrg if (!got_it) { 305f66df612Smrg int origscreen = ip->scr->screen; 306f66df612Smrg int inc = (dir == F_NEXTICONMGR ? 1 : -1); 307f66df612Smrg int screen; 308f66df612Smrg 309f66df612Smrg for (screen = origscreen + inc;; screen += inc) { 310f66df612Smrg ScreenInfo *sp; 311f66df612Smrg 312f66df612Smrg if (screen >= NumScreens) 313f66df612Smrg screen = 0; 314f66df612Smrg else if (screen < 0) 315f66df612Smrg screen = NumScreens - 1; 316f66df612Smrg 317f66df612Smrg sp = ScreenList[screen]; 318f66df612Smrg if (sp) { 319f66df612Smrg for (tmp_ip = IPOFSP(sp); tmp_ip; tmp_ip = ITER(tmp_ip)) { 320f66df612Smrg TEST(tmp_ip); 321f66df612Smrg } 322f66df612Smrg } 323f66df612Smrg if (got_it || screen == origscreen) 324f66df612Smrg break; 325f66df612Smrg } 3263e747e6dSmrg } 3273e747e6dSmrg 3283e747e6dSmrg#undef ITER 3293e747e6dSmrg#undef IPOFSP 3303e747e6dSmrg#undef TEST 3313e747e6dSmrg 3323e747e6dSmrg if (!got_it) { 333f66df612Smrg Bell(XkbBI_MinorError, 0, None); 334f66df612Smrg return; 3353e747e6dSmrg } 3363e747e6dSmrg 3373e747e6dSmrg /* raise the frame so it is visible */ 3383e747e6dSmrg XRaiseWindow(dpy, tmp_ip->twm_win->frame); 3393e747e6dSmrg if (tmp_ip->active) 340f66df612Smrg XWarpPointer(dpy, None, tmp_ip->active->icon, 0, 0, 0, 0, 5, 5); 3413e747e6dSmrg else 342f66df612Smrg XWarpPointer(dpy, None, tmp_ip->w, 0, 0, 0, 0, 5, 5); 3433e747e6dSmrg} 3443e747e6dSmrg 3453e747e6dSmrg/** 3463e747e6dSmrg * add a window to an icon manager 3473e747e6dSmrg * 3483e747e6dSmrg * \param tmp_win the TwmWindow structure 3493e747e6dSmrg */ 350f66df612SmrgWList * 351f66df612SmrgAddIconManager(TwmWindow *tmp_win) 3523e747e6dSmrg{ 3533e747e6dSmrg WList *tmp; 3543e747e6dSmrg int h; 355f66df612Smrg unsigned long valuemask; /* mask for create windows */ 356f66df612Smrg XSetWindowAttributes attributes; /* attributes for create windows */ 3573e747e6dSmrg IconMgr *ip; 3583e747e6dSmrg 3593e747e6dSmrg tmp_win->list = NULL; 3603e747e6dSmrg 3613e747e6dSmrg if (tmp_win->iconmgr || tmp_win->transient || Scr->NoIconManagers) 362f66df612Smrg return NULL; 3633e747e6dSmrg 3646d8e82c3Smrg if (LookInList(Scr->IconMgrNoShow, tmp_win->full_name, &tmp_win->xclass)) 365f66df612Smrg return NULL; 3663e747e6dSmrg if (Scr->IconManagerDontShow && 3676d8e82c3Smrg !LookInList(Scr->IconMgrShow, tmp_win->full_name, &tmp_win->xclass)) 368f66df612Smrg return NULL; 369f66df612Smrg if ((ip = (IconMgr *) LookInList(Scr->IconMgrs, tmp_win->full_name, 3706d8e82c3Smrg &tmp_win->xclass)) == NULL) 371f66df612Smrg ip = &Scr->iconmgr; 3723e747e6dSmrg 3736d8e82c3Smrg tmp = (WList *) malloc(sizeof(WList)); 3743e747e6dSmrg tmp->iconmgr = ip; 3753e747e6dSmrg tmp->next = NULL; 3763e747e6dSmrg tmp->active = FALSE; 3773e747e6dSmrg tmp->down = FALSE; 3783e747e6dSmrg 3793e747e6dSmrg InsertInIconManager(ip, tmp, tmp_win); 3803e747e6dSmrg 3813e747e6dSmrg tmp->twm = tmp_win; 3823e747e6dSmrg 3833e747e6dSmrg tmp->fore = Scr->IconManagerC.fore; 3843e747e6dSmrg tmp->back = Scr->IconManagerC.back; 3853e747e6dSmrg tmp->highlight = Scr->IconManagerHighlight; 3863e747e6dSmrg 3876d8e82c3Smrg GetColorFromList(Scr->IconManagerFL, tmp_win->full_name, &tmp_win->xclass, 388f66df612Smrg &tmp->fore); 3896d8e82c3Smrg GetColorFromList(Scr->IconManagerBL, tmp_win->full_name, &tmp_win->xclass, 390f66df612Smrg &tmp->back); 3913e747e6dSmrg GetColorFromList(Scr->IconManagerHighlightL, tmp_win->full_name, 3926d8e82c3Smrg &tmp_win->xclass, &tmp->highlight); 3933e747e6dSmrg 3943e747e6dSmrg h = Scr->IconManagerFont.height + 10; 3953e747e6dSmrg if (h < (siconify_height + 4)) 396f66df612Smrg h = siconify_height + 4; 3973e747e6dSmrg 3983e747e6dSmrg ip->height = h * ip->count; 3993e747e6dSmrg tmp->me = ip->count; 4003e747e6dSmrg tmp->x = -1; 4013e747e6dSmrg tmp->y = -1; 402ffd25bcaSmrg 4033e747e6dSmrg valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); 4043e747e6dSmrg attributes.background_pixel = tmp->back; 4053e747e6dSmrg attributes.border_pixel = tmp->back; 4063e747e6dSmrg attributes.event_mask = (KeyPressMask | ButtonPressMask | 407f66df612Smrg ButtonReleaseMask | ExposureMask | 408f66df612Smrg EnterWindowMask | LeaveWindowMask); 4093e747e6dSmrg attributes.cursor = Scr->IconMgrCursor; 410f66df612Smrg tmp->w = XCreateWindow(dpy, ip->w, 0, 0, (unsigned int) 1, 411f66df612Smrg (unsigned int) h, (unsigned int) 0, 412f66df612Smrg CopyFromParent, (unsigned int) CopyFromParent, 413f66df612Smrg (Visual *) CopyFromParent, valuemask, &attributes); 4143e747e6dSmrg 4153e747e6dSmrg valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); 4163e747e6dSmrg attributes.background_pixel = tmp->back; 4173e747e6dSmrg attributes.border_pixel = Scr->Black; 418f66df612Smrg attributes.event_mask = (ButtonReleaseMask | ButtonPressMask | 419f66df612Smrg ExposureMask); 4203e747e6dSmrg attributes.cursor = Scr->ButtonCursor; 421f66df612Smrg tmp->icon = XCreateWindow(dpy, tmp->w, 5, (int) (h - siconify_height) / 2, 422f66df612Smrg (unsigned int) siconify_width, 423f66df612Smrg (unsigned int) siconify_height, 424f66df612Smrg (unsigned int) 0, CopyFromParent, 425f66df612Smrg (unsigned int) CopyFromParent, 426f66df612Smrg (Visual *) CopyFromParent, 427f66df612Smrg valuemask, &attributes); 4283e747e6dSmrg 4293e747e6dSmrg ip->count += 1; 4303e747e6dSmrg PackIconManager(ip); 4313e747e6dSmrg XMapWindow(dpy, tmp->w); 4323e747e6dSmrg 433f66df612Smrg XSaveContext(dpy, tmp->w, IconManagerContext, (XPointer) tmp); 434f66df612Smrg XSaveContext(dpy, tmp->w, TwmContext, (XPointer) tmp_win); 435f66df612Smrg XSaveContext(dpy, tmp->w, ScreenContext, (XPointer) Scr); 436f66df612Smrg XSaveContext(dpy, tmp->icon, TwmContext, (XPointer) tmp_win); 437f66df612Smrg XSaveContext(dpy, tmp->icon, ScreenContext, (XPointer) Scr); 4383e747e6dSmrg tmp_win->list = tmp; 4393e747e6dSmrg 440f66df612Smrg if (!ip->twm_win->icon) { 441f66df612Smrg XMapWindow(dpy, ip->w); 442f66df612Smrg XMapWindow(dpy, ip->twm_win->frame); 4433e747e6dSmrg } 4443e747e6dSmrg 445f66df612Smrg if (Active == NULL) 446f66df612Smrg Active = tmp; 4473e747e6dSmrg 4483e747e6dSmrg return (tmp); 4493e747e6dSmrg} 4503e747e6dSmrg 4513e747e6dSmrg/** 4523e747e6dSmrg * put an allocated entry into an icon manager 4533e747e6dSmrg * 4543e747e6dSmrg * \param ip the icon manager pointer 4553e747e6dSmrg * \param tmp the entry to insert 4563e747e6dSmrg */ 457f66df612Smrgstatic void 458f66df612SmrgInsertInIconManager(IconMgr *ip, WList *tmp, TwmWindow *tmp_win) 4593e747e6dSmrg{ 4603e747e6dSmrg WList *tmp1; 4613e747e6dSmrg int added; 462f66df612Smrg int (*compar) (const char *, const char *) 463f66df612Smrg = (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1); 4643e747e6dSmrg 4653e747e6dSmrg added = FALSE; 466f66df612Smrg if (ip->first == NULL) { 467f66df612Smrg ip->first = tmp; 468f66df612Smrg tmp->prev = NULL; 469f66df612Smrg ip->last = tmp; 470f66df612Smrg added = TRUE; 4713e747e6dSmrg } 472f66df612Smrg else if (Scr->SortIconMgr) { 473f66df612Smrg for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) { 474f66df612Smrg if ((*compar) (tmp_win->icon_name, tmp1->twm->icon_name) < 0) { 475f66df612Smrg tmp->next = tmp1; 476f66df612Smrg tmp->prev = tmp1->prev; 477f66df612Smrg tmp1->prev = tmp; 478f66df612Smrg if (tmp->prev == NULL) 479f66df612Smrg ip->first = tmp; 480f66df612Smrg else 481f66df612Smrg tmp->prev->next = tmp; 482f66df612Smrg added = TRUE; 483f66df612Smrg break; 484f66df612Smrg } 485f66df612Smrg } 4863e747e6dSmrg } 4873e747e6dSmrg 488f66df612Smrg if (!added) { 489f66df612Smrg ip->last->next = tmp; 490f66df612Smrg tmp->prev = ip->last; 491f66df612Smrg ip->last = tmp; 4923e747e6dSmrg } 4933e747e6dSmrg} 4943e747e6dSmrg 495f66df612Smrgstatic void 496f66df612SmrgRemoveFromIconManager(IconMgr *ip, WList *tmp) 4973e747e6dSmrg{ 4983e747e6dSmrg if (tmp->prev == NULL) 499f66df612Smrg ip->first = tmp->next; 5003e747e6dSmrg else 501f66df612Smrg tmp->prev->next = tmp->next; 5023e747e6dSmrg 5033e747e6dSmrg if (tmp->next == NULL) 504f66df612Smrg ip->last = tmp->prev; 5053e747e6dSmrg else 506f66df612Smrg tmp->next->prev = tmp->prev; 5073e747e6dSmrg} 5083e747e6dSmrg 5093e747e6dSmrg/** 5103e747e6dSmrg * remove a window from the icon manager 5113e747e6dSmrg * \param tmp_win the TwmWindow structure 5123e747e6dSmrg */ 513f66df612Smrgvoid 514f66df612SmrgRemoveIconManager(TwmWindow *tmp_win) 5153e747e6dSmrg{ 5163e747e6dSmrg IconMgr *ip; 5173e747e6dSmrg WList *tmp; 5183e747e6dSmrg 5193e747e6dSmrg if (tmp_win->list == NULL) 520f66df612Smrg return; 5213e747e6dSmrg 5223e747e6dSmrg tmp = tmp_win->list; 5233e747e6dSmrg tmp_win->list = NULL; 5243e747e6dSmrg ip = tmp->iconmgr; 5253e747e6dSmrg 5263e747e6dSmrg RemoveFromIconManager(ip, tmp); 527ffd25bcaSmrg 5283e747e6dSmrg XDeleteContext(dpy, tmp->icon, TwmContext); 5293e747e6dSmrg XDeleteContext(dpy, tmp->icon, ScreenContext); 5303e747e6dSmrg XDestroyWindow(dpy, tmp->icon); 5313e747e6dSmrg XDeleteContext(dpy, tmp->w, IconManagerContext); 5323e747e6dSmrg XDeleteContext(dpy, tmp->w, TwmContext); 5333e747e6dSmrg XDeleteContext(dpy, tmp->w, ScreenContext); 5343e747e6dSmrg XDestroyWindow(dpy, tmp->w); 5353e747e6dSmrg ip->count -= 1; 536c2535118Smrg free(tmp); 5373e747e6dSmrg 5383e747e6dSmrg PackIconManager(ip); 5393e747e6dSmrg 540f66df612Smrg if (ip->count == 0) { 541f66df612Smrg XUnmapWindow(dpy, ip->twm_win->frame); 5423e747e6dSmrg } 5433e747e6dSmrg 5443e747e6dSmrg} 5453e747e6dSmrg 546f66df612Smrgvoid 547f66df612SmrgActiveIconManager(WList *active) 5483e747e6dSmrg{ 5493e747e6dSmrg active->active = TRUE; 5503e747e6dSmrg Active = active; 5513e747e6dSmrg Active->iconmgr->active = active; 5523e747e6dSmrg DrawIconManagerBorder(active); 5533e747e6dSmrg} 5543e747e6dSmrg 555f66df612Smrgvoid 556f66df612SmrgNotActiveIconManager(WList *active) 5573e747e6dSmrg{ 5583e747e6dSmrg active->active = FALSE; 5593e747e6dSmrg DrawIconManagerBorder(active); 5603e747e6dSmrg} 5613e747e6dSmrg 562f66df612Smrgvoid 563f66df612SmrgDrawIconManagerBorder(WList *tmp) 5643e747e6dSmrg{ 5653e747e6dSmrg { 566f66df612Smrg XSetForeground(dpy, Scr->NormalGC, tmp->fore); 567f66df612Smrg XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 2, 2, 568f66df612Smrg (unsigned) (tmp->width - 5), 569f66df612Smrg (unsigned) (tmp->height - 5)); 570f66df612Smrg 571f66df612Smrg if (tmp->active && Scr->Highlight) 572f66df612Smrg XSetForeground(dpy, Scr->NormalGC, tmp->highlight); 573f66df612Smrg else 574f66df612Smrg XSetForeground(dpy, Scr->NormalGC, tmp->back); 575f66df612Smrg 576f66df612Smrg XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 0, 0, 577f66df612Smrg (unsigned) (tmp->width - 1), 578f66df612Smrg (unsigned) (tmp->height - 1)); 579f66df612Smrg XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 1, 1, 580f66df612Smrg (unsigned) (tmp->width - 3), 581f66df612Smrg (unsigned) (tmp->height - 3)); 5823e747e6dSmrg } 5833e747e6dSmrg} 5843e747e6dSmrg 5853e747e6dSmrg/** 5863e747e6dSmrg * sort The Dude 5873e747e6dSmrg * 588f66df612Smrg * \param ip a pointer to the icon manager structure 5893e747e6dSmrg */ 590f66df612Smrgvoid 591f66df612SmrgSortIconManager(IconMgr *ip) 5923e747e6dSmrg{ 5933e747e6dSmrg WList *tmp1, *tmp2; 5943e747e6dSmrg int done; 595f66df612Smrg int (*compar) (const char *, const char *) 596f66df612Smrg = (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1); 5973e747e6dSmrg 5983e747e6dSmrg if (ip == NULL) 599f66df612Smrg ip = Active->iconmgr; 6003e747e6dSmrg 6013e747e6dSmrg done = FALSE; 602f66df612Smrg do { 603f66df612Smrg for (tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) { 604f66df612Smrg if ((tmp2 = tmp1->next) == NULL) { 605f66df612Smrg done = TRUE; 606f66df612Smrg break; 607f66df612Smrg } 608f66df612Smrg if ((*compar) (tmp1->twm->icon_name, tmp2->twm->icon_name) > 0) { 609f66df612Smrg /* take it out and put it back in */ 610f66df612Smrg RemoveFromIconManager(ip, tmp2); 611f66df612Smrg InsertInIconManager(ip, tmp2, tmp2->twm); 612f66df612Smrg break; 613f66df612Smrg } 614f66df612Smrg } 6153e747e6dSmrg } 6163e747e6dSmrg while (!done); 6173e747e6dSmrg PackIconManager(ip); 6183e747e6dSmrg} 6193e747e6dSmrg 6203e747e6dSmrg/** 621ffd25bcaSmrg * pack the icon manager windows following 622f66df612Smrg * an addition or deletion 6233e747e6dSmrg * 624f66df612Smrg * \param ip a pointer to the icon manager structure 6253e747e6dSmrg */ 626f66df612Smrgvoid 627f66df612SmrgPackIconManager(IconMgr *ip) 6283e747e6dSmrg{ 629f66df612Smrg int newwidth, i, row, col, maxcol, colinc, rowinc, wheight, wwidth; 6303e747e6dSmrg int savewidth; 6313e747e6dSmrg WList *tmp; 6323e747e6dSmrg 6333e747e6dSmrg wheight = Scr->IconManagerFont.height + 10; 6343e747e6dSmrg if (wheight < (siconify_height + 4)) 635f66df612Smrg wheight = siconify_height + 4; 6363e747e6dSmrg 6373e747e6dSmrg wwidth = ip->width / ip->columns; 6383e747e6dSmrg 6393e747e6dSmrg rowinc = wheight; 6403e747e6dSmrg colinc = wwidth; 6413e747e6dSmrg 6423e747e6dSmrg row = 0; 6433e747e6dSmrg col = ip->columns; 6443e747e6dSmrg maxcol = 0; 645f66df612Smrg 646f66df612Smrg for (i = 0, tmp = ip->first; tmp != NULL; i++, tmp = tmp->next) { 647f66df612Smrg int new_x, new_y; 648f66df612Smrg 649f66df612Smrg tmp->me = i; 650f66df612Smrg if (++col >= ip->columns) { 651f66df612Smrg col = 0; 652f66df612Smrg row += 1; 653f66df612Smrg } 654f66df612Smrg if (col > maxcol) 655f66df612Smrg maxcol = col; 656f66df612Smrg 657f66df612Smrg new_x = col * colinc; 658f66df612Smrg new_y = (row - 1) * rowinc; 659f66df612Smrg 660f66df612Smrg /* if the position or size has not changed, don't touch it */ 661f66df612Smrg if (tmp->x != new_x || tmp->y != new_y || 662f66df612Smrg tmp->width != wwidth || tmp->height != wheight) { 663f66df612Smrg XMoveResizeWindow(dpy, tmp->w, 664f66df612Smrg new_x, new_y, 665f66df612Smrg (unsigned) wwidth, (unsigned) wheight); 666f66df612Smrg 667f66df612Smrg tmp->row = row - 1; 668f66df612Smrg tmp->col = col; 669f66df612Smrg tmp->x = new_x; 670f66df612Smrg tmp->y = new_y; 671f66df612Smrg tmp->width = wwidth; 672f66df612Smrg tmp->height = wheight; 673f66df612Smrg } 6743e747e6dSmrg } 6753e747e6dSmrg maxcol += 1; 6763e747e6dSmrg 6773e747e6dSmrg ip->cur_rows = row; 6783e747e6dSmrg ip->cur_columns = maxcol; 6793e747e6dSmrg ip->height = row * rowinc; 6803e747e6dSmrg if (ip->height == 0) 681f66df612Smrg ip->height = rowinc; 6823e747e6dSmrg newwidth = maxcol * colinc; 6833e747e6dSmrg if (newwidth == 0) 684f66df612Smrg newwidth = colinc; 6853e747e6dSmrg 686f66df612Smrg XResizeWindow(dpy, ip->w, (unsigned) newwidth, (unsigned) ip->height); 6873e747e6dSmrg 6883e747e6dSmrg savewidth = ip->width; 6893e747e6dSmrg if (ip->twm_win) 690f66df612Smrg SetupWindow(ip->twm_win, 691f66df612Smrg ip->twm_win->frame_x, ip->twm_win->frame_y, 692f66df612Smrg newwidth, ip->height + ip->twm_win->title_height, -1); 6933e747e6dSmrg ip->width = savewidth; 6943e747e6dSmrg} 695