1645f5050Syouri/* 2645f5050Syouri * Copyright 1989 Massachusetts Institute of Technology 30bbfda8aSnia * Copyright 1992 Claude Lecommandeur. 4645f5050Syouri */ 5645f5050Syouri 6645f5050Syouri/*********************************************************************** 7645f5050Syouri * 8645f5050Syouri * $XConsortium: iconmgr.c,v 1.48 91/09/10 15:27:07 dave Exp $ 9645f5050Syouri * 10645f5050Syouri * Icon Manager routines 11645f5050Syouri * 120bbfda8aSnia * 09-Mar-89 Tom LaStrange File Created 13645f5050Syouri * 14645f5050Syouri * Do the necessary modification to be integrated in ctwm. 15645f5050Syouri * Can no longer be used for the standard twm. 16645f5050Syouri * 17645f5050Syouri * 22-April-92 Claude Lecommandeur. 18645f5050Syouri * 19645f5050Syouri * 20645f5050Syouri ***********************************************************************/ 21645f5050Syouri 220bbfda8aSnia#include "ctwm.h" 230bbfda8aSnia 24645f5050Syouri#include <stdio.h> 250bbfda8aSnia#include <stdlib.h> 260bbfda8aSnia#include <string.h> 270bbfda8aSnia#include <strings.h> 280bbfda8aSnia 29645f5050Syouri#include <X11/Xatom.h> 300bbfda8aSnia 31645f5050Syouri#include "util.h" 320bbfda8aSnia#include "iconmgr.h" 330bbfda8aSnia#include "icons_builtin.h" 34645f5050Syouri#include "screen.h" 350bbfda8aSnia#include "drawing.h" 360bbfda8aSnia#include "functions_defs.h" 370bbfda8aSnia#include "list.h" 380bbfda8aSnia#include "occupation.h" 390bbfda8aSnia#include "otp.h" 40645f5050Syouri#include "add_window.h" 410bbfda8aSnia#include "gram.tab.h" 42df1c27a6Snia#include "vscreen.h" 430bbfda8aSnia#include "win_decorations.h" 440bbfda8aSnia#include "win_resize.h" 450bbfda8aSnia#include "win_utils.h" 46df1c27a6Snia#include "xparsegeometry.h" 470bbfda8aSnia 480bbfda8aSnia 490bbfda8aSnia/* Where we start drawing the name in the icon manager */ 500bbfda8aSniastatic int iconmgr_textx; 51645f5050Syouri 520bbfda8aSniastatic WList *Active = NULL; 530bbfda8aSniastatic WList *Current = NULL; 54645f5050SyouriWList *DownIconManager = NULL; 55645f5050Syouri 56645f5050Syouri/*********************************************************************** 57645f5050Syouri * 58645f5050Syouri * Procedure: 590bbfda8aSnia * CreateIconManagers - creat all the icon manager windows 600bbfda8aSnia * for this screen. 61645f5050Syouri * 62645f5050Syouri * Returned Value: 630bbfda8aSnia * none 64645f5050Syouri * 65645f5050Syouri * Inputs: 660bbfda8aSnia * none 67645f5050Syouri * 68645f5050Syouri *********************************************************************** 69645f5050Syouri */ 70645f5050Syouri 71645f5050Syourivoid CreateIconManagers(void) 72645f5050Syouri{ 730bbfda8aSnia WorkSpace *ws; 740bbfda8aSnia 750bbfda8aSnia if(Scr->NoIconManagers) { 760bbfda8aSnia return; 770bbfda8aSnia } 780bbfda8aSnia 790bbfda8aSnia /* 800bbfda8aSnia * Move past the iconified icon to start the text. 810bbfda8aSnia * XXX Semi-arbitrary magic add'l padding, to deal with various inner 820bbfda8aSnia * positioning of the icon subwindow. Be smarter (or at least 830bbfda8aSnia * clearer) about this... 840bbfda8aSnia */ 850bbfda8aSnia iconmgr_textx = im_iconified_icon_width + 11; 860bbfda8aSnia if(Scr->use3Diconmanagers) { 870bbfda8aSnia iconmgr_textx += Scr->IconManagerShadowDepth; 880bbfda8aSnia } 890bbfda8aSnia 900bbfda8aSnia if(Scr->siconifyPm == None) { 910bbfda8aSnia Scr->siconifyPm = Create2DIconManagerIcon(); 920bbfda8aSnia } 930bbfda8aSnia 94df1c27a6Snia // This loop is confusing. The inner for() loops p over the ->next 95df1c27a6Snia // elements in the list, which is all the iconmgr's in the workspace. 96df1c27a6Snia // The outer for() loops q over the ->nextv (<-- extra 'v' on the 97df1c27a6Snia // end), which is a link to the head of the iconmgr list for the 98df1c27a6Snia // _next_ workspace. 990bbfda8aSnia ws = Scr->workSpaceMgr.workSpaceList; 1000bbfda8aSnia for(IconMgr *q = Scr->iconmgr; q != NULL; q = q->nextv) { 1010bbfda8aSnia for(IconMgr *p = q; p != NULL; p = p->next) { 1020bbfda8aSnia int gx, gy; 1030bbfda8aSnia char imname[100]; 1040bbfda8aSnia int mask; 1050bbfda8aSnia int gravity; 1060bbfda8aSnia int bw; 1070bbfda8aSnia Pixel background; 1080bbfda8aSnia 1090bbfda8aSnia snprintf(imname, sizeof(imname), "%s Icon Manager", p->name); 1100bbfda8aSnia 1110bbfda8aSnia if(!p->geometry || !strlen(p->geometry)) { 1120bbfda8aSnia p->geometry = "+0+0"; 1130bbfda8aSnia } 114df1c27a6Snia mask = RLayoutXParseGeometry(Scr->Layout, p->geometry, 115df1c27a6Snia &gx, &gy, 116df1c27a6Snia (unsigned int *) &p->width, (unsigned int *)&p->height); 1170bbfda8aSnia 1180bbfda8aSnia bw = LookInList(Scr->NoBorder, imname, NULL) ? 0 : 1190bbfda8aSnia (Scr->ThreeDBorderWidth ? Scr->ThreeDBorderWidth : Scr->BorderWidth); 1200bbfda8aSnia 1210bbfda8aSnia if(mask & XNegative) { 1220bbfda8aSnia gx += Scr->rootw - p->width - 2 * bw; 1230bbfda8aSnia gravity = (mask & YNegative) ? SouthEastGravity : NorthEastGravity; 1240bbfda8aSnia } 1250bbfda8aSnia else { 1260bbfda8aSnia gravity = (mask & YNegative) ? SouthWestGravity : NorthWestGravity; 1270bbfda8aSnia } 1280bbfda8aSnia if(mask & YNegative) { 1290bbfda8aSnia gy += Scr->rooth - p->height - 2 * bw; 1300bbfda8aSnia } 1310bbfda8aSnia 1320bbfda8aSnia background = Scr->IconManagerC.back; 1330bbfda8aSnia GetColorFromList(Scr->IconManagerBL, p->name, NULL, 1340bbfda8aSnia &background); 1350bbfda8aSnia 1360bbfda8aSnia if(p->width < 1) { 1370bbfda8aSnia p->width = 1; 1380bbfda8aSnia } 1390bbfda8aSnia if(p->height < 1) { 1400bbfda8aSnia p->height = 1; 1410bbfda8aSnia } 1420bbfda8aSnia p->w = XCreateSimpleWindow(dpy, Scr->Root, 1430bbfda8aSnia gx, gy, p->width, p->height, 1, 1440bbfda8aSnia Scr->Black, background); 1450bbfda8aSnia 1460bbfda8aSnia 1470bbfda8aSnia /* Scr->workSpaceMgr.activeWSPC = ws; */ 1480bbfda8aSnia 1490bbfda8aSnia /* Setup various WM properties on the iconmgr's window */ 1500bbfda8aSnia { 1510bbfda8aSnia char *icon_name; 1520bbfda8aSnia XWMHints wmhints; 1530bbfda8aSnia XClassHint clhints; 1540bbfda8aSnia 1550bbfda8aSnia if(p->icon_name) { 1560bbfda8aSnia icon_name = strdup(p->icon_name); 1570bbfda8aSnia } 1580bbfda8aSnia else { 1590bbfda8aSnia asprintf(&icon_name, "%s Icons", p->name); 1600bbfda8aSnia } 1610bbfda8aSnia 1620bbfda8aSnia wmhints.initial_state = NormalState; 1630bbfda8aSnia wmhints.input = True; 1640bbfda8aSnia wmhints.flags = InputHint | StateHint; 1650bbfda8aSnia 1660bbfda8aSnia clhints.res_name = icon_name; 1670bbfda8aSnia clhints.res_class = "TwmIconManager"; 1680bbfda8aSnia 1690bbfda8aSnia XmbSetWMProperties(dpy, p->w, imname, icon_name, NULL, 0, NULL, 1700bbfda8aSnia &wmhints, &clhints); 1710bbfda8aSnia free(icon_name); 1720bbfda8aSnia } 1730bbfda8aSnia 1740bbfda8aSnia 1750bbfda8aSnia p->twm_win = AddWindow(p->w, AWT_ICON_MANAGER, p, Scr->currentvs); 176df1c27a6Snia 177df1c27a6Snia // SetupOccupation() called from AddWindow() doesn't setup 178df1c27a6Snia // occupation for icon managers, nor clear vs if occupation 179df1c27a6Snia // lacks. So make it occupy the one we're setting up, or the 180df1c27a6Snia // 1st if we ran out somehow... 1810bbfda8aSnia if(ws) { 1820bbfda8aSnia p->twm_win->occupation = 1 << ws->number; 183df1c27a6Snia 184df1c27a6Snia // ConfigureWorkSpaceManager() ran before us, so we can 185df1c27a6Snia // tell whether we're in the ws to reveal this IM. 186df1c27a6Snia if(ws->number != Scr->currentvs->wsw->currentwspc->number) { 1870bbfda8aSnia p->twm_win->vs = NULL; 1880bbfda8aSnia } 1890bbfda8aSnia } 1900bbfda8aSnia else { 1910bbfda8aSnia p->twm_win->occupation = 1; 1920bbfda8aSnia } 193df1c27a6Snia 1940bbfda8aSnia#ifdef DEBUG_ICONMGR 1950bbfda8aSnia fprintf(stderr, 196df1c27a6Snia "CreateIconManagers: IconMgr %p: twm_win=%p win=0x%lx " 197df1c27a6Snia "name='%s' x=%d y=%d w=%d h=%d occupation=%x\n", 198df1c27a6Snia p, p->twm_win, p->twm_win->w, p->name, 199df1c27a6Snia gx, gy, p->width, p->height, p->twm_win->occupation); 2000bbfda8aSnia#endif 2010bbfda8aSnia 2020bbfda8aSnia { 2030bbfda8aSnia XSizeHints sizehints; 2040bbfda8aSnia 2050bbfda8aSnia sizehints.flags = PWinGravity; 2060bbfda8aSnia sizehints.win_gravity = gravity; 2070bbfda8aSnia XSetWMSizeHints(dpy, p->w, &sizehints, XA_WM_NORMAL_HINTS); 2080bbfda8aSnia } 2090bbfda8aSnia 2100bbfda8aSnia p->twm_win->mapped = false; 2110bbfda8aSnia SetMapStateProp(p->twm_win, WithdrawnState); 2120bbfda8aSnia if(p->twm_win && (p->twm_win->wmhints->initial_state == IconicState)) { 2130bbfda8aSnia p->twm_win->isicon = true; 2140bbfda8aSnia } 2150bbfda8aSnia else if(!Scr->NoIconManagers && Scr->ShowIconManager) { 2160bbfda8aSnia p->twm_win->isicon = false; 2170bbfda8aSnia } 2180bbfda8aSnia else { 2190bbfda8aSnia p->twm_win->isicon = true; 2200bbfda8aSnia } 2210bbfda8aSnia } 2220bbfda8aSnia if(ws != NULL) { 2230bbfda8aSnia ws = ws->next; 2240bbfda8aSnia } 2250bbfda8aSnia } 2260bbfda8aSnia 2270bbfda8aSnia if(Scr->workSpaceManagerActive) { 2280bbfda8aSnia Scr->workSpaceMgr.workSpaceList->iconmgr = Scr->iconmgr; 2290bbfda8aSnia } 2300bbfda8aSnia 2310bbfda8aSnia 2320bbfda8aSnia /* 2330bbfda8aSnia * Grab buttons/keystrokes for icon managers appropriately. 2340bbfda8aSnia * Normally, this is done in AddWindow(), but it explicitly skips it 2350bbfda8aSnia * for icon managers. It's not at all clear why GrabButtons() would 2360bbfda8aSnia * do so; I don't think it needs to. GrabKeys() does do some looping 2370bbfda8aSnia * over the Scr->iconmgr list at the end though, so it's possible we 2380bbfda8aSnia * need to delay calling it until now when the list is all filled up. 2390bbfda8aSnia * This needs further investigation; it may be that the special case 2400bbfda8aSnia * and this code can be removed. X-ref comments in add_window.c 2410bbfda8aSnia * about it. 2420bbfda8aSnia */ 2430bbfda8aSnia for(IconMgr *q = Scr->iconmgr; q != NULL; q = q->nextv) { 2440bbfda8aSnia for(IconMgr *p = q; p != NULL; p = p->next) { 2450bbfda8aSnia GrabButtons(p->twm_win); 2460bbfda8aSnia GrabKeys(p->twm_win); 2470bbfda8aSnia } 248645f5050Syouri } 249645f5050Syouri 250645f5050Syouri} 251645f5050Syouri 252645f5050Syouri/*********************************************************************** 253645f5050Syouri * 254645f5050Syouri * Procedure: 2550bbfda8aSnia * AllocateIconManager - allocate a new icon manager 256645f5050Syouri * 257645f5050Syouri * Inputs: 2580bbfda8aSnia * name - the name of this icon manager 2590bbfda8aSnia * icon_name - the name of the associated icon 2600bbfda8aSnia * geom - a geometry string to eventually parse 2610bbfda8aSnia * columns - the number of columns this icon manager has 262645f5050Syouri * 263645f5050Syouri *********************************************************************** 264645f5050Syouri */ 265645f5050Syouri 266645f5050SyouriIconMgr *AllocateIconManager(char *name, char *icon_name, char *geom, 2670bbfda8aSnia int columns) 268645f5050Syouri{ 2690bbfda8aSnia IconMgr *p; 270645f5050Syouri 271645f5050Syouri#ifdef DEBUG_ICONMGR 2720bbfda8aSnia fprintf(stderr, "AllocateIconManager\n"); 2730bbfda8aSnia fprintf(stderr, " name=\"%s\" icon_name=\"%s\", geom=\"%s\", col=%d\n", 2740bbfda8aSnia name, icon_name, geom, columns); 275645f5050Syouri#endif 276645f5050Syouri 2770bbfda8aSnia if(Scr->NoIconManagers) { 2780bbfda8aSnia return NULL; 2790bbfda8aSnia } 2800bbfda8aSnia 2810bbfda8aSnia if(columns < 1) { 2820bbfda8aSnia columns = 1; 2830bbfda8aSnia } 2840bbfda8aSnia p = calloc(1, sizeof(IconMgr)); 2850bbfda8aSnia p->name = name; 2860bbfda8aSnia p->icon_name = icon_name; 2870bbfda8aSnia p->geometry = geom; 2880bbfda8aSnia p->columns = columns; 2890bbfda8aSnia p->scr = Scr; 2900bbfda8aSnia p->width = 150; 2910bbfda8aSnia p->height = 10; 2920bbfda8aSnia 2930bbfda8aSnia if(Scr->iconmgr == NULL) { 2940bbfda8aSnia Scr->iconmgr = p; 2950bbfda8aSnia Scr->iconmgr->lasti = p; 2960bbfda8aSnia } 2970bbfda8aSnia else { 2980bbfda8aSnia Scr->iconmgr->lasti->next = p; 2990bbfda8aSnia p->prev = Scr->iconmgr->lasti; 3000bbfda8aSnia Scr->iconmgr->lasti = p; 3010bbfda8aSnia } 3020bbfda8aSnia return(p); 3030bbfda8aSnia} 3040bbfda8aSnia 3050bbfda8aSnia 3060bbfda8aSnia/* 3070bbfda8aSnia * Each workspace has its own [set of] icon manager[s]. The initial main 3080bbfda8aSnia * one was setup via AllocateIconManager() early in startup. The others 3090bbfda8aSnia * were setup during parsing the config file. Then this gets called late 3100bbfda8aSnia * in startup, after all the workspaces are setup, to copy them all into 3110bbfda8aSnia * each one. 3120bbfda8aSnia * 3130bbfda8aSnia * Note this is distinct from CreateIconManagers(); that creates and 3140bbfda8aSnia * draws the windows, this creates and connects up the data structures. 3150bbfda8aSnia */ 3160bbfda8aSniavoid AllocateOtherIconManagers(void) 3170bbfda8aSnia{ 3180bbfda8aSnia IconMgr *imfirst; // First IM on each workspace 3190bbfda8aSnia WorkSpace *ws; 3200bbfda8aSnia 3210bbfda8aSnia /* No defined workspaces? Nothing to do. */ 3220bbfda8aSnia if(! Scr->workSpaceManagerActive) { 3230bbfda8aSnia return; 3240bbfda8aSnia } 3250bbfda8aSnia 3260bbfda8aSnia /* The first workspace just gets the ones we already have */ 3270bbfda8aSnia ws = Scr->workSpaceMgr.workSpaceList; 3280bbfda8aSnia ws->iconmgr = Scr->iconmgr; 3290bbfda8aSnia 3300bbfda8aSnia /* From the second on, we start copying */ 3310bbfda8aSnia imfirst = ws->iconmgr; 3320bbfda8aSnia for(ws = ws->next; ws != NULL; ws = ws->next) { 3330bbfda8aSnia IconMgr *ip, *previ, *p = NULL; 3340bbfda8aSnia 3350bbfda8aSnia /* Copy in the first iconmgr */ 3360bbfda8aSnia ws->iconmgr = malloc(sizeof(IconMgr)); 3370bbfda8aSnia *ws->iconmgr = *imfirst; 3380bbfda8aSnia 3390bbfda8aSnia /* 3400bbfda8aSnia * This first is now the nextv to the first in the previous WS, 3410bbfda8aSnia * and we don't [yet] have a nextv of our own. 3420bbfda8aSnia * */ 3430bbfda8aSnia imfirst->nextv = ws->iconmgr; 3440bbfda8aSnia ws->iconmgr->nextv = NULL; 3450bbfda8aSnia 3460bbfda8aSnia /* 3470bbfda8aSnia * Start from the second, and copy them each from the prior 3480bbfda8aSnia * workspace we just went through. 3490bbfda8aSnia * */ 3500bbfda8aSnia previ = ws->iconmgr; 3510bbfda8aSnia for(ip = imfirst->next; ip != NULL; ip = ip->next) { 3520bbfda8aSnia /* Copy the base bits */ 3530bbfda8aSnia p = malloc(sizeof(IconMgr)); 3540bbfda8aSnia *p = *ip; 3550bbfda8aSnia 3560bbfda8aSnia /* Link up the double-links, and there's no nextv [yet] */ 3570bbfda8aSnia previ->next = p; 3580bbfda8aSnia p->prev = previ; 3590bbfda8aSnia p->next = NULL; 3600bbfda8aSnia p->nextv = NULL; 3610bbfda8aSnia 3620bbfda8aSnia /* We're now the nextv to that one in the old workspace */ 3630bbfda8aSnia ip->nextv = p; 3640bbfda8aSnia 3650bbfda8aSnia /* And back around to the next one to copy into this WS */ 3660bbfda8aSnia previ = p; 3670bbfda8aSnia } 3680bbfda8aSnia 3690bbfda8aSnia /* Each one has a pointer to the last IM in this WS, so save those */ 3700bbfda8aSnia for(ip = ws->iconmgr; ip != NULL; ip = ip->next) { 3710bbfda8aSnia ip->lasti = p; 3720bbfda8aSnia } 3730bbfda8aSnia 3740bbfda8aSnia /* 3750bbfda8aSnia * And back around to the next workspace, which works from those 3760bbfda8aSnia * we made for this WS. We go from imfirst rather than 3770bbfda8aSnia * Scr->iconmgr so the ip->nextv rewrites are correct above; we 3780bbfda8aSnia * have to fill them in on the next loop. 3790bbfda8aSnia */ 3800bbfda8aSnia imfirst = ws->iconmgr; 3810bbfda8aSnia } 382645f5050Syouri} 383645f5050Syouri 3840bbfda8aSnia 385645f5050Syouri/*********************************************************************** 386645f5050Syouri * 387645f5050Syouri * Procedure: 3880bbfda8aSnia * MoveIconManager - move the pointer around in an icon manager 389645f5050Syouri * 390645f5050Syouri * Inputs: 3910bbfda8aSnia * dir - one of the following: 3920bbfda8aSnia * F_FORWICONMGR - forward in the window list 3930bbfda8aSnia * F_BACKICONMGR - backward in the window list 3940bbfda8aSnia * F_UPICONMGR - up one row 3950bbfda8aSnia * F_DOWNICONMGR - down one row 3960bbfda8aSnia * F_LEFTICONMGR - left one column 3970bbfda8aSnia * F_RIGHTICONMGR - right one column 398645f5050Syouri * 399645f5050Syouri * Special Considerations: 4000bbfda8aSnia * none 401645f5050Syouri * 402645f5050Syouri *********************************************************************** 403645f5050Syouri */ 404645f5050Syouri 405645f5050Syourivoid MoveIconManager(int dir) 406645f5050Syouri{ 4070bbfda8aSnia IconMgr *ip; 4080bbfda8aSnia WList *tmp = NULL; 4090bbfda8aSnia int cur_row, cur_col, new_row, new_col; 4100bbfda8aSnia int row_inc, col_inc; 4110bbfda8aSnia bool got_it; 4120bbfda8aSnia 4130bbfda8aSnia if(!Current) { 4140bbfda8aSnia return; 4150bbfda8aSnia } 4160bbfda8aSnia 4170bbfda8aSnia cur_row = Current->row; 4180bbfda8aSnia cur_col = Current->col; 4190bbfda8aSnia ip = Current->iconmgr; 4200bbfda8aSnia 4210bbfda8aSnia row_inc = 0; 4220bbfda8aSnia col_inc = 0; 4230bbfda8aSnia got_it = false; 4240bbfda8aSnia 4250bbfda8aSnia switch(dir) { 4260bbfda8aSnia case F_FORWICONMGR: 4270bbfda8aSnia if((tmp = Current->next) == NULL) { 4280bbfda8aSnia tmp = ip->first; 4290bbfda8aSnia } 4300bbfda8aSnia got_it = true; 4310bbfda8aSnia break; 4320bbfda8aSnia 4330bbfda8aSnia case F_BACKICONMGR: 4340bbfda8aSnia if((tmp = Current->prev) == NULL) { 4350bbfda8aSnia tmp = ip->last; 4360bbfda8aSnia } 4370bbfda8aSnia got_it = true; 4380bbfda8aSnia break; 4390bbfda8aSnia 4400bbfda8aSnia case F_UPICONMGR: 4410bbfda8aSnia row_inc = -1; 4420bbfda8aSnia break; 4430bbfda8aSnia 4440bbfda8aSnia case F_DOWNICONMGR: 4450bbfda8aSnia row_inc = 1; 4460bbfda8aSnia break; 4470bbfda8aSnia 4480bbfda8aSnia case F_LEFTICONMGR: 4490bbfda8aSnia col_inc = -1; 4500bbfda8aSnia break; 4510bbfda8aSnia 4520bbfda8aSnia case F_RIGHTICONMGR: 4530bbfda8aSnia col_inc = 1; 4540bbfda8aSnia break; 4550bbfda8aSnia } 4560bbfda8aSnia 4570bbfda8aSnia /* If got_it is false ast this point then we got a left, right, 4580bbfda8aSnia * up, or down, command. We will enter this loop until we find 4590bbfda8aSnia * a window to warp to. 460645f5050Syouri */ 4610bbfda8aSnia new_row = cur_row; 4620bbfda8aSnia new_col = cur_col; 4630bbfda8aSnia 4640bbfda8aSnia while(!got_it) { 4650bbfda8aSnia new_row += row_inc; 4660bbfda8aSnia new_col += col_inc; 4670bbfda8aSnia if(new_row < 0) { 4680bbfda8aSnia new_row = ip->cur_rows - 1; 4690bbfda8aSnia } 4700bbfda8aSnia if(new_col < 0) { 4710bbfda8aSnia new_col = ip->cur_columns - 1; 4720bbfda8aSnia } 4730bbfda8aSnia if(new_row >= ip->cur_rows) { 4740bbfda8aSnia new_row = 0; 4750bbfda8aSnia } 4760bbfda8aSnia if(new_col >= ip->cur_columns) { 4770bbfda8aSnia new_col = 0; 4780bbfda8aSnia } 4790bbfda8aSnia 4800bbfda8aSnia /* Now let's go through the list to see if there is an entry with this 4810bbfda8aSnia * new position 4820bbfda8aSnia */ 4830bbfda8aSnia for(tmp = ip->first; tmp != NULL; tmp = tmp->next) { 4840bbfda8aSnia if(tmp->row == new_row && tmp->col == new_col) { 4850bbfda8aSnia got_it = true; 4860bbfda8aSnia break; 4870bbfda8aSnia } 4880bbfda8aSnia } 4890bbfda8aSnia } 4900bbfda8aSnia 4910bbfda8aSnia if(!got_it) { 4920bbfda8aSnia fprintf(stderr, 4930bbfda8aSnia "%s: unable to find window (%d, %d) in icon manager\n", 4940bbfda8aSnia ProgramName, new_row, new_col); 4950bbfda8aSnia return; 4960bbfda8aSnia } 4970bbfda8aSnia 4980bbfda8aSnia if(tmp == NULL) { 4990bbfda8aSnia return; 5000bbfda8aSnia } 5010bbfda8aSnia 5020bbfda8aSnia /* raise the frame so the icon manager is visible */ 5030bbfda8aSnia if(ip->twm_win->mapped) { 5040bbfda8aSnia OtpRaise(ip->twm_win, WinWin); 5050bbfda8aSnia XWarpPointer(dpy, None, tmp->icon, 0, 0, 0, 0, 5, 5); 5060bbfda8aSnia } 5070bbfda8aSnia else { 5080bbfda8aSnia if(tmp->twm->title_height) { 5090bbfda8aSnia int tbx = Scr->TBInfo.titlex; 5100bbfda8aSnia int x = tmp->twm->highlightxr; 5110bbfda8aSnia XWarpPointer(dpy, None, tmp->twm->title_w, 0, 0, 0, 0, 5120bbfda8aSnia tbx + (x - tbx) / 2, 5130bbfda8aSnia Scr->TitleHeight / 4); 5140bbfda8aSnia } 5150bbfda8aSnia else { 5160bbfda8aSnia XWarpPointer(dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5); 5170bbfda8aSnia } 5180bbfda8aSnia } 519645f5050Syouri} 520645f5050Syouri 521645f5050Syouri/*********************************************************************** 522645f5050Syouri * 523645f5050Syouri * Procedure: 5240bbfda8aSnia * MoveMappedIconManager - move the pointer around in an icon manager 525645f5050Syouri * 526645f5050Syouri * Inputs: 5270bbfda8aSnia * dir - one of the following: 5280bbfda8aSnia * F_FORWMAPICONMGR - forward in the window list 5290bbfda8aSnia * F_BACKMAPICONMGR - backward in the window list 530645f5050Syouri * 531645f5050Syouri * Special Considerations: 5320bbfda8aSnia * none 533645f5050Syouri * 534645f5050Syouri *********************************************************************** 535645f5050Syouri */ 536645f5050Syouri 537645f5050Syourivoid MoveMappedIconManager(int dir) 538645f5050Syouri{ 5390bbfda8aSnia IconMgr *ip; 5400bbfda8aSnia WList *tmp = NULL; 5410bbfda8aSnia WList *orig = NULL; 5420bbfda8aSnia bool got_it; 5430bbfda8aSnia 5440bbfda8aSnia if(!Current) { 5450bbfda8aSnia Current = Active; 5460bbfda8aSnia } 5470bbfda8aSnia if(!Current) { 5480bbfda8aSnia return; 5490bbfda8aSnia } 5500bbfda8aSnia 5510bbfda8aSnia ip = Current->iconmgr; 5520bbfda8aSnia 5530bbfda8aSnia got_it = false; 5540bbfda8aSnia tmp = Current; 5550bbfda8aSnia orig = Current; 5560bbfda8aSnia 5570bbfda8aSnia while(!got_it) { 5580bbfda8aSnia switch(dir) { 5590bbfda8aSnia case F_FORWMAPICONMGR: 5600bbfda8aSnia if((tmp = tmp->next) == NULL) { 5610bbfda8aSnia tmp = ip->first; 5620bbfda8aSnia } 5630bbfda8aSnia break; 5640bbfda8aSnia 5650bbfda8aSnia case F_BACKMAPICONMGR: 5660bbfda8aSnia if((tmp = tmp->prev) == NULL) { 5670bbfda8aSnia tmp = ip->last; 5680bbfda8aSnia } 5690bbfda8aSnia break; 5700bbfda8aSnia } 5710bbfda8aSnia if(tmp->twm->mapped) { 5720bbfda8aSnia got_it = true; 5730bbfda8aSnia break; 5740bbfda8aSnia } 5750bbfda8aSnia if(tmp == orig) { 5760bbfda8aSnia break; 5770bbfda8aSnia } 5780bbfda8aSnia } 5790bbfda8aSnia 5800bbfda8aSnia if(!got_it) { 5810bbfda8aSnia fprintf(stderr, "%s: unable to find open window in icon manager\n", 5820bbfda8aSnia ProgramName); 5830bbfda8aSnia return; 5840bbfda8aSnia } 5850bbfda8aSnia 5860bbfda8aSnia if(tmp == NULL) { 5870bbfda8aSnia return; 5880bbfda8aSnia } 5890bbfda8aSnia 5900bbfda8aSnia /* raise the frame so the icon manager is visible */ 5910bbfda8aSnia if(ip->twm_win->mapped) { 5920bbfda8aSnia OtpRaise(ip->twm_win, WinWin); 5930bbfda8aSnia XWarpPointer(dpy, None, tmp->icon, 0, 0, 0, 0, 5, 5); 5940bbfda8aSnia } 5950bbfda8aSnia else { 5960bbfda8aSnia if(tmp->twm->title_height) { 5970bbfda8aSnia XWarpPointer(dpy, None, tmp->twm->title_w, 0, 0, 0, 0, 5980bbfda8aSnia tmp->twm->title_width / 2, 5990bbfda8aSnia Scr->TitleHeight / 4); 6000bbfda8aSnia } 6010bbfda8aSnia else { 6020bbfda8aSnia XWarpPointer(dpy, None, tmp->twm->w, 0, 0, 0, 0, 5, 5); 6030bbfda8aSnia } 6040bbfda8aSnia } 605645f5050Syouri} 606645f5050Syouri 607645f5050Syouri/*********************************************************************** 608645f5050Syouri * 609645f5050Syouri * Procedure: 6100bbfda8aSnia * JumpIconManager - jump from one icon manager to another, 6110bbfda8aSnia * possibly even on another screen 612645f5050Syouri * 613645f5050Syouri * Inputs: 6140bbfda8aSnia * dir - one of the following: 6150bbfda8aSnia * F_NEXTICONMGR - go to the next icon manager 6160bbfda8aSnia * F_PREVICONMGR - go to the previous one 617645f5050Syouri * 618645f5050Syouri *********************************************************************** 619645f5050Syouri */ 620645f5050Syouri 6210bbfda8aSniavoid JumpIconManager(int dir) 622645f5050Syouri{ 6230bbfda8aSnia IconMgr *ip, *tmp_ip = NULL; 6240bbfda8aSnia bool got_it = false; 6250bbfda8aSnia ScreenInfo *sp; 6260bbfda8aSnia int screen; 627645f5050Syouri 6280bbfda8aSnia if(!Current) { 6290bbfda8aSnia return; 6300bbfda8aSnia } 631645f5050Syouri 632645f5050Syouri 633645f5050Syouri#define ITER(i) (dir == F_NEXTICONMGR ? (i)->next : (i)->prev) 634645f5050Syouri#define IPOFSP(sp) (dir == F_NEXTICONMGR ? sp->iconmgr : sp->iconmgr->lasti) 635645f5050Syouri#define TEST(ip) if ((ip)->count != 0 && (ip)->twm_win->mapped) \ 6360bbfda8aSnia { got_it = true; break; } 6370bbfda8aSnia 6380bbfda8aSnia ip = Current->iconmgr; 6390bbfda8aSnia for(tmp_ip = ITER(ip); tmp_ip; tmp_ip = ITER(tmp_ip)) { 6400bbfda8aSnia TEST(tmp_ip); 6410bbfda8aSnia } 6420bbfda8aSnia 6430bbfda8aSnia if(!got_it) { 6440bbfda8aSnia int origscreen = ip->scr->screen; 6450bbfda8aSnia int inc = (dir == F_NEXTICONMGR ? 1 : -1); 6460bbfda8aSnia 6470bbfda8aSnia for(screen = origscreen + inc; ; screen += inc) { 6480bbfda8aSnia if(screen >= NumScreens) { 6490bbfda8aSnia screen = 0; 6500bbfda8aSnia } 6510bbfda8aSnia else if(screen < 0) { 6520bbfda8aSnia screen = NumScreens - 1; 6530bbfda8aSnia } 6540bbfda8aSnia 6550bbfda8aSnia sp = ScreenList[screen]; 6560bbfda8aSnia if(sp) { 6570bbfda8aSnia for(tmp_ip = IPOFSP(sp); tmp_ip; tmp_ip = ITER(tmp_ip)) { 6580bbfda8aSnia TEST(tmp_ip); 6590bbfda8aSnia } 6600bbfda8aSnia } 6610bbfda8aSnia if(got_it || screen == origscreen) { 6620bbfda8aSnia break; 6630bbfda8aSnia } 664645f5050Syouri } 665645f5050Syouri } 666645f5050Syouri 667645f5050Syouri#undef ITER 668645f5050Syouri#undef IPOFSP 669645f5050Syouri#undef TEST 670645f5050Syouri 6710bbfda8aSnia if(!got_it) { 6720bbfda8aSnia XBell(dpy, 0); 6730bbfda8aSnia return; 6740bbfda8aSnia } 6750bbfda8aSnia 6760bbfda8aSnia /* raise the frame so it is visible */ 6770bbfda8aSnia OtpRaise(tmp_ip->twm_win, WinWin); 6780bbfda8aSnia if(tmp_ip->active) { 6790bbfda8aSnia XWarpPointer(dpy, None, tmp_ip->active->icon, 0, 0, 0, 0, 5, 5); 6800bbfda8aSnia } 6810bbfda8aSnia else { 6820bbfda8aSnia XWarpPointer(dpy, None, tmp_ip->w, 0, 0, 0, 0, 5, 5); 6830bbfda8aSnia } 684645f5050Syouri} 685645f5050Syouri 686645f5050Syouri/*********************************************************************** 687645f5050Syouri * 688645f5050Syouri * Procedure: 6890bbfda8aSnia * AddIconManager - add a window to an icon manager 690645f5050Syouri * 691645f5050Syouri * Inputs: 6920bbfda8aSnia * tmp_win - the TwmWindow structure 693645f5050Syouri * 694645f5050Syouri *********************************************************************** 695645f5050Syouri */ 696645f5050Syouri 697645f5050SyouriWList *AddIconManager(TwmWindow *tmp_win) 698645f5050Syouri{ 6990bbfda8aSnia WList *tmp, *old; 7000bbfda8aSnia IconMgr *ip; 7010bbfda8aSnia 7020bbfda8aSnia /* Some window types don't wind up in icon managers ever */ 7030bbfda8aSnia if(tmp_win->isiconmgr || tmp_win->istransient || tmp_win->iswspmgr 7040bbfda8aSnia || tmp_win->w == Scr->workSpaceMgr.occupyWindow->w) { 7050bbfda8aSnia return NULL; 7060bbfda8aSnia } 7070bbfda8aSnia 7080bbfda8aSnia /* Icon managers can be shut off wholesale in the config */ 7090bbfda8aSnia if(Scr->NoIconManagers) { 7100bbfda8aSnia return NULL; 7110bbfda8aSnia } 7120bbfda8aSnia 7130bbfda8aSnia /* Config could declare not to IMify this type of window in two ways */ 7140bbfda8aSnia if(LookInList(Scr->IconMgrNoShow, tmp_win->name, &tmp_win->class)) { 7150bbfda8aSnia return NULL; 7160bbfda8aSnia } 7170bbfda8aSnia if(Scr->IconManagerDontShow 7180bbfda8aSnia && !LookInList(Scr->IconMgrShow, tmp_win->name, &tmp_win->class)) { 7190bbfda8aSnia return NULL; 7200bbfda8aSnia } 7210bbfda8aSnia 7220bbfda8aSnia /* Dredge up the appropriate IM */ 7230bbfda8aSnia if((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->name, 7240bbfda8aSnia &tmp_win->class)) == NULL) { 7250bbfda8aSnia if(Scr->workSpaceManagerActive) { 7260bbfda8aSnia ip = Scr->workSpaceMgr.workSpaceList->iconmgr; 7270bbfda8aSnia } 7280bbfda8aSnia else { 7290bbfda8aSnia ip = Scr->iconmgr; 7300bbfda8aSnia } 7310bbfda8aSnia } 7320bbfda8aSnia 7330bbfda8aSnia /* IM's exist in all workspaces, so loop through WSen */ 7340bbfda8aSnia tmp = NULL; 7350bbfda8aSnia old = tmp_win->iconmanagerlist; 7360bbfda8aSnia while(ip != NULL) { 7370bbfda8aSnia int h; 7380bbfda8aSnia unsigned long valuemask; /* mask for create windows */ 7390bbfda8aSnia XSetWindowAttributes attributes; /* attributes for create windows */ 7400bbfda8aSnia 7410bbfda8aSnia /* Is the window in this workspace? */ 7420bbfda8aSnia if((tmp_win->occupation & ip->twm_win->occupation) == 0) { 7430bbfda8aSnia /* Nope, skip onward */ 7440bbfda8aSnia ip = ip->nextv; 7450bbfda8aSnia continue; 7460bbfda8aSnia } 7470bbfda8aSnia 7480bbfda8aSnia /* Yep, create entry and stick it in */ 7490bbfda8aSnia tmp = calloc(1, sizeof(WList)); 7500bbfda8aSnia tmp->iconmgr = ip; 7510bbfda8aSnia tmp->twm = tmp_win; 7520bbfda8aSnia 7530bbfda8aSnia InsertInIconManager(ip, tmp, tmp_win); 7540bbfda8aSnia 7550bbfda8aSnia /* IM color settings, shared worldwide */ 7560bbfda8aSnia tmp->cp.fore = Scr->IconManagerC.fore; 7570bbfda8aSnia tmp->cp.back = Scr->IconManagerC.back; 7580bbfda8aSnia tmp->highlight = Scr->IconManagerHighlight; 7590bbfda8aSnia 7600bbfda8aSnia GetColorFromList(Scr->IconManagerFL, tmp_win->name, 7610bbfda8aSnia &tmp_win->class, &tmp->cp.fore); 7620bbfda8aSnia GetColorFromList(Scr->IconManagerBL, tmp_win->name, 7630bbfda8aSnia &tmp_win->class, &tmp->cp.back); 7640bbfda8aSnia GetColorFromList(Scr->IconManagerHighlightL, tmp_win->name, 7650bbfda8aSnia &tmp_win->class, &tmp->highlight); 7660bbfda8aSnia 7670bbfda8aSnia /* 7680bbfda8aSnia * If we're using 3d icon managers, each line item has its own 7690bbfda8aSnia * icon; see comment on creation function for details. With 2d 7700bbfda8aSnia * icon managers, it's the same for all of them, so it's stored 7710bbfda8aSnia * screen-wide. 7720bbfda8aSnia */ 7730bbfda8aSnia if(Scr->use3Diconmanagers) { 7740bbfda8aSnia if(!Scr->BeNiceToColormap) { 7750bbfda8aSnia GetShadeColors(&tmp->cp); 7760bbfda8aSnia } 7770bbfda8aSnia tmp->iconifypm = Create3DIconManagerIcon(tmp->cp); 7780bbfda8aSnia } 7790bbfda8aSnia 7800bbfda8aSnia /* Refigure the height of the whole IM */ 7810bbfda8aSnia h = Scr->IconManagerFont.avg_height 7820bbfda8aSnia + 2 * (ICON_MGR_OBORDER + ICON_MGR_OBORDER); 7830bbfda8aSnia if(h < (im_iconified_icon_height + 4)) { 7840bbfda8aSnia h = im_iconified_icon_height + 4; 7850bbfda8aSnia } 7860bbfda8aSnia 7870bbfda8aSnia ip->height = h * ip->count; 7880bbfda8aSnia tmp->me = ip->count; 7890bbfda8aSnia tmp->x = -1; 7900bbfda8aSnia tmp->y = -1; 7910bbfda8aSnia tmp->height = -1; 7920bbfda8aSnia tmp->width = -1; 7930bbfda8aSnia 7940bbfda8aSnia 7950bbfda8aSnia /* Make a window for this row in the IM */ 7960bbfda8aSnia valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); 7970bbfda8aSnia attributes.background_pixel = tmp->cp.back; 7980bbfda8aSnia attributes.border_pixel = tmp->cp.back; 7990bbfda8aSnia attributes.event_mask = (KeyPressMask | ButtonPressMask | 8000bbfda8aSnia ButtonReleaseMask | ExposureMask); 8010bbfda8aSnia if(Scr->IconManagerFocus) { 8020bbfda8aSnia attributes.event_mask |= (EnterWindowMask | LeaveWindowMask); 8030bbfda8aSnia } 8040bbfda8aSnia attributes.cursor = Scr->IconMgrCursor; 8050bbfda8aSnia tmp->w = XCreateWindow(dpy, ip->w, 0, 0, 1, 8060bbfda8aSnia h, 0, 8070bbfda8aSnia CopyFromParent, CopyFromParent, 8080bbfda8aSnia CopyFromParent, 8090bbfda8aSnia valuemask, &attributes); 8100bbfda8aSnia 8110bbfda8aSnia 8120bbfda8aSnia /* Setup the icon for it too */ 8130bbfda8aSnia valuemask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); 8140bbfda8aSnia attributes.background_pixel = tmp->cp.back; 8150bbfda8aSnia attributes.border_pixel = Scr->Black; 8160bbfda8aSnia attributes.event_mask = (ButtonReleaseMask | ButtonPressMask 8170bbfda8aSnia | ExposureMask); 8180bbfda8aSnia attributes.cursor = Scr->ButtonCursor; 8190bbfda8aSnia /* The precise location will be set it in PackIconManager. */ 8200bbfda8aSnia tmp->icon = XCreateWindow(dpy, tmp->w, 0, 0, 8210bbfda8aSnia im_iconified_icon_width, 8220bbfda8aSnia im_iconified_icon_height, 8230bbfda8aSnia 0, CopyFromParent, 8240bbfda8aSnia CopyFromParent, 8250bbfda8aSnia CopyFromParent, 8260bbfda8aSnia valuemask, &attributes); 8270bbfda8aSnia 8280bbfda8aSnia 8290bbfda8aSnia /* Bump housekeeping for the IM */ 8300bbfda8aSnia ip->count += 1; 8310bbfda8aSnia PackIconManager(ip); 8320bbfda8aSnia if(Scr->WindowMask) { 8330bbfda8aSnia XRaiseWindow(dpy, Scr->WindowMask); 8340bbfda8aSnia } 8350bbfda8aSnia XMapWindow(dpy, tmp->w); 8360bbfda8aSnia 8370bbfda8aSnia XSaveContext(dpy, tmp->w, TwmContext, (XPointer) tmp_win); 8380bbfda8aSnia XSaveContext(dpy, tmp->w, ScreenContext, (XPointer) Scr); 8390bbfda8aSnia XSaveContext(dpy, tmp->icon, TwmContext, (XPointer) tmp_win); 8400bbfda8aSnia XSaveContext(dpy, tmp->icon, ScreenContext, (XPointer) Scr); 8410bbfda8aSnia 8420bbfda8aSnia if(!ip->twm_win->isicon) { 8430bbfda8aSnia if(visible(ip->twm_win)) { 8440bbfda8aSnia SetMapStateProp(ip->twm_win, NormalState); 8450bbfda8aSnia XMapWindow(dpy, ip->w); 8460bbfda8aSnia XMapWindow(dpy, ip->twm_win->frame); 8470bbfda8aSnia } 8480bbfda8aSnia ip->twm_win->mapped = true; 8490bbfda8aSnia } 8500bbfda8aSnia 8510bbfda8aSnia 8520bbfda8aSnia /* 8530bbfda8aSnia * Stick this entry on the head of our list of "IM entries we 8540bbfda8aSnia * created", and loop around to the next WS for this IM. 8550bbfda8aSnia */ 8560bbfda8aSnia tmp->nextv = old; 8570bbfda8aSnia old = tmp; 8580bbfda8aSnia ip = ip->nextv; 8590bbfda8aSnia } 8600bbfda8aSnia 8610bbfda8aSnia /* If we didn't create at least one thing, we're done here */ 8620bbfda8aSnia if(tmp == NULL) { 8630bbfda8aSnia return NULL; 8640bbfda8aSnia } 8650bbfda8aSnia 8660bbfda8aSnia /* Stash where the window is IM-listed */ 8670bbfda8aSnia tmp_win->iconmanagerlist = tmp; 8680bbfda8aSnia 8690bbfda8aSnia /* ??? */ 8700bbfda8aSnia if(! visible(tmp->iconmgr->twm_win)) { 8710bbfda8aSnia old = tmp; 8720bbfda8aSnia tmp = tmp->nextv; 8730bbfda8aSnia while(tmp != NULL) { 8740bbfda8aSnia if(visible(tmp->iconmgr->twm_win)) { 8750bbfda8aSnia break; 8760bbfda8aSnia } 8770bbfda8aSnia old = tmp; 8780bbfda8aSnia tmp = tmp->nextv; 8790bbfda8aSnia } 8800bbfda8aSnia if(tmp != NULL) { 8810bbfda8aSnia old->nextv = tmp->nextv; 8820bbfda8aSnia tmp->nextv = tmp_win->iconmanagerlist; 8830bbfda8aSnia tmp_win->iconmanagerlist = tmp; 8840bbfda8aSnia } 8850bbfda8aSnia } 8860bbfda8aSnia 8870bbfda8aSnia /* Hand back the list places we added */ 8880bbfda8aSnia return tmp_win->iconmanagerlist; 889645f5050Syouri} 890645f5050Syouri 891645f5050Syouri/*********************************************************************** 892645f5050Syouri * 893645f5050Syouri * Procedure: 8940bbfda8aSnia * InsertInIconManager - put an allocated entry into an icon 8950bbfda8aSnia * manager 896645f5050Syouri * 897645f5050Syouri * Inputs: 8980bbfda8aSnia * ip - the icon manager pointer 8990bbfda8aSnia * tmp - the entry to insert 900645f5050Syouri * 901645f5050Syouri *********************************************************************** 902645f5050Syouri */ 903645f5050Syouri 904645f5050Syourivoid InsertInIconManager(IconMgr *ip, WList *tmp, TwmWindow *tmp_win) 905645f5050Syouri{ 9060bbfda8aSnia WList *tmp1; 9070bbfda8aSnia bool added; 9080bbfda8aSnia 9090bbfda8aSnia added = false; 9100bbfda8aSnia if(ip->first == NULL) { 9110bbfda8aSnia ip->first = tmp; 9120bbfda8aSnia tmp->prev = NULL; 9130bbfda8aSnia ip->last = tmp; 9140bbfda8aSnia added = true; 9150bbfda8aSnia } 9160bbfda8aSnia else if(Scr->SortIconMgr) { 9170bbfda8aSnia for(tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) { 9180bbfda8aSnia int compresult; 9190bbfda8aSnia if(Scr->CaseSensitive) { 9200bbfda8aSnia compresult = strcmp(tmp_win->icon_name, tmp1->twm->icon_name); 9210bbfda8aSnia } 9220bbfda8aSnia else { 9230bbfda8aSnia compresult = strcasecmp(tmp_win->icon_name, tmp1->twm->icon_name); 9240bbfda8aSnia } 9250bbfda8aSnia if(compresult < 0) { 9260bbfda8aSnia tmp->next = tmp1; 9270bbfda8aSnia tmp->prev = tmp1->prev; 9280bbfda8aSnia tmp1->prev = tmp; 9290bbfda8aSnia if(tmp->prev == NULL) { 9300bbfda8aSnia ip->first = tmp; 9310bbfda8aSnia } 9320bbfda8aSnia else { 9330bbfda8aSnia tmp->prev->next = tmp; 9340bbfda8aSnia } 9350bbfda8aSnia added = true; 9360bbfda8aSnia break; 9370bbfda8aSnia } 9380bbfda8aSnia } 9390bbfda8aSnia } 9400bbfda8aSnia 9410bbfda8aSnia if(!added) { 9420bbfda8aSnia ip->last->next = tmp; 9430bbfda8aSnia tmp->prev = ip->last; 9440bbfda8aSnia ip->last = tmp; 9450bbfda8aSnia } 946645f5050Syouri} 947645f5050Syouri 948645f5050Syourivoid RemoveFromIconManager(IconMgr *ip, WList *tmp) 949645f5050Syouri{ 9500bbfda8aSnia if(tmp->prev == NULL) { 9510bbfda8aSnia ip->first = tmp->next; 9520bbfda8aSnia } 9530bbfda8aSnia else { 9540bbfda8aSnia tmp->prev->next = tmp->next; 9550bbfda8aSnia } 9560bbfda8aSnia 9570bbfda8aSnia if(tmp->next == NULL) { 9580bbfda8aSnia ip->last = tmp->prev; 9590bbfda8aSnia } 9600bbfda8aSnia else { 9610bbfda8aSnia tmp->next->prev = tmp->prev; 9620bbfda8aSnia } 9630bbfda8aSnia 9640bbfda8aSnia /* pebl: If the list was the current and tmp was the last in the list 9650bbfda8aSnia reset current list */ 9660bbfda8aSnia if(Current == tmp) { 9670bbfda8aSnia Current = ip->first; 9680bbfda8aSnia } 969645f5050Syouri} 970645f5050Syouri 971645f5050Syouri/*********************************************************************** 972645f5050Syouri * 973645f5050Syouri * Procedure: 9740bbfda8aSnia * RemoveIconManager - remove a window from the icon manager 975645f5050Syouri * 976645f5050Syouri * Inputs: 9770bbfda8aSnia * tmp_win - the TwmWindow structure 978645f5050Syouri * 979645f5050Syouri *********************************************************************** 980645f5050Syouri */ 981645f5050Syouri 982645f5050Syourivoid RemoveIconManager(TwmWindow *tmp_win) 983645f5050Syouri{ 9840bbfda8aSnia IconMgr *ip; 9850bbfda8aSnia WList *tmp, *tmp1, *save; 9860bbfda8aSnia 9870bbfda8aSnia if(tmp_win->iconmanagerlist == NULL) { 9880bbfda8aSnia return; 9890bbfda8aSnia } 9900bbfda8aSnia 9910bbfda8aSnia tmp = tmp_win->iconmanagerlist; 9920bbfda8aSnia tmp1 = NULL; 9930bbfda8aSnia 9940bbfda8aSnia while(tmp != NULL) { 9950bbfda8aSnia ip = tmp->iconmgr; 9960bbfda8aSnia if((tmp_win->occupation & ip->twm_win->occupation) != 0) { 9970bbfda8aSnia tmp1 = tmp; 9980bbfda8aSnia tmp = tmp->nextv; 9990bbfda8aSnia continue; 10000bbfda8aSnia } 10010bbfda8aSnia RemoveFromIconManager(ip, tmp); 10020bbfda8aSnia 10030bbfda8aSnia XDeleteContext(dpy, tmp->icon, TwmContext); 10040bbfda8aSnia XDeleteContext(dpy, tmp->icon, ScreenContext); 10050bbfda8aSnia XDestroyWindow(dpy, tmp->icon); 10060bbfda8aSnia XDeleteContext(dpy, tmp->w, TwmContext); 10070bbfda8aSnia XDeleteContext(dpy, tmp->w, ScreenContext); 10080bbfda8aSnia XDestroyWindow(dpy, tmp->w); 10090bbfda8aSnia ip->count -= 1; 10100bbfda8aSnia 10110bbfda8aSnia PackIconManager(ip); 10120bbfda8aSnia 10130bbfda8aSnia if(ip->count == 0) { 10140bbfda8aSnia XUnmapWindow(dpy, ip->twm_win->frame); 10150bbfda8aSnia ip->twm_win->mapped = false; 10160bbfda8aSnia } 10170bbfda8aSnia if(tmp1 == NULL) { 10180bbfda8aSnia tmp_win->iconmanagerlist = tmp_win->iconmanagerlist->nextv; 10190bbfda8aSnia } 10200bbfda8aSnia else { 10210bbfda8aSnia tmp1->nextv = tmp->nextv; 10220bbfda8aSnia } 10230bbfda8aSnia 10240bbfda8aSnia save = tmp; 10250bbfda8aSnia tmp = tmp->nextv; 10260bbfda8aSnia free(save); 10270bbfda8aSnia } 1028645f5050Syouri} 1029645f5050Syouri 10300bbfda8aSniavoid CurrentIconManagerEntry(WList *current) 1031645f5050Syouri{ 10320bbfda8aSnia Current = current; 1033645f5050Syouri} 1034645f5050Syouri 1035645f5050Syourivoid ActiveIconManager(WList *active) 1036645f5050Syouri{ 10370bbfda8aSnia active->active = true; 10380bbfda8aSnia Active = active; 10390bbfda8aSnia Active->iconmgr->active = active; 10400bbfda8aSnia Current = Active; 10410bbfda8aSnia DrawIconManagerBorder(active, false); 1042645f5050Syouri} 1043645f5050Syouri 1044645f5050Syourivoid NotActiveIconManager(WList *active) 1045645f5050Syouri{ 10460bbfda8aSnia active->active = false; 10470bbfda8aSnia DrawIconManagerBorder(active, false); 1048645f5050Syouri} 1049645f5050Syouri 10500bbfda8aSniavoid DrawIconManagerBorder(WList *tmp, bool fill) 1051645f5050Syouri{ 10520bbfda8aSnia if(Scr->use3Diconmanagers) { 10530bbfda8aSnia Draw3DBorder(tmp->w, 0, 0, tmp->width, tmp->height, 10540bbfda8aSnia Scr->IconManagerShadowDepth, tmp->cp, 10550bbfda8aSnia (tmp->active && Scr->Highlight ? on : off), 10560bbfda8aSnia fill, false); 10570bbfda8aSnia } 10580bbfda8aSnia else { 10590bbfda8aSnia XSetForeground(dpy, Scr->NormalGC, tmp->cp.fore); 10600bbfda8aSnia XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 2, 2, tmp->width - 5, 10610bbfda8aSnia tmp->height - 5); 10620bbfda8aSnia 10630bbfda8aSnia XSetForeground(dpy, Scr->NormalGC, 10640bbfda8aSnia (tmp->active && Scr->Highlight 10650bbfda8aSnia ? tmp->highlight : tmp->cp.back)); 10660bbfda8aSnia 10670bbfda8aSnia XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 0, 0, tmp->width - 1, 10680bbfda8aSnia tmp->height - 1); 10690bbfda8aSnia XDrawRectangle(dpy, tmp->w, Scr->NormalGC, 1, 1, tmp->width - 3, 10700bbfda8aSnia tmp->height - 3); 10710bbfda8aSnia } 1072645f5050Syouri} 1073645f5050Syouri 1074645f5050Syouri/*********************************************************************** 1075645f5050Syouri * 1076645f5050Syouri * Procedure: 10770bbfda8aSnia * SortIconManager - sort the dude 1078645f5050Syouri * 1079645f5050Syouri * Inputs: 10800bbfda8aSnia * ip - a pointer to the icon manager struture 1081645f5050Syouri * 1082645f5050Syouri *********************************************************************** 1083645f5050Syouri */ 1084645f5050Syouri 1085645f5050Syourivoid SortIconManager(IconMgr *ip) 1086645f5050Syouri{ 10870bbfda8aSnia WList *tmp1, *tmp2; 10880bbfda8aSnia int done; 10890bbfda8aSnia 10900bbfda8aSnia if(ip == NULL) { 10910bbfda8aSnia ip = Active->iconmgr; 10920bbfda8aSnia } 10930bbfda8aSnia 10940bbfda8aSnia done = false; 10950bbfda8aSnia do { 10960bbfda8aSnia for(tmp1 = ip->first; tmp1 != NULL; tmp1 = tmp1->next) { 10970bbfda8aSnia int compresult; 10980bbfda8aSnia if((tmp2 = tmp1->next) == NULL) { 10990bbfda8aSnia done = true; 11000bbfda8aSnia break; 11010bbfda8aSnia } 11020bbfda8aSnia if(Scr->CaseSensitive) { 11030bbfda8aSnia compresult = strcmp(tmp1->twm->icon_name, tmp2->twm->icon_name); 11040bbfda8aSnia } 11050bbfda8aSnia else { 11060bbfda8aSnia compresult = strcasecmp(tmp1->twm->icon_name, tmp2->twm->icon_name); 11070bbfda8aSnia } 11080bbfda8aSnia if(compresult > 0) { 11090bbfda8aSnia /* take it out and put it back in */ 11100bbfda8aSnia RemoveFromIconManager(ip, tmp2); 11110bbfda8aSnia InsertInIconManager(ip, tmp2, tmp2->twm); 11120bbfda8aSnia break; 11130bbfda8aSnia } 11140bbfda8aSnia } 11150bbfda8aSnia } 11160bbfda8aSnia while(!done); 11170bbfda8aSnia PackIconManager(ip); 1118645f5050Syouri} 1119645f5050Syouri 1120645f5050Syouri/*********************************************************************** 1121645f5050Syouri * 1122645f5050Syouri * Procedure: 11230bbfda8aSnia * PackIconManager - pack the icon manager windows following 11240bbfda8aSnia * an addition or deletion 1125645f5050Syouri * 1126645f5050Syouri * Inputs: 11270bbfda8aSnia * ip - a pointer to the icon manager struture 1128645f5050Syouri * 1129645f5050Syouri *********************************************************************** 1130645f5050Syouri */ 1131645f5050Syouri 11320bbfda8aSniavoid PackIconManagers(void) 11330bbfda8aSnia{ 11340bbfda8aSnia TwmWindow *twm_win; 11350bbfda8aSnia 11360bbfda8aSnia for(twm_win = Scr->FirstWindow; twm_win != NULL; twm_win = twm_win->next) { 11370bbfda8aSnia if(twm_win->iconmgrp) { 11380bbfda8aSnia PackIconManager(twm_win->iconmgrp); 11390bbfda8aSnia } 11400bbfda8aSnia } 11410bbfda8aSnia} 11420bbfda8aSnia 1143645f5050Syourivoid PackIconManager(IconMgr *ip) 1144645f5050Syouri{ 11450bbfda8aSnia int newwidth, i, row, col, maxcol, colinc, rowinc, wheight, wwidth; 11460bbfda8aSnia int new_x, new_y; 11470bbfda8aSnia int savewidth; 11480bbfda8aSnia WList *tmp; 11490bbfda8aSnia int mask; 11500bbfda8aSnia 11510bbfda8aSnia wheight = Scr->IconManagerFont.avg_height 11520bbfda8aSnia + 2 * (ICON_MGR_OBORDER + ICON_MGR_IBORDER); 11530bbfda8aSnia if(wheight < (im_iconified_icon_height + 4)) { 11540bbfda8aSnia wheight = im_iconified_icon_height + 4; 11550bbfda8aSnia } 11560bbfda8aSnia 11570bbfda8aSnia wwidth = ip->width / ip->columns; 11580bbfda8aSnia 11590bbfda8aSnia rowinc = wheight; 11600bbfda8aSnia colinc = wwidth; 11610bbfda8aSnia 11620bbfda8aSnia row = 0; 11630bbfda8aSnia col = ip->columns; 11640bbfda8aSnia maxcol = 0; 11650bbfda8aSnia for(i = 0, tmp = ip->first; tmp != NULL; i++, tmp = tmp->next) { 11660bbfda8aSnia tmp->me = i; 11670bbfda8aSnia if(++col >= ip->columns) { 11680bbfda8aSnia col = 0; 11690bbfda8aSnia row += 1; 11700bbfda8aSnia } 11710bbfda8aSnia if(col > maxcol) { 11720bbfda8aSnia maxcol = col; 11730bbfda8aSnia } 11740bbfda8aSnia 11750bbfda8aSnia new_x = col * colinc; 11760bbfda8aSnia new_y = (row - 1) * rowinc; 11770bbfda8aSnia 11780bbfda8aSnia /* if the position or size has not changed, don't touch it */ 11790bbfda8aSnia if(tmp->x != new_x || tmp->y != new_y || 11800bbfda8aSnia tmp->width != wwidth || tmp->height != wheight) { 11810bbfda8aSnia XMoveResizeWindow(dpy, tmp->w, new_x, new_y, wwidth, wheight); 11820bbfda8aSnia if(tmp->height != wheight) 11830bbfda8aSnia XMoveWindow(dpy, tmp->icon, ICON_MGR_OBORDER + ICON_MGR_IBORDER, 11840bbfda8aSnia (wheight - im_iconified_icon_height) / 2); 11850bbfda8aSnia 11860bbfda8aSnia tmp->row = row - 1; 11870bbfda8aSnia tmp->col = col; 11880bbfda8aSnia tmp->x = new_x; 11890bbfda8aSnia tmp->y = new_y; 11900bbfda8aSnia tmp->width = wwidth; 11910bbfda8aSnia tmp->height = wheight; 11920bbfda8aSnia } 11930bbfda8aSnia } 11940bbfda8aSnia maxcol += 1; 11950bbfda8aSnia 11960bbfda8aSnia ip->cur_rows = row; 11970bbfda8aSnia ip->cur_columns = maxcol; 11980bbfda8aSnia ip->height = row * rowinc; 11990bbfda8aSnia if(ip->height == 0) { 12000bbfda8aSnia ip->height = rowinc; 12010bbfda8aSnia } 12020bbfda8aSnia newwidth = maxcol * colinc; 12030bbfda8aSnia if(newwidth == 0) { 12040bbfda8aSnia newwidth = colinc; 12050bbfda8aSnia } 12060bbfda8aSnia 12070bbfda8aSnia XResizeWindow(dpy, ip->w, newwidth, ip->height); 12080bbfda8aSnia 1209df1c27a6Snia mask = RLayoutXParseGeometry(Scr->Layout, ip->geometry, &JunkX, &JunkY, 1210df1c27a6Snia &JunkWidth, &JunkHeight); 12110bbfda8aSnia if(mask & XNegative) { 12120bbfda8aSnia ip->twm_win->frame_x += ip->twm_win->frame_width - newwidth - 12130bbfda8aSnia 2 * ip->twm_win->frame_bw3D; 12140bbfda8aSnia } 12150bbfda8aSnia if(mask & YNegative) { 12160bbfda8aSnia ip->twm_win->frame_y += ip->twm_win->frame_height - ip->height - 12170bbfda8aSnia 2 * ip->twm_win->frame_bw3D - ip->twm_win->title_height; 12180bbfda8aSnia } 12190bbfda8aSnia savewidth = ip->width; 12200bbfda8aSnia if(ip->twm_win) 12210bbfda8aSnia SetupWindow(ip->twm_win, 12220bbfda8aSnia ip->twm_win->frame_x, ip->twm_win->frame_y, 12230bbfda8aSnia newwidth + 2 * ip->twm_win->frame_bw3D, 12240bbfda8aSnia ip->height + ip->twm_win->title_height + 2 * ip->twm_win->frame_bw3D, -1); 12250bbfda8aSnia ip->width = savewidth; 12260bbfda8aSnia} 12270bbfda8aSnia 12280bbfda8aSniavoid dump_iconmanager(IconMgr *mgr, char *label) 12290bbfda8aSnia{ 12300bbfda8aSnia fprintf(stderr, "IconMgr %s %p name='%s' geom='%s'\n", 12310bbfda8aSnia label, 12320bbfda8aSnia mgr, 12330bbfda8aSnia mgr->name, 12340bbfda8aSnia mgr->geometry); 12350bbfda8aSnia fprintf(stderr, "next = %p, prev = %p, lasti = %p, nextv = %p\n", 12360bbfda8aSnia mgr->next, 12370bbfda8aSnia mgr->prev, 12380bbfda8aSnia mgr->lasti, 12390bbfda8aSnia mgr->nextv); 12400bbfda8aSnia} 12410bbfda8aSnia 12420bbfda8aSnia 12430bbfda8aSnia/* 12440bbfda8aSnia * Draw the window name into the icon manager line 12450bbfda8aSnia */ 12460bbfda8aSniavoid 12470bbfda8aSniaDrawIconManagerIconName(TwmWindow *tmp_win) 12480bbfda8aSnia{ 12490bbfda8aSnia WList *iconmanagerlist = tmp_win->iconmanagerlist; 12500bbfda8aSnia XRectangle ink_rect, logical_rect; 12510bbfda8aSnia 12520bbfda8aSnia XmbTextExtents(Scr->IconManagerFont.font_set, 12530bbfda8aSnia tmp_win->icon_name, strlen(tmp_win->icon_name), 12540bbfda8aSnia &ink_rect, &logical_rect); 12550bbfda8aSnia 12560bbfda8aSnia if(UpdateFont(&Scr->IconManagerFont, logical_rect.height)) { 12570bbfda8aSnia PackIconManagers(); 12580bbfda8aSnia } 12590bbfda8aSnia 1260df1c27a6Snia // Write in the title 12610bbfda8aSnia FB(iconmanagerlist->cp.fore, iconmanagerlist->cp.back); 12620bbfda8aSnia 12630bbfda8aSnia /* XXX This is a completely absurd way of writing this */ 12640bbfda8aSnia ((Scr->use3Diconmanagers && (Scr->Monochrome != COLOR)) ? 12650bbfda8aSnia XmbDrawImageString : XmbDrawString) 12660bbfda8aSnia (dpy, 12670bbfda8aSnia iconmanagerlist->w, 12680bbfda8aSnia Scr->IconManagerFont.font_set, 12690bbfda8aSnia Scr->NormalGC, 12700bbfda8aSnia iconmgr_textx, 12710bbfda8aSnia (Scr->IconManagerFont.avg_height - logical_rect.height) / 2 12720bbfda8aSnia + (- logical_rect.y) 12730bbfda8aSnia + ICON_MGR_OBORDER 12740bbfda8aSnia + ICON_MGR_IBORDER, 12750bbfda8aSnia tmp_win->icon_name, 12760bbfda8aSnia strlen(tmp_win->icon_name)); 1277df1c27a6Snia 1278df1c27a6Snia // Draw the border around it. Our "border" isn't an X border, it's 1279df1c27a6Snia // just our own drawing inside the X window. Since XmbDrawString() 1280df1c27a6Snia // believes it has all the space in the window to fill, it might 1281df1c27a6Snia // scribble into the space where we're drawing the border, so draw 1282df1c27a6Snia // the border after the text to cover it up. 1283df1c27a6Snia DrawIconManagerBorder(iconmanagerlist, false); 12840bbfda8aSnia} 12850bbfda8aSnia 12860bbfda8aSnia 12870bbfda8aSnia/* 12880bbfda8aSnia * Copy the icon into the icon manager for a window that's iconified. 12890bbfda8aSnia * This is slightly different for the 3d vs 2d case, since the 3d is just 12900bbfda8aSnia * copying a pixmap in, while the 2d is drawing a bitmap in with the 12910bbfda8aSnia * fg/bg colors appropriate to the line. 12920bbfda8aSnia */ 12930bbfda8aSniavoid 12940bbfda8aSniaShowIconifiedIcon(TwmWindow *tmp_win) 12950bbfda8aSnia{ 12960bbfda8aSnia WList *iconmanagerlist = tmp_win->iconmanagerlist; 12970bbfda8aSnia 12980bbfda8aSnia if(Scr->use3Diconmanagers && iconmanagerlist->iconifypm) { 12990bbfda8aSnia XCopyArea(dpy, iconmanagerlist->iconifypm, 13000bbfda8aSnia iconmanagerlist->icon, 13010bbfda8aSnia Scr->NormalGC, 0, 0, 13020bbfda8aSnia im_iconified_icon_width, im_iconified_icon_height, 0, 0); 13030bbfda8aSnia } 13040bbfda8aSnia else { 13050bbfda8aSnia FB(iconmanagerlist->cp.fore, iconmanagerlist->cp.back); 13060bbfda8aSnia XCopyPlane(dpy, Scr->siconifyPm, iconmanagerlist->icon, 13070bbfda8aSnia Scr->NormalGC, 0, 0, 13080bbfda8aSnia im_iconified_icon_width, im_iconified_icon_height, 0, 0, 1); 13090bbfda8aSnia } 1310645f5050Syouri} 1311