1645f5050Syouri/* 2645f5050Syouri * Copyright 1989 Massachusetts Institute of Technology 30bbfda8aSnia * Copyright 1992 Claude Lecommandeur. 4645f5050Syouri */ 5645f5050Syouri 6645f5050Syouri/********************************************************************** 7645f5050Syouri * 8645f5050Syouri * $XConsortium: icons.c,v 1.22 91/07/12 09:58:38 dave Exp $ 9645f5050Syouri * 10645f5050Syouri * Icon releated routines 11645f5050Syouri * 12645f5050Syouri * 10-Apr-89 Tom LaStrange Initial Version. 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 270bbfda8aSnia#include <X11/extensions/shape.h> 280bbfda8aSnia 290bbfda8aSnia#include "drawing.h" 30645f5050Syouri#include "screen.h" 310bbfda8aSnia#include "iconmgr.h" 32645f5050Syouri#include "icons.h" 330bbfda8aSnia#include "otp.h" 34645f5050Syouri#include "list.h" 35645f5050Syouri#include "parse.h" 36645f5050Syouri#include "util.h" 370bbfda8aSnia#include "animate.h" 380bbfda8aSnia#include "image.h" 390bbfda8aSnia#include "win_utils.h" 400bbfda8aSnia#include "workspace_manager.h" 41df1c27a6Snia#include "xparsegeometry.h" 42df1c27a6Snia 430bbfda8aSnia 440bbfda8aSniastatic void splitIconRegionEntry(IconEntry *ie, RegGravity grav1, 450bbfda8aSnia RegGravity grav2, int w, int h); 460bbfda8aSniastatic void PlaceIcon(TwmWindow *tmp_win, int def_x, int def_y, 470bbfda8aSnia int *final_x, int *final_y); 480bbfda8aSniastatic IconEntry *FindIconEntry(TwmWindow *tmp_win, IconRegion **irp); 490bbfda8aSniastatic IconEntry *prevIconEntry(IconEntry *ie, IconRegion *ir); 500bbfda8aSniastatic void mergeEntries(IconEntry *old, IconEntry *ie); 510bbfda8aSniastatic void ReshapeIcon(Icon *icon); 520bbfda8aSniastatic int roundUp(int v, int multiple); 530bbfda8aSniastatic Image *LookupIconNameOrClass(TwmWindow *tmp_win, Icon *icon, 540bbfda8aSnia char **pattern); 55645f5050Syouri 56645f5050Syouri 57645f5050Syouri 580bbfda8aSnia/* 590bbfda8aSnia **************************************************************** 600bbfda8aSnia * 610bbfda8aSnia * First some bits related to figuring out where icons go. Lots of 620bbfda8aSnia * IconRegion handling stuff, handling of IconEntry tracking, etc. 630bbfda8aSnia * 640bbfda8aSnia **************************************************************** 650bbfda8aSnia */ 660bbfda8aSnia 670bbfda8aSnia 680bbfda8aSnia/* 690bbfda8aSnia * This function operates in very weird and obtuse ways, especially in 700bbfda8aSnia * how it handles vertical vs. horizontal in weird recursive calls. Part 710bbfda8aSnia * of this is what previously allowed specs with "hgrav vgrav" instead of 720bbfda8aSnia * the proper "vgrav hgrav" to sorta-work. This should be broken up at 730bbfda8aSnia * some point into clean h/v functions, but because of the recursion it's 740bbfda8aSnia * not exactly trivial. The parsing code now enforces v/h, so at least 750bbfda8aSnia * things can be known to come in in the right order initially. Revisit 760bbfda8aSnia * someday. 770bbfda8aSnia */ 780bbfda8aSniastatic void 790bbfda8aSniasplitIconRegionEntry(IconEntry *ie, RegGravity grav1, RegGravity grav2, 800bbfda8aSnia int w, int h) 81645f5050Syouri{ 820bbfda8aSnia switch(grav1) { 830bbfda8aSnia case GRAV_NORTH: 840bbfda8aSnia case GRAV_SOUTH: 850bbfda8aSnia if(w != ie->w) { 860bbfda8aSnia splitIconRegionEntry(ie, grav2, grav1, w, ie->h); 870bbfda8aSnia } 880bbfda8aSnia if(h != ie->h) { 890bbfda8aSnia IconEntry *new = calloc(1, sizeof(IconEntry)); 900bbfda8aSnia new->next = ie->next; 910bbfda8aSnia ie->next = new; 920bbfda8aSnia new->x = ie->x; 930bbfda8aSnia new->h = (ie->h - h); 940bbfda8aSnia new->w = ie->w; 950bbfda8aSnia ie->h = h; 960bbfda8aSnia if(grav1 == GRAV_SOUTH) { 970bbfda8aSnia new->y = ie->y; 980bbfda8aSnia ie->y = new->y + new->h; 990bbfda8aSnia } 1000bbfda8aSnia else { 1010bbfda8aSnia new->y = ie->y + ie->h; 1020bbfda8aSnia } 1030bbfda8aSnia } 1040bbfda8aSnia break; 1050bbfda8aSnia case GRAV_EAST: 1060bbfda8aSnia case GRAV_WEST: 1070bbfda8aSnia if(h != ie->h) { 1080bbfda8aSnia splitIconRegionEntry(ie, grav2, grav1, ie->w, h); 1090bbfda8aSnia } 1100bbfda8aSnia if(w != ie->w) { 1110bbfda8aSnia IconEntry *new = calloc(1, sizeof(IconEntry)); 1120bbfda8aSnia new->next = ie->next; 1130bbfda8aSnia ie->next = new; 1140bbfda8aSnia new->y = ie->y; 1150bbfda8aSnia new->w = (ie->w - w); 1160bbfda8aSnia new->h = ie->h; 1170bbfda8aSnia ie->w = w; 1180bbfda8aSnia if(grav1 == GRAV_EAST) { 1190bbfda8aSnia new->x = ie->x; 1200bbfda8aSnia ie->x = new->x + new->w; 1210bbfda8aSnia } 1220bbfda8aSnia else { 1230bbfda8aSnia new->x = ie->x + ie->w; 1240bbfda8aSnia } 1250bbfda8aSnia } 1260bbfda8aSnia break; 1270bbfda8aSnia } 128645f5050Syouri} 129645f5050Syouri 1300bbfda8aSnia 1310bbfda8aSnia/* 1320bbfda8aSnia * Backend for parsing IconRegion config 1330bbfda8aSnia */ 1340bbfda8aSnianame_list ** 1350bbfda8aSniaAddIconRegion(const char *geom, RegGravity grav1, RegGravity grav2, 1360bbfda8aSnia int stepx, int stepy, 1370bbfda8aSnia const char *ijust, const char *just, const char *align) 138645f5050Syouri{ 1390bbfda8aSnia IconRegion *ir; 1400bbfda8aSnia int mask, tmp; 1410bbfda8aSnia 1420bbfda8aSnia ir = malloc(sizeof(IconRegion)); 1430bbfda8aSnia ir->next = NULL; 1440bbfda8aSnia 1450bbfda8aSnia if(Scr->LastRegion) { 1460bbfda8aSnia Scr->LastRegion->next = ir; 1470bbfda8aSnia } 1480bbfda8aSnia Scr->LastRegion = ir; 1490bbfda8aSnia if(!Scr->FirstRegion) { 1500bbfda8aSnia Scr->FirstRegion = ir; 1510bbfda8aSnia } 1520bbfda8aSnia 1530bbfda8aSnia ir->entries = NULL; 1540bbfda8aSnia ir->clientlist = NULL; 1550bbfda8aSnia ir->grav1 = grav1; 1560bbfda8aSnia ir->grav2 = grav2; 1570bbfda8aSnia if(stepx <= 0) { 1580bbfda8aSnia stepx = 1; 1590bbfda8aSnia } 1600bbfda8aSnia if(stepy <= 0) { 1610bbfda8aSnia stepy = 1; 1620bbfda8aSnia } 1630bbfda8aSnia ir->stepx = stepx; 1640bbfda8aSnia ir->stepy = stepy; 1650bbfda8aSnia ir->x = ir->y = ir->w = ir->h = 0; 1660bbfda8aSnia 167df1c27a6Snia mask = RLayoutXParseGeometry(Scr->Layout, geom, &ir->x, &ir->y, 168df1c27a6Snia (unsigned int *)&ir->w, (unsigned int *)&ir->h); 1690bbfda8aSnia 1700bbfda8aSnia if(mask & XNegative) { 1710bbfda8aSnia ir->x += Scr->rootw - ir->w; 1720bbfda8aSnia } 1730bbfda8aSnia if(mask & YNegative) { 1740bbfda8aSnia ir->y += Scr->rooth - ir->h; 1750bbfda8aSnia } 1760bbfda8aSnia 1770bbfda8aSnia ir->entries = calloc(1, sizeof(IconEntry)); 1780bbfda8aSnia ir->entries->x = ir->x; 1790bbfda8aSnia ir->entries->y = ir->y; 1800bbfda8aSnia ir->entries->w = ir->w; 1810bbfda8aSnia ir->entries->h = ir->h; 1820bbfda8aSnia 1830bbfda8aSnia if((tmp = ParseTitleJustification(ijust)) < 0) { 1840bbfda8aSnia twmrc_error_prefix(); 1850bbfda8aSnia fprintf(stderr, "ignoring invalid IconRegion argument \"%s\"\n", ijust); 1860bbfda8aSnia tmp = TJ_UNDEF; 1870bbfda8aSnia } 1880bbfda8aSnia ir->TitleJustification = tmp; 1890bbfda8aSnia 1900bbfda8aSnia if((tmp = ParseIRJustification(just)) < 0) { 1910bbfda8aSnia twmrc_error_prefix(); 1920bbfda8aSnia fprintf(stderr, "ignoring invalid IconRegion argument \"%s\"\n", just); 1930bbfda8aSnia tmp = IRJ_UNDEF; 1940bbfda8aSnia } 1950bbfda8aSnia ir->Justification = tmp; 1960bbfda8aSnia 1970bbfda8aSnia if((tmp = ParseAlignement(align)) < 0) { 1980bbfda8aSnia twmrc_error_prefix(); 1990bbfda8aSnia fprintf(stderr, "ignoring invalid IconRegion argument \"%s\"\n", align); 2000bbfda8aSnia tmp = IRA_UNDEF; 2010bbfda8aSnia } 2020bbfda8aSnia ir->Alignement = tmp; 2030bbfda8aSnia 2040bbfda8aSnia return(&(ir->clientlist)); 205645f5050Syouri} 206645f5050Syouri 2070bbfda8aSnia 2080bbfda8aSnia/* 2090bbfda8aSnia * Figure out where to put a window's icon based on the IconRegion 2100bbfda8aSnia * specifications given in config. Passed def_[xy] which are used 2110bbfda8aSnia * if we don't find a better location ourselves. Returns the chosen 2120bbfda8aSnia * location in final_[xy], and also sets the IconRegion in tmp_win->icon 2130bbfda8aSnia * if we chose one. 2140bbfda8aSnia */ 2150bbfda8aSniastatic void 2160bbfda8aSniaPlaceIcon(TwmWindow *tmp_win, int def_x, int def_y, 2170bbfda8aSnia int *final_x, int *final_y) 218645f5050Syouri{ 2190bbfda8aSnia IconRegion *ir, *oldir; 2200bbfda8aSnia IconEntry *ie; 2210bbfda8aSnia int w, h; 2220bbfda8aSnia 2230bbfda8aSnia const int iconWidth = tmp_win->icon->border_width * 2 2240bbfda8aSnia + (Scr->ShrinkIconTitles ? tmp_win->icon->width 2250bbfda8aSnia : tmp_win->icon->w_width); 2260bbfda8aSnia const int iconHeight = tmp_win->icon->border_width * 2 2270bbfda8aSnia + tmp_win->icon->w_height; 2280bbfda8aSnia 2290bbfda8aSnia /* 2300bbfda8aSnia * First, check to see if the window is in a region's client list 2310bbfda8aSnia * (i.e., the win-list on an IconRegion specifier in the config). 2320bbfda8aSnia */ 2330bbfda8aSnia ie = NULL; 2340bbfda8aSnia for(ir = Scr->FirstRegion; ir; ir = ir->next) { 2350bbfda8aSnia if(LookInList(ir->clientlist, tmp_win->name, &tmp_win->class)) { 2360bbfda8aSnia /* 2370bbfda8aSnia * Found one that claims it. Figure the necessary local 2380bbfda8aSnia * size, based on the icon's side itself and the grid for 2390bbfda8aSnia * this IR. 2400bbfda8aSnia */ 2410bbfda8aSnia w = roundUp(iconWidth, ir->stepx); 2420bbfda8aSnia h = roundUp(iconHeight, ir->stepy); 2430bbfda8aSnia 2440bbfda8aSnia /* Find a currently-unused region that's big enough */ 2450bbfda8aSnia for(ie = ir->entries; ie; ie = ie->next) { 2460bbfda8aSnia if(ie->used) { 2470bbfda8aSnia continue; 2480bbfda8aSnia } 2490bbfda8aSnia if(ie->w >= w && ie->h >= h) { 2500bbfda8aSnia /* Bingo */ 2510bbfda8aSnia break; 2520bbfda8aSnia } 2530bbfda8aSnia } 2540bbfda8aSnia 2550bbfda8aSnia /* If we found one, we're done here */ 2560bbfda8aSnia if(ie) { 2570bbfda8aSnia break; 2580bbfda8aSnia } 2590bbfda8aSnia } 2600bbfda8aSnia } 2610bbfda8aSnia 2620bbfda8aSnia 2630bbfda8aSnia /* 2640bbfda8aSnia * If we found a slot in a region claiming it, ie is set to the 2650bbfda8aSnia * IconEntry. If not, start over and find the first available berth. 2660bbfda8aSnia */ 2670bbfda8aSnia if(!ie) { 2680bbfda8aSnia for(ir = Scr->FirstRegion; ir; ir = ir->next) { 2690bbfda8aSnia w = roundUp(iconWidth, ir->stepx); 2700bbfda8aSnia h = roundUp(iconHeight, ir->stepy); 2710bbfda8aSnia for(ie = ir->entries; ie; ie = ie->next) { 2720bbfda8aSnia if(ie->used) { 2730bbfda8aSnia continue; 2740bbfda8aSnia } 2750bbfda8aSnia if(ie->w >= w && ie->h >= h) { 2760bbfda8aSnia /* Bingo */ 2770bbfda8aSnia break; 2780bbfda8aSnia } 2790bbfda8aSnia } 2800bbfda8aSnia if(ie) { 2810bbfda8aSnia break; 2820bbfda8aSnia } 2830bbfda8aSnia } 2840bbfda8aSnia } 2850bbfda8aSnia 2860bbfda8aSnia /* Stash for comparison */ 2870bbfda8aSnia oldir = tmp_win->icon->ir; 2880bbfda8aSnia 2890bbfda8aSnia /* 2900bbfda8aSnia * If we found an appropriate region, use it. Else, we have no 2910bbfda8aSnia * better idea, so use the x/y coords the caller passed us as our 2920bbfda8aSnia * basis. 2930bbfda8aSnia */ 2940bbfda8aSnia if(ie) { 2950bbfda8aSnia /* XXX whatever sIRE() does */ 2960bbfda8aSnia splitIconRegionEntry(ie, ir->grav1, ir->grav2, w, h); 2970bbfda8aSnia 2980bbfda8aSnia /* Adjust horizontal positioning based on IconRegionJustification */ 2990bbfda8aSnia switch(ir->Justification) { 3000bbfda8aSnia case IRJ_LEFT: 3010bbfda8aSnia *final_x = ie->x; 3020bbfda8aSnia break; 3030bbfda8aSnia case IRJ_UNDEF: 3040bbfda8aSnia case IRJ_CENTER: 3050bbfda8aSnia *final_x = ie->x + (ie->w - iconWidth) / 2; 3060bbfda8aSnia break; 3070bbfda8aSnia case IRJ_RIGHT: 3080bbfda8aSnia *final_x = ie->x + ie->w - iconWidth; 3090bbfda8aSnia break; 3100bbfda8aSnia case IRJ_BORDER: 3110bbfda8aSnia if(ir->grav2 == GRAV_EAST) { 3120bbfda8aSnia *final_x = ie->x + ie->w - iconWidth; 3130bbfda8aSnia } 3140bbfda8aSnia else { 3150bbfda8aSnia *final_x = ie->x; 3160bbfda8aSnia } 3170bbfda8aSnia break; 3180bbfda8aSnia } 3190bbfda8aSnia 3200bbfda8aSnia /* And vertical based on IconRegionAlignement */ 3210bbfda8aSnia switch(ir->Alignement) { 3220bbfda8aSnia case IRA_TOP : 3230bbfda8aSnia *final_y = ie->y; 3240bbfda8aSnia break; 3250bbfda8aSnia case IRA_UNDEF : 3260bbfda8aSnia case IRA_CENTER : 3270bbfda8aSnia *final_y = ie->y + (ie->h - iconHeight) / 2; 3280bbfda8aSnia break; 3290bbfda8aSnia case IRA_BOTTOM : 3300bbfda8aSnia *final_y = ie->y + ie->h - iconHeight; 3310bbfda8aSnia break; 3320bbfda8aSnia case IRA_BORDER : 3330bbfda8aSnia if(ir->grav1 == GRAV_SOUTH) { 3340bbfda8aSnia *final_y = ie->y + ie->h - iconHeight; 3350bbfda8aSnia } 3360bbfda8aSnia else { 3370bbfda8aSnia *final_y = ie->y; 3380bbfda8aSnia } 3390bbfda8aSnia break; 3400bbfda8aSnia } 3410bbfda8aSnia 3420bbfda8aSnia /* Tell the win/icon what region it's in, and the entry what's in it */ 3430bbfda8aSnia tmp_win->icon->ir = ir; 3440bbfda8aSnia ie->used = true; 3450bbfda8aSnia ie->twm_win = tmp_win; 3460bbfda8aSnia } 3470bbfda8aSnia else { 3480bbfda8aSnia /* No better idea, tell caller to use theirs */ 3490bbfda8aSnia *final_x = def_x; 3500bbfda8aSnia *final_y = def_y; 3510bbfda8aSnia tmp_win->icon->ir = NULL; 3520bbfda8aSnia return; 3530bbfda8aSnia /* XXX Should we be doing the below in this case too? */ 3540bbfda8aSnia } 3550bbfda8aSnia 3560bbfda8aSnia /* Alterations if ShrinkIconTitles is set */ 3570bbfda8aSnia if(Scr->ShrinkIconTitles && tmp_win->icon->has_title) { 3580bbfda8aSnia *final_x -= GetIconOffset(tmp_win->icon); 3590bbfda8aSnia if(tmp_win->icon->ir != oldir) { 3600bbfda8aSnia ReshapeIcon(tmp_win->icon); 3610bbfda8aSnia } 3620bbfda8aSnia } 3630bbfda8aSnia 364645f5050Syouri return; 365645f5050Syouri} 366645f5050Syouri 3670bbfda8aSnia 3680bbfda8aSnia/* 3690bbfda8aSnia * Look up an IconEntry holding the icon for a given window, and 3700bbfda8aSnia * optionally stash its IconRegion in irp. Used internally in 3710bbfda8aSnia * IconDown(). 3720bbfda8aSnia */ 3730bbfda8aSniastatic IconEntry * 3740bbfda8aSniaFindIconEntry(TwmWindow *tmp_win, IconRegion **irp) 375645f5050Syouri{ 3760bbfda8aSnia IconRegion *ir; 3770bbfda8aSnia IconEntry *ie; 3780bbfda8aSnia 3790bbfda8aSnia for(ir = Scr->FirstRegion; ir; ir = ir->next) { 3800bbfda8aSnia for(ie = ir->entries; ie; ie = ie->next) 3810bbfda8aSnia if(ie->twm_win == tmp_win) { 3820bbfda8aSnia if(irp) { 3830bbfda8aSnia *irp = ir; 3840bbfda8aSnia } 3850bbfda8aSnia return ie; 3860bbfda8aSnia } 3870bbfda8aSnia } 3880bbfda8aSnia return NULL; 389645f5050Syouri} 390645f5050Syouri 3910bbfda8aSnia 3920bbfda8aSnia/* 3930bbfda8aSnia * Find prior IE in list. Used internally in IconDown(). 3940bbfda8aSnia */ 3950bbfda8aSniastatic IconEntry * 3960bbfda8aSniaprevIconEntry(IconEntry *ie, IconRegion *ir) 397645f5050Syouri{ 3980bbfda8aSnia IconEntry *ip; 3990bbfda8aSnia 4000bbfda8aSnia if(ie == ir->entries) { 4010bbfda8aSnia return NULL; 4020bbfda8aSnia } 4030bbfda8aSnia for(ip = ir->entries; ip->next != ie; ip = ip->next) 4040bbfda8aSnia ; 4050bbfda8aSnia return ip; 406645f5050Syouri} 407645f5050Syouri 408645f5050Syouri 4090bbfda8aSnia/* 4100bbfda8aSnia * Merge two adjacent IconEntry's. old is being freed; and is adjacent 4110bbfda8aSnia * to ie. Merge regions together. 4120bbfda8aSnia */ 4130bbfda8aSniastatic void 4140bbfda8aSniamergeEntries(IconEntry *old, IconEntry *ie) 4150bbfda8aSnia{ 4160bbfda8aSnia if(old->y == ie->y) { 4170bbfda8aSnia ie->w = old->w + ie->w; 4180bbfda8aSnia if(old->x < ie->x) { 4190bbfda8aSnia ie->x = old->x; 4200bbfda8aSnia } 4210bbfda8aSnia } 4220bbfda8aSnia else { 4230bbfda8aSnia ie->h = old->h + ie->h; 4240bbfda8aSnia if(old->y < ie->y) { 4250bbfda8aSnia ie->y = old->y; 4260bbfda8aSnia } 4270bbfda8aSnia } 428645f5050Syouri} 429645f5050Syouri 4300bbfda8aSnia 4310bbfda8aSnia 4320bbfda8aSnia 4330bbfda8aSnia/* 4340bbfda8aSnia **************************************************************** 4350bbfda8aSnia * 4360bbfda8aSnia * Next, the bits related to creating and putting together the icon 4370bbfda8aSnia * windows, as well as destroying them. 4380bbfda8aSnia * 4390bbfda8aSnia **************************************************************** 440645f5050Syouri */ 441645f5050Syouri 4420bbfda8aSnia 4430bbfda8aSnia/* 4440bbfda8aSnia * Create the window scaffolding for an icon. Called when we need to 4450bbfda8aSnia * make one, e.g. the first time a window is iconified. 4460bbfda8aSnia */ 4470bbfda8aSniavoid 4480bbfda8aSniaCreateIconWindow(TwmWindow *tmp_win, int def_x, int def_y) 449645f5050Syouri{ 4500bbfda8aSnia unsigned long event_mask; 4510bbfda8aSnia unsigned long valuemask; /* mask for create windows */ 4520bbfda8aSnia XSetWindowAttributes attributes; /* attributes for create windows */ 4530bbfda8aSnia int final_x, final_y; 4540bbfda8aSnia int x; 4550bbfda8aSnia Icon *icon; 4560bbfda8aSnia Image *image = NULL; 4570bbfda8aSnia char *pattern; 4580bbfda8aSnia 4590bbfda8aSnia icon = malloc(sizeof(struct Icon)); 4600bbfda8aSnia 4610bbfda8aSnia icon->otp = NULL; 4620bbfda8aSnia icon->border = Scr->IconBorderColor; 4630bbfda8aSnia icon->iconc.fore = Scr->IconC.fore; 4640bbfda8aSnia icon->iconc.back = Scr->IconC.back; 4650bbfda8aSnia icon->title_shrunk = false; 4660bbfda8aSnia 4670bbfda8aSnia GetColorFromList(Scr->IconBorderColorL, tmp_win->name, &tmp_win->class, 4680bbfda8aSnia &icon->border); 4690bbfda8aSnia GetColorFromList(Scr->IconForegroundL, tmp_win->name, &tmp_win->class, 4700bbfda8aSnia &icon->iconc.fore); 4710bbfda8aSnia GetColorFromList(Scr->IconBackgroundL, tmp_win->name, &tmp_win->class, 4720bbfda8aSnia &icon->iconc.back); 4730bbfda8aSnia if(Scr->use3Diconmanagers && !Scr->BeNiceToColormap) { 4740bbfda8aSnia GetShadeColors(&icon->iconc); 4750bbfda8aSnia } 4760bbfda8aSnia 4770bbfda8aSnia FB(icon->iconc.fore, icon->iconc.back); 4780bbfda8aSnia 4790bbfda8aSnia icon->match = match_none; 4800bbfda8aSnia icon->image = NULL; 4810bbfda8aSnia icon->ir = NULL; 4820bbfda8aSnia 4830bbfda8aSnia tmp_win->forced = false; 4840bbfda8aSnia icon->w_not_ours = false; 4850bbfda8aSnia 4860bbfda8aSnia pattern = NULL; 4870bbfda8aSnia 4880bbfda8aSnia /* now go through the steps to get an icon window, if ForceIcon is 4890bbfda8aSnia * set, then no matter what else is defined, the bitmap from the 4900bbfda8aSnia * .twmrc file is used 4910bbfda8aSnia */ 4920bbfda8aSnia if(Scr->ForceIcon) { 4930bbfda8aSnia image = LookupIconNameOrClass(tmp_win, icon, &pattern); 4940bbfda8aSnia } 4950bbfda8aSnia 4960bbfda8aSnia#ifdef EWMH 4970bbfda8aSnia /* 4980bbfda8aSnia * Look to see if there is a _NET_WM_ICON property to provide an icon. 4990bbfda8aSnia */ 5000bbfda8aSnia if(image == NULL) { 5010bbfda8aSnia image = EwmhGetIcon(Scr, tmp_win); 5020bbfda8aSnia if(image != NULL) { 5030bbfda8aSnia icon->match = match_net_wm_icon; 5040bbfda8aSnia icon->width = image->width; 5050bbfda8aSnia icon->height = image->height; 5060bbfda8aSnia icon->image = image; 5070bbfda8aSnia } 5080bbfda8aSnia } 5090bbfda8aSnia#endif /* EWMH */ 5100bbfda8aSnia 5110bbfda8aSnia /* if the pixmap is still NULL, we didn't get one from the above code, 5120bbfda8aSnia * that could mean that ForceIcon was not set, or that the window 5130bbfda8aSnia * was not in the Icons list, now check the WM hints for an icon 5140bbfda8aSnia */ 5150bbfda8aSnia if(image == NULL && tmp_win->wmhints->flags & IconPixmapHint) { 5160bbfda8aSnia unsigned int IconDepth, IconWidth, IconHeight; 5170bbfda8aSnia 5180bbfda8aSnia if(XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap, 5190bbfda8aSnia &JunkRoot, &JunkX, &JunkY, &IconWidth, &IconHeight, &JunkBW, &IconDepth)) { 5200bbfda8aSnia image = AllocImage(); 5210bbfda8aSnia image->width = IconWidth; 5220bbfda8aSnia image->height = IconHeight; 5230bbfda8aSnia image->pixmap = XCreatePixmap(dpy, Scr->Root, image->width, 5240bbfda8aSnia image->height, Scr->d_depth); 5250bbfda8aSnia if(IconDepth == Scr->d_depth) 5260bbfda8aSnia XCopyArea(dpy, tmp_win->wmhints->icon_pixmap, image->pixmap, Scr->NormalGC, 5270bbfda8aSnia 0, 0, image->width, image->height, 0, 0); 5280bbfda8aSnia else 5290bbfda8aSnia XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, image->pixmap, Scr->NormalGC, 5300bbfda8aSnia 0, 0, image->width, image->height, 0, 0, 1); 5310bbfda8aSnia 5320bbfda8aSnia icon->width = image->width; 5330bbfda8aSnia icon->height = image->height; 5340bbfda8aSnia icon->match = match_icon_pixmap_hint; 5350bbfda8aSnia 5360bbfda8aSnia if((tmp_win->wmhints->flags & IconMaskHint) && 5370bbfda8aSnia XGetGeometry(dpy, tmp_win->wmhints->icon_mask, 5380bbfda8aSnia &JunkRoot, &JunkX, &JunkY, &IconWidth, &IconHeight, &JunkBW, &IconDepth) && 5390bbfda8aSnia (IconDepth == 1)) { 5400bbfda8aSnia GC gc; 5410bbfda8aSnia 5420bbfda8aSnia image->mask = XCreatePixmap(dpy, Scr->Root, IconWidth, IconHeight, 1); 5430bbfda8aSnia if(image->mask) { 5440bbfda8aSnia gc = XCreateGC(dpy, image->mask, 0, NULL); 5450bbfda8aSnia if(gc) { 5460bbfda8aSnia XCopyArea(dpy, tmp_win->wmhints->icon_mask, image->mask, gc, 5470bbfda8aSnia 0, 0, IconWidth, IconHeight, 0, 0); 5480bbfda8aSnia XFreeGC(dpy, gc); 5490bbfda8aSnia } 5500bbfda8aSnia } 5510bbfda8aSnia } 5520bbfda8aSnia icon->image = image; 5530bbfda8aSnia } 5540bbfda8aSnia } 5550bbfda8aSnia 5560bbfda8aSnia /* if we still haven't got an icon, let's look in the Icon list 5570bbfda8aSnia * if ForceIcon is not set 5580bbfda8aSnia */ 5590bbfda8aSnia if(image == NULL && !Scr->ForceIcon) { 5600bbfda8aSnia image = LookupIconNameOrClass(tmp_win, icon, &pattern); 5610bbfda8aSnia } 5620bbfda8aSnia 5630bbfda8aSnia /* if we still don't have an icon, assign the UnknownIcon */ 5640bbfda8aSnia if(image == NULL && Scr->UnknownImage != NULL) { 5650bbfda8aSnia image = Scr->UnknownImage; 5660bbfda8aSnia icon->match = match_unknown_default; 5670bbfda8aSnia icon->width = image->width; 5680bbfda8aSnia icon->height = image->height; 5690bbfda8aSnia icon->image = image; 5700bbfda8aSnia } 5710bbfda8aSnia 5720bbfda8aSnia if(image == NULL) { 5730bbfda8aSnia icon->height = 0; 5740bbfda8aSnia icon->width = 0; 5750bbfda8aSnia valuemask = 0; 5760bbfda8aSnia } 5770bbfda8aSnia else { 5780bbfda8aSnia valuemask = CWBackPixmap; 5790bbfda8aSnia attributes.background_pixmap = image->pixmap; 5800bbfda8aSnia } 5810bbfda8aSnia 5820bbfda8aSnia icon->border_width = Scr->IconBorderWidth; 5830bbfda8aSnia if(Scr->NoIconTitlebar || 5840bbfda8aSnia LookInNameList(Scr->NoIconTitle, tmp_win->icon_name) || 5850bbfda8aSnia LookInList(Scr->NoIconTitle, tmp_win->name, &tmp_win->class)) { 5860bbfda8aSnia icon->w_width = icon->width; 5870bbfda8aSnia icon->w_height = icon->height; 5880bbfda8aSnia icon->x = 0; 5890bbfda8aSnia icon->y = 0; 5900bbfda8aSnia icon->has_title = false; 5910bbfda8aSnia } 5920bbfda8aSnia else { 5930bbfda8aSnia XRectangle inc_rect; 5940bbfda8aSnia XRectangle logical_rect; 5950bbfda8aSnia 5960bbfda8aSnia XmbTextExtents(Scr->IconFont.font_set, 5970bbfda8aSnia tmp_win->icon_name, strlen(tmp_win->icon_name), 5980bbfda8aSnia &inc_rect, &logical_rect); 5990bbfda8aSnia icon->w_width = logical_rect.width; 6000bbfda8aSnia 6010bbfda8aSnia icon->w_width += 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER); 6020bbfda8aSnia if(icon->w_width > Scr->MaxIconTitleWidth) { 6030bbfda8aSnia icon->w_width = Scr->MaxIconTitleWidth; 6040bbfda8aSnia } 6050bbfda8aSnia if(icon->w_width < icon->width) { 6060bbfda8aSnia icon->x = (icon->width - icon->w_width) / 2; 6070bbfda8aSnia icon->x += Scr->IconManagerShadowDepth + ICON_MGR_IBORDER; 6080bbfda8aSnia icon->w_width = icon->width; 6090bbfda8aSnia } 6100bbfda8aSnia else { 6110bbfda8aSnia icon->x = Scr->IconManagerShadowDepth + ICON_MGR_IBORDER; 6120bbfda8aSnia } 6130bbfda8aSnia icon->y = icon->height + Scr->IconFont.height + Scr->IconManagerShadowDepth; 6140bbfda8aSnia icon->w_height = icon->height + Scr->IconFont.height + 6150bbfda8aSnia 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER); 6160bbfda8aSnia icon->has_title = true; 6170bbfda8aSnia if(icon->height) { 6180bbfda8aSnia icon->border_width = 0; 6190bbfda8aSnia } 6200bbfda8aSnia } 6210bbfda8aSnia 6220bbfda8aSnia event_mask = 0; 6230bbfda8aSnia if(tmp_win->wmhints->flags & IconWindowHint) { 6240bbfda8aSnia icon->w = tmp_win->wmhints->icon_window; 6250bbfda8aSnia if(tmp_win->forced || 6260bbfda8aSnia XGetGeometry(dpy, icon->w, &JunkRoot, &JunkX, &JunkY, 6270bbfda8aSnia (unsigned int *)&icon->w_width, (unsigned int *)&icon->w_height, 6280bbfda8aSnia &JunkBW, &JunkDepth) == 0) { 6290bbfda8aSnia icon->w = None; 6300bbfda8aSnia tmp_win->wmhints->flags &= ~IconWindowHint; 6310bbfda8aSnia } 6320bbfda8aSnia else { 6330bbfda8aSnia image = NULL; 6340bbfda8aSnia icon->w_not_ours = true; 6350bbfda8aSnia icon->width = icon->w_width; 6360bbfda8aSnia icon->height = icon->w_height; 6370bbfda8aSnia icon->image = image; 6380bbfda8aSnia icon->has_title = false; 6390bbfda8aSnia event_mask = 0; 6400bbfda8aSnia } 6410bbfda8aSnia } 6420bbfda8aSnia else { 6430bbfda8aSnia icon->w = None; 6440bbfda8aSnia } 6450bbfda8aSnia 6460bbfda8aSnia if((image != NULL) && 6470bbfda8aSnia image->mask != None && 6480bbfda8aSnia !(tmp_win->wmhints->flags & IconWindowHint)) { 6490bbfda8aSnia icon->border_width = 0; 6500bbfda8aSnia } 6510bbfda8aSnia if(icon->w == None) { 6520bbfda8aSnia icon->w = XCreateSimpleWindow(dpy, Scr->Root, 6530bbfda8aSnia 0, 0, 6540bbfda8aSnia icon->w_width, icon->w_height, 6550bbfda8aSnia icon->border_width, icon->border, icon->iconc.back); 6560bbfda8aSnia event_mask = ExposureMask; 6570bbfda8aSnia } 6580bbfda8aSnia 6590bbfda8aSnia if(Scr->AutoRaiseIcons || Scr->ShrinkIconTitles) { 6600bbfda8aSnia event_mask |= EnterWindowMask | LeaveWindowMask; 6610bbfda8aSnia } 6620bbfda8aSnia event_mask |= KeyPressMask | ButtonPressMask | ButtonReleaseMask; 6630bbfda8aSnia 6640bbfda8aSnia if(icon->w_not_ours) { 6650bbfda8aSnia XWindowAttributes wattr; 6660bbfda8aSnia 6670bbfda8aSnia XGetWindowAttributes(dpy, icon->w, &wattr); 6680bbfda8aSnia if(wattr.all_event_masks & ButtonPressMask) { 6690bbfda8aSnia event_mask &= ~ButtonPressMask; 6700bbfda8aSnia } 6710bbfda8aSnia } 6720bbfda8aSnia XSelectInput(dpy, icon->w, event_mask); 6730bbfda8aSnia 6740bbfda8aSnia if(icon->width == 0) { 6750bbfda8aSnia icon->width = icon->w_width; 6760bbfda8aSnia } 6770bbfda8aSnia icon->bm_w = None; 6780bbfda8aSnia if(image && !(tmp_win->wmhints->flags & IconWindowHint)) { 6790bbfda8aSnia XRectangle rect; 6800bbfda8aSnia 6810bbfda8aSnia x = GetIconOffset(icon); 6820bbfda8aSnia icon->bm_w = XCreateWindow(dpy, icon->w, x, 0, 6830bbfda8aSnia icon->width, 6840bbfda8aSnia icon->height, 6850bbfda8aSnia 0, Scr->d_depth, 6860bbfda8aSnia CopyFromParent, 6870bbfda8aSnia Scr->d_visual, valuemask, 6880bbfda8aSnia &attributes); 6890bbfda8aSnia if(image->mask) { 6900bbfda8aSnia XShapeCombineMask(dpy, icon->bm_w, ShapeBounding, 0, 0, image->mask, ShapeSet); 6910bbfda8aSnia XShapeCombineMask(dpy, icon->w, ShapeBounding, x, 0, image->mask, ShapeSet); 6920bbfda8aSnia } 6930bbfda8aSnia else if(icon->has_title) { 6940bbfda8aSnia rect.x = x; 6950bbfda8aSnia rect.y = 0; 6960bbfda8aSnia rect.width = icon->width; 6970bbfda8aSnia rect.height = icon->height; 6980bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 6990bbfda8aSnia 0, 0, &rect, 1, ShapeSet, 0); 7000bbfda8aSnia } 7010bbfda8aSnia if(icon->has_title) { 7020bbfda8aSnia if(Scr->ShrinkIconTitles) { 7030bbfda8aSnia rect.x = x; 7040bbfda8aSnia rect.y = icon->height; 7050bbfda8aSnia rect.width = icon->width; 7060bbfda8aSnia rect.height = icon->w_height - icon->height; 7070bbfda8aSnia icon->title_shrunk = true; 7080bbfda8aSnia } 7090bbfda8aSnia else { 7100bbfda8aSnia rect.x = 0; 7110bbfda8aSnia rect.y = icon->height; 7120bbfda8aSnia rect.width = icon->w_width; 7130bbfda8aSnia rect.height = icon->w_height - icon->height; 7140bbfda8aSnia icon->title_shrunk = false; 7150bbfda8aSnia } 7160bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 7170bbfda8aSnia 0, 0, &rect, 1, ShapeUnion, 0); 7180bbfda8aSnia } 7190bbfda8aSnia } 7200bbfda8aSnia 7210bbfda8aSnia if(pattern != NULL) { 7220bbfda8aSnia AddToList(&tmp_win->iconslist, pattern, icon); 7230bbfda8aSnia } 7240bbfda8aSnia 7250bbfda8aSnia tmp_win->icon = icon; 7260bbfda8aSnia /* I need to figure out where to put the icon window now, because 7270bbfda8aSnia * getting here means that I am going to make the icon visible 7280bbfda8aSnia */ 7290bbfda8aSnia final_x = final_y = 0; 7300bbfda8aSnia if(tmp_win->wmhints->flags & IconPositionHint) { 7310bbfda8aSnia final_x = tmp_win->wmhints->icon_x; 7320bbfda8aSnia final_y = tmp_win->wmhints->icon_y; 7330bbfda8aSnia } 7340bbfda8aSnia else { 7350bbfda8aSnia if(visible(tmp_win)) { 7360bbfda8aSnia PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y); 7370bbfda8aSnia } 7380bbfda8aSnia } 7390bbfda8aSnia 7400bbfda8aSnia if(visible(tmp_win) || (tmp_win->wmhints->flags & IconPositionHint)) { 7410bbfda8aSnia if(final_x > Scr->rootw) { 7420bbfda8aSnia final_x = Scr->rootw - icon->w_width - (2 * Scr->IconBorderWidth); 7430bbfda8aSnia } 7440bbfda8aSnia if(Scr->ShrinkIconTitles && icon->bm_w) { 7450bbfda8aSnia if(final_x + (icon->w_width - icon->width) < 0) { 7460bbfda8aSnia final_x = 0; 7470bbfda8aSnia } 7480bbfda8aSnia } 7490bbfda8aSnia else { 7500bbfda8aSnia if(final_x < 0) { 7510bbfda8aSnia final_x = 0; 7520bbfda8aSnia } 7530bbfda8aSnia } 7540bbfda8aSnia if(final_y > Scr->rooth) 7550bbfda8aSnia final_y = Scr->rooth - icon->height - 7560bbfda8aSnia Scr->IconFont.height - 6 - (2 * Scr->IconBorderWidth); 7570bbfda8aSnia if(final_y < 0) { 7580bbfda8aSnia final_y = 0; 7590bbfda8aSnia } 7600bbfda8aSnia 7610bbfda8aSnia XMoveWindow(dpy, icon->w, final_x, final_y); 7620bbfda8aSnia icon->w_x = final_x; 7630bbfda8aSnia icon->w_y = final_y; 7640bbfda8aSnia } 7650bbfda8aSnia tmp_win->iconified = true; 7660bbfda8aSnia OtpAdd(tmp_win, IconWin); 7670bbfda8aSnia 7680bbfda8aSnia XMapSubwindows(dpy, icon->w); 7690bbfda8aSnia XSaveContext(dpy, icon->w, TwmContext, (XPointer)tmp_win); 7700bbfda8aSnia XSaveContext(dpy, icon->w, ScreenContext, (XPointer)Scr); 7710bbfda8aSnia XDefineCursor(dpy, icon->w, Scr->IconCursor); 7720bbfda8aSnia MaybeAnimate = true; 773645f5050Syouri} 774645f5050Syouri 7750bbfda8aSnia 7760bbfda8aSnia/* 7770bbfda8aSnia * Delete TwmWindow.iconslist. 7780bbfda8aSnia * Call it before deleting TwmWindow.icon, since we need to check 7790bbfda8aSnia * that we're not deleting that Icon. 7800bbfda8aSnia */ 7810bbfda8aSniavoid 7820bbfda8aSniaDeleteIconsList(TwmWindow *tmp_win) 783645f5050Syouri{ 7840bbfda8aSnia /* 7850bbfda8aSnia * Only the list itself needs to be freed, since the pointers it 7860bbfda8aSnia * contains point into various lists that belong to Scr. 7870bbfda8aSnia * 7880bbfda8aSnia * Rhialto: Hmmmm not quite sure about that! CreateIconWindow() above 7890bbfda8aSnia * always allocates a struct Icon, and doesn't attach it to Scr... 7900bbfda8aSnia * It is probably correct for the Image pointers inside those Icons though. 7910bbfda8aSnia */ 7920bbfda8aSnia name_list *nptr; 7930bbfda8aSnia name_list *next; 7940bbfda8aSnia 7950bbfda8aSnia for(nptr = tmp_win->iconslist; nptr != NULL;) { 7960bbfda8aSnia next = nptr->next; 7970bbfda8aSnia Icon *icon = (Icon *)nptr->ptr; 7980bbfda8aSnia if(icon != tmp_win->icon) { 7990bbfda8aSnia DeleteIcon(icon); 8000bbfda8aSnia } 8010bbfda8aSnia free(nptr->name); 8020bbfda8aSnia free(nptr); 8030bbfda8aSnia nptr = next; 8040bbfda8aSnia } 8050bbfda8aSnia tmp_win->iconslist = NULL; 806645f5050Syouri} 807645f5050Syouri 8080bbfda8aSnia 8090bbfda8aSnia/* 8100bbfda8aSnia * Delete a single Icon. Called iteratively from DeleteIconList(), and 8110bbfda8aSnia * directly during window destruction. 8120bbfda8aSnia */ 8130bbfda8aSniavoid 8140bbfda8aSniaDeleteIcon(Icon *icon) 815645f5050Syouri{ 8160bbfda8aSnia if(icon->w && !icon->w_not_ours) { 8170bbfda8aSnia XDestroyWindow(dpy, icon->w); 8180bbfda8aSnia } 8190bbfda8aSnia ReleaseIconImage(icon); 8200bbfda8aSnia free(icon); 821645f5050Syouri} 822645f5050Syouri 823645f5050Syouri 8240bbfda8aSnia/* 8250bbfda8aSnia * Delete the Image from an icon, if it is not a shared one. match_list 8260bbfda8aSnia * ands match_unknown_default need not be freed. 8270bbfda8aSnia * 8280bbfda8aSnia * Formerly ReleaseImage() 8290bbfda8aSnia */ 8300bbfda8aSniavoid 8310bbfda8aSniaReleaseIconImage(Icon *icon) 8320bbfda8aSnia{ 8330bbfda8aSnia if(icon->match == match_icon_pixmap_hint || 8340bbfda8aSnia icon->match == match_net_wm_icon) { 8350bbfda8aSnia FreeImage(icon->image); 8360bbfda8aSnia } 837645f5050Syouri} 8380bbfda8aSnia 8390bbfda8aSnia 8400bbfda8aSnia 8410bbfda8aSnia 8420bbfda8aSnia/* 8430bbfda8aSnia **************************************************************** 8440bbfda8aSnia * 8450bbfda8aSnia * Bringing an icon up or down. 8460bbfda8aSnia * 8470bbfda8aSnia **************************************************************** 8480bbfda8aSnia */ 8490bbfda8aSnia 8500bbfda8aSnia 8510bbfda8aSnia/* 8520bbfda8aSnia * Show up an icon. Note that neither IconUp nor IconDown actually map 8530bbfda8aSnia * or unmap the icon window; that's handled by the callers. These 8540bbfda8aSnia * functions limit themselves to figuring out where it should be, moving 8550bbfda8aSnia * it (still unmapped) there, and linking/unlinking it from the iconentry 8560bbfda8aSnia * lists. 8570bbfda8aSnia */ 8580bbfda8aSniavoid 8590bbfda8aSniaIconUp(TwmWindow *tmp_win) 860645f5050Syouri{ 8610bbfda8aSnia int x, y; 8620bbfda8aSnia int defx, defy; 8630bbfda8aSnia 8640bbfda8aSnia /* 8650bbfda8aSnia * If the client specified a particular location, let's use it (this might 8660bbfda8aSnia * want to be an option at some point). Otherwise, try to fit within the 8670bbfda8aSnia * icon region. 8680bbfda8aSnia */ 8690bbfda8aSnia if(tmp_win->wmhints->flags & IconPositionHint) { 8700bbfda8aSnia return; 8710bbfda8aSnia } 8720bbfda8aSnia 8730bbfda8aSnia if(tmp_win->icon_moved) { 8740bbfda8aSnia struct IconRegion *ir; 8750bbfda8aSnia unsigned int iww, iwh; 8760bbfda8aSnia 8770bbfda8aSnia if(!XGetGeometry(dpy, tmp_win->icon->w, &JunkRoot, &defx, &defy, 8780bbfda8aSnia &iww, &iwh, &JunkBW, &JunkDepth)) { 8790bbfda8aSnia return; 8800bbfda8aSnia } 8810bbfda8aSnia 8820bbfda8aSnia x = defx + ((int) iww) / 2; 8830bbfda8aSnia y = defy + ((int) iwh) / 2; 8840bbfda8aSnia 8850bbfda8aSnia for(ir = Scr->FirstRegion; ir; ir = ir->next) { 8860bbfda8aSnia if(x >= ir->x && x < (ir->x + ir->w) && 8870bbfda8aSnia y >= ir->y && y < (ir->y + ir->h)) { 8880bbfda8aSnia break; 8890bbfda8aSnia } 8900bbfda8aSnia } 8910bbfda8aSnia if(!ir) { 8920bbfda8aSnia return; /* outside icon regions, leave alone */ 8930bbfda8aSnia } 8940bbfda8aSnia } 8950bbfda8aSnia 8960bbfda8aSnia defx = -100; 8970bbfda8aSnia defy = -100; 8980bbfda8aSnia PlaceIcon(tmp_win, defx, defy, &x, &y); 8990bbfda8aSnia if(x != defx || y != defy) { 9000bbfda8aSnia XMoveWindow(dpy, tmp_win->icon->w, x, y); 9010bbfda8aSnia tmp_win->icon->w_x = x; 9020bbfda8aSnia tmp_win->icon->w_y = y; 9030bbfda8aSnia tmp_win->icon_moved = false; /* since we've restored it */ 9040bbfda8aSnia } 9050bbfda8aSnia MaybeAnimate = true; 9060bbfda8aSnia return; 907645f5050Syouri} 908645f5050Syouri 9090bbfda8aSnia 9100bbfda8aSnia/* 9110bbfda8aSnia * Remove an icon from its displayed IconEntry. x-ref comment on 9120bbfda8aSnia * IconUp(). 9130bbfda8aSnia */ 9140bbfda8aSniavoid 9150bbfda8aSniaIconDown(TwmWindow *tmp_win) 916645f5050Syouri{ 9170bbfda8aSnia IconEntry *ie, *ip, *in; 9180bbfda8aSnia IconRegion *ir; 9190bbfda8aSnia 9200bbfda8aSnia ie = FindIconEntry(tmp_win, &ir); 9210bbfda8aSnia if(ie) { 9220bbfda8aSnia ie->twm_win = NULL; 9230bbfda8aSnia ie->used = false; 9240bbfda8aSnia ip = prevIconEntry(ie, ir); 9250bbfda8aSnia in = ie->next; 9260bbfda8aSnia for(;;) { 9270bbfda8aSnia if(ip && ip->used == false && 9280bbfda8aSnia ((ip->x == ie->x && ip->w == ie->w) || 9290bbfda8aSnia (ip->y == ie->y && ip->h == ie->h))) { 9300bbfda8aSnia ip->next = ie->next; 9310bbfda8aSnia mergeEntries(ie, ip); 9320bbfda8aSnia free(ie); 9330bbfda8aSnia ie = ip; 9340bbfda8aSnia ip = prevIconEntry(ip, ir); 9350bbfda8aSnia } 9360bbfda8aSnia else if(in && in->used == false && 9370bbfda8aSnia ((in->x == ie->x && in->w == ie->w) || 9380bbfda8aSnia (in->y == ie->y && in->h == ie->h))) { 9390bbfda8aSnia ie->next = in->next; 9400bbfda8aSnia mergeEntries(in, ie); 9410bbfda8aSnia free(in); 9420bbfda8aSnia in = ie->next; 9430bbfda8aSnia } 9440bbfda8aSnia else { 9450bbfda8aSnia break; 9460bbfda8aSnia } 9470bbfda8aSnia } 9480bbfda8aSnia } 9490bbfda8aSnia} 950645f5050Syouri 9510bbfda8aSnia 9520bbfda8aSnia 9530bbfda8aSnia 9540bbfda8aSnia/* 9550bbfda8aSnia **************************************************************** 9560bbfda8aSnia * 9570bbfda8aSnia * Funcs related to drawing the icon. 9580bbfda8aSnia * 9590bbfda8aSnia **************************************************************** 9600bbfda8aSnia */ 9610bbfda8aSnia 9620bbfda8aSnia 9630bbfda8aSnia/* 9640bbfda8aSnia * Slightly misnamed: draws the text label under an icon. 9650bbfda8aSnia */ 9660bbfda8aSniavoid 9670bbfda8aSniaPaintIcon(TwmWindow *tmp_win) 9680bbfda8aSnia{ 9690bbfda8aSnia int width, twidth, mwidth, len, x; 9700bbfda8aSnia Icon *icon; 9710bbfda8aSnia XRectangle ink_rect; 972645f5050Syouri XRectangle logical_rect; 973645f5050Syouri 9740bbfda8aSnia if(!tmp_win || !tmp_win->icon) { 9750bbfda8aSnia return; 9760bbfda8aSnia } 9770bbfda8aSnia icon = tmp_win->icon; 9780bbfda8aSnia if(!icon->has_title) { 9790bbfda8aSnia return; 9800bbfda8aSnia } 9810bbfda8aSnia 9820bbfda8aSnia x = 0; 9830bbfda8aSnia width = icon->w_width; 9840bbfda8aSnia if(Scr->ShrinkIconTitles && icon->title_shrunk) { 9850bbfda8aSnia x = GetIconOffset(icon); 9860bbfda8aSnia width = icon->width; 9870bbfda8aSnia } 9880bbfda8aSnia len = strlen(tmp_win->icon_name); 989645f5050Syouri XmbTextExtents(Scr->IconFont.font_set, 9900bbfda8aSnia tmp_win->icon_name, len, 9910bbfda8aSnia &ink_rect, &logical_rect); 9920bbfda8aSnia twidth = logical_rect.width; 9930bbfda8aSnia mwidth = width - 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER); 9940bbfda8aSnia if(Scr->use3Diconmanagers) { 9950bbfda8aSnia Draw3DBorder(icon->w, x, icon->height, width, 9960bbfda8aSnia Scr->IconFont.height + 9970bbfda8aSnia 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER), 9980bbfda8aSnia Scr->IconManagerShadowDepth, icon->iconc, off, false, false); 9990bbfda8aSnia } 10000bbfda8aSnia while((len > 0) && (twidth > mwidth)) { 10010bbfda8aSnia len--; 10020bbfda8aSnia XmbTextExtents(Scr->IconFont.font_set, 10030bbfda8aSnia tmp_win->icon_name, len, 10040bbfda8aSnia &ink_rect, &logical_rect); 10050bbfda8aSnia twidth = logical_rect.width; 10060bbfda8aSnia } 10070bbfda8aSnia FB(icon->iconc.fore, icon->iconc.back); 10080bbfda8aSnia XmbDrawString(dpy, icon->w, Scr->IconFont.font_set, Scr->NormalGC, 10090bbfda8aSnia x + ((mwidth - twidth) / 2) + 10100bbfda8aSnia Scr->IconManagerShadowDepth + ICON_MGR_IBORDER, 10110bbfda8aSnia icon->y, tmp_win->icon_name, len); 1012645f5050Syouri} 1013645f5050Syouri 1014645f5050Syouri 10150bbfda8aSnia/* 10160bbfda8aSnia * Handling for ShrinkIconTitles; when pointer is away from them, shrink 10170bbfda8aSnia * the titles down to the width of the image, and expand back out when it 10180bbfda8aSnia * enters. 10190bbfda8aSnia */ 10200bbfda8aSniavoid 10210bbfda8aSniaShrinkIconTitle(TwmWindow *tmp_win) 1022645f5050Syouri{ 10230bbfda8aSnia Icon *icon; 10240bbfda8aSnia XRectangle rect; 10250bbfda8aSnia 10260bbfda8aSnia if(!tmp_win || !tmp_win->icon) { 10270bbfda8aSnia return; 10280bbfda8aSnia } 10290bbfda8aSnia icon = tmp_win->icon; 10300bbfda8aSnia if(!icon->has_title) { 10310bbfda8aSnia return; 10320bbfda8aSnia } 10330bbfda8aSnia if(icon->w_width == icon->width) { 10340bbfda8aSnia return; 10350bbfda8aSnia } 10360bbfda8aSnia if(icon->height == 0) { 10370bbfda8aSnia return; 10380bbfda8aSnia } 10390bbfda8aSnia 10400bbfda8aSnia rect.x = GetIconOffset(icon); 10410bbfda8aSnia rect.y = 0; 10420bbfda8aSnia rect.width = icon->width; 10430bbfda8aSnia rect.height = icon->w_height; 10440bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, 10450bbfda8aSnia ShapeIntersect, 0); 10460bbfda8aSnia icon->title_shrunk = true; 10470bbfda8aSnia XClearArea(dpy, icon->w, 0, icon->height, icon->w_width, 10480bbfda8aSnia icon->w_height - icon->height, True); 1049645f5050Syouri} 1050645f5050Syouri 10510bbfda8aSnia 10520bbfda8aSniavoid 10530bbfda8aSniaExpandIconTitle(TwmWindow *tmp_win) 1054645f5050Syouri{ 10550bbfda8aSnia Icon *icon; 10560bbfda8aSnia XRectangle rect; 10570bbfda8aSnia 10580bbfda8aSnia if(!tmp_win || !tmp_win->icon) { 10590bbfda8aSnia return; 10600bbfda8aSnia } 10610bbfda8aSnia icon = tmp_win->icon; 10620bbfda8aSnia if(!icon->has_title) { 10630bbfda8aSnia return; 10640bbfda8aSnia } 10650bbfda8aSnia if(icon->w_width == icon->width) { 10660bbfda8aSnia return; 10670bbfda8aSnia } 10680bbfda8aSnia if(icon->height == 0) { 10690bbfda8aSnia return; 10700bbfda8aSnia } 10710bbfda8aSnia 10720bbfda8aSnia rect.x = 0; 10730bbfda8aSnia rect.y = icon->height; 10740bbfda8aSnia rect.width = icon->w_width; 10750bbfda8aSnia rect.height = icon->w_height - icon->height; 10760bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, 10770bbfda8aSnia 0); 10780bbfda8aSnia icon->title_shrunk = false; 10790bbfda8aSnia XClearArea(dpy, icon->w, 0, icon->height, icon->w_width, 10800bbfda8aSnia icon->w_height - icon->height, True); 1081645f5050Syouri} 1082645f5050Syouri 10830bbfda8aSnia 10840bbfda8aSnia/* 10850bbfda8aSnia * Setup X Shape'ing around icons and their titles. 10860bbfda8aSnia * 10870bbfda8aSnia * XXX should this be checking HasShape? It seems to be called 10880bbfda8aSnia * unconditionally... 10890bbfda8aSnia */ 10900bbfda8aSniastatic void 10910bbfda8aSniaReshapeIcon(Icon *icon) 1092645f5050Syouri{ 10930bbfda8aSnia int x; 10940bbfda8aSnia XRectangle rect; 1095645f5050Syouri 10960bbfda8aSnia if(!icon) { 10970bbfda8aSnia return; 10980bbfda8aSnia } 10990bbfda8aSnia x = GetIconOffset(icon); 11000bbfda8aSnia XMoveWindow(dpy, icon->bm_w, x, 0); 1101645f5050Syouri 11020bbfda8aSnia if(icon->image && icon->image->mask) { 11030bbfda8aSnia XShapeCombineMask(dpy, icon->w, ShapeBounding, x, 0, icon->image->mask, 11040bbfda8aSnia ShapeSet); 11050bbfda8aSnia } 11060bbfda8aSnia else { 11070bbfda8aSnia rect.x = x; 11080bbfda8aSnia rect.y = 0; 11090bbfda8aSnia rect.width = icon->width; 11100bbfda8aSnia rect.height = icon->height; 11110bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 11120bbfda8aSnia 0); 11130bbfda8aSnia } 1114645f5050Syouri rect.x = x; 11150bbfda8aSnia rect.y = icon->height; 1116645f5050Syouri rect.width = icon->width; 11170bbfda8aSnia rect.height = icon->w_height - icon->height; 11180bbfda8aSnia XShapeCombineRectangles(dpy, icon->w, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, 11190bbfda8aSnia 0); 11200bbfda8aSnia} 11210bbfda8aSnia 11220bbfda8aSnia 11230bbfda8aSnia/* 11240bbfda8aSnia * Figure horizontal positioning/offset for the icon image within its 11250bbfda8aSnia * window. 11260bbfda8aSnia */ 11270bbfda8aSniaint 11280bbfda8aSniaGetIconOffset(Icon *icon) 11290bbfda8aSnia{ 11300bbfda8aSnia TitleJust justif; 11310bbfda8aSnia 11320bbfda8aSnia if(!icon) { 11330bbfda8aSnia return 0; 11340bbfda8aSnia } 11350bbfda8aSnia 11360bbfda8aSnia justif = icon->ir ? icon->ir->TitleJustification : Scr->IconJustification; 11370bbfda8aSnia switch(justif) { 11380bbfda8aSnia case TJ_LEFT: 11390bbfda8aSnia return 0; 11400bbfda8aSnia 11410bbfda8aSnia case TJ_CENTER: 11420bbfda8aSnia return ((icon->w_width - icon->width) / 2); 11430bbfda8aSnia 11440bbfda8aSnia case TJ_RIGHT: 11450bbfda8aSnia return (icon->w_width - icon->width); 11460bbfda8aSnia 11470bbfda8aSnia default: 11480bbfda8aSnia /* Can't happen? */ 11490bbfda8aSnia fprintf(stderr, "%s(): Invalid TitleJustification %d\n", 11500bbfda8aSnia __func__, justif); 11510bbfda8aSnia return 0; 11520bbfda8aSnia } 1153645f5050Syouri} 1154645f5050Syouri 11550bbfda8aSnia 11560bbfda8aSnia/* 11570bbfda8aSnia * [Re-]lookup the image for an icon and [re-]layout it. 11580bbfda8aSnia */ 11590bbfda8aSniavoid 11600bbfda8aSniaRedoIcon(TwmWindow *win) 1161645f5050Syouri{ 11620bbfda8aSnia Icon *icon, *old_icon; 11630bbfda8aSnia char *pattern; 11640bbfda8aSnia 11650bbfda8aSnia old_icon = win->icon; 11660bbfda8aSnia 11670bbfda8aSnia if(old_icon && (old_icon->w_not_ours || old_icon->match != match_list)) { 11680bbfda8aSnia RedoIconName(win); 11690bbfda8aSnia return; 11700bbfda8aSnia } 11710bbfda8aSnia icon = NULL; 11720bbfda8aSnia if((pattern = LookPatternInNameList(Scr->IconNames, win->icon_name))) { 11730bbfda8aSnia icon = LookInNameList(win->iconslist, pattern); 11740bbfda8aSnia } 11750bbfda8aSnia else if((pattern = LookPatternInNameList(Scr->IconNames, win->name))) { 11760bbfda8aSnia icon = LookInNameList(win->iconslist, pattern); 11770bbfda8aSnia } 11780bbfda8aSnia else if((pattern = LookPatternInList(Scr->IconNames, win->name, 11790bbfda8aSnia &win->class))) { 11800bbfda8aSnia icon = LookInNameList(win->iconslist, pattern); 11810bbfda8aSnia } 11820bbfda8aSnia if(pattern == NULL) { 11830bbfda8aSnia RedoIconName(win); 11840bbfda8aSnia return; 11850bbfda8aSnia } 11860bbfda8aSnia if(icon != NULL) { 11870bbfda8aSnia if(old_icon == icon) { 11880bbfda8aSnia RedoIconName(win); 11890bbfda8aSnia return; 11900bbfda8aSnia } 11910bbfda8aSnia if(win->icon_on && visible(win)) { 11920bbfda8aSnia IconDown(win); 11930bbfda8aSnia if(old_icon && old_icon->w) { 11940bbfda8aSnia XUnmapWindow(dpy, old_icon->w); 11950bbfda8aSnia } 11960bbfda8aSnia win->icon = icon; 11970bbfda8aSnia OtpReassignIcon(win, old_icon); 11980bbfda8aSnia IconUp(win); 11990bbfda8aSnia OtpRaise(win, IconWin); 12000bbfda8aSnia XMapWindow(dpy, win->icon->w); 12010bbfda8aSnia } 12020bbfda8aSnia else { 12030bbfda8aSnia win->icon = icon; 12040bbfda8aSnia OtpReassignIcon(win, old_icon); 12050bbfda8aSnia } 12060bbfda8aSnia RedoIconName(win); 12070bbfda8aSnia } 12080bbfda8aSnia else { 12090bbfda8aSnia if(win->icon_on && visible(win)) { 12100bbfda8aSnia IconDown(win); 12110bbfda8aSnia if(old_icon && old_icon->w) { 12120bbfda8aSnia XUnmapWindow(dpy, old_icon->w); 12130bbfda8aSnia } 12140bbfda8aSnia /* 12150bbfda8aSnia * If the icon name/class was found on one of the above lists, 12160bbfda8aSnia * the call to CreateIconWindow() will find it again there 12170bbfda8aSnia * and keep track of it on win->iconslist for eventual 12180bbfda8aSnia * deallocation. (It is now checked that the current struct 12190bbfda8aSnia * Icon is also already on that list) 12200bbfda8aSnia */ 12210bbfda8aSnia OtpFreeIcon(win); 12220bbfda8aSnia bool saveForceIcon = Scr->ForceIcon; 12230bbfda8aSnia Scr->ForceIcon = true; 12240bbfda8aSnia CreateIconWindow(win, -100, -100); 12250bbfda8aSnia Scr->ForceIcon = saveForceIcon; 12260bbfda8aSnia OtpRaise(win, IconWin); 12270bbfda8aSnia XMapWindow(dpy, win->icon->w); 12280bbfda8aSnia } 12290bbfda8aSnia else { 12300bbfda8aSnia OtpFreeIcon(win); 12310bbfda8aSnia win->icon = NULL; 12320bbfda8aSnia WMapUpdateIconName(win); 12330bbfda8aSnia } 12340bbfda8aSnia RedoIconName(win); 12350bbfda8aSnia } 12360bbfda8aSnia} 12370bbfda8aSnia 12380bbfda8aSnia 12390bbfda8aSnia/* 12400bbfda8aSnia * Resize the icon window, and reposition the image and name within it. 12410bbfda8aSnia * (a lot of the actual repositioning gets done during the later expose). 12420bbfda8aSnia */ 12430bbfda8aSniavoid 12440bbfda8aSniaRedoIconName(TwmWindow *win) 12450bbfda8aSnia{ 12460bbfda8aSnia int x; 12470bbfda8aSnia XRectangle ink_rect; 12480bbfda8aSnia XRectangle logical_rect; 12490bbfda8aSnia 12500bbfda8aSnia if(Scr->NoIconTitlebar || 12510bbfda8aSnia LookInNameList(Scr->NoIconTitle, win->icon_name) || 12520bbfda8aSnia LookInList(Scr->NoIconTitle, win->name, &win->class)) { 12530bbfda8aSnia WMapUpdateIconName(win); 12540bbfda8aSnia return; 12550bbfda8aSnia } 12560bbfda8aSnia if(win->iconmanagerlist) { 12570bbfda8aSnia /* let the expose event cause the repaint */ 12580bbfda8aSnia XClearArea(dpy, win->iconmanagerlist->w, 0, 0, 0, 0, True); 12590bbfda8aSnia 12600bbfda8aSnia if(Scr->SortIconMgr) { 12610bbfda8aSnia SortIconManager(win->iconmanagerlist->iconmgr); 12620bbfda8aSnia } 12630bbfda8aSnia } 12640bbfda8aSnia 12650bbfda8aSnia if(!win->icon || !win->icon->w) { 12660bbfda8aSnia WMapUpdateIconName(win); 12670bbfda8aSnia return; 12680bbfda8aSnia } 1269645f5050Syouri 12700bbfda8aSnia if(win->icon->w_not_ours) { 12710bbfda8aSnia WMapUpdateIconName(win); 12720bbfda8aSnia return; 12730bbfda8aSnia } 1274645f5050Syouri 12750bbfda8aSnia XmbTextExtents(Scr->IconFont.font_set, 12760bbfda8aSnia win->icon_name, strlen(win->icon_name), 12770bbfda8aSnia &ink_rect, &logical_rect); 12780bbfda8aSnia win->icon->w_width = logical_rect.width; 12790bbfda8aSnia win->icon->w_width += 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER); 12800bbfda8aSnia if(win->icon->w_width > Scr->MaxIconTitleWidth) { 12810bbfda8aSnia win->icon->w_width = Scr->MaxIconTitleWidth; 12820bbfda8aSnia } 1283645f5050Syouri 12840bbfda8aSnia if(win->icon->w_width < win->icon->width) { 12850bbfda8aSnia win->icon->x = (win->icon->width - win->icon->w_width) / 2; 12860bbfda8aSnia win->icon->x += Scr->IconManagerShadowDepth + ICON_MGR_IBORDER; 12870bbfda8aSnia win->icon->w_width = win->icon->width; 12880bbfda8aSnia } 12890bbfda8aSnia else { 12900bbfda8aSnia win->icon->x = Scr->IconManagerShadowDepth + ICON_MGR_IBORDER; 12910bbfda8aSnia } 1292645f5050Syouri 12930bbfda8aSnia x = GetIconOffset(win->icon); 12940bbfda8aSnia win->icon->y = win->icon->height + Scr->IconFont.height + 12950bbfda8aSnia Scr->IconManagerShadowDepth; 12960bbfda8aSnia win->icon->w_height = win->icon->height + Scr->IconFont.height + 12970bbfda8aSnia 2 * (Scr->IconManagerShadowDepth + ICON_MGR_IBORDER); 12980bbfda8aSnia 12990bbfda8aSnia XResizeWindow(dpy, win->icon->w, win->icon->w_width, 13000bbfda8aSnia win->icon->w_height); 13010bbfda8aSnia if(win->icon->bm_w) { 13020bbfda8aSnia XRectangle rect; 13030bbfda8aSnia 13040bbfda8aSnia XMoveWindow(dpy, win->icon->bm_w, x, 0); 13050bbfda8aSnia XMapWindow(dpy, win->icon->bm_w); 13060bbfda8aSnia if(win->icon->image && win->icon->image->mask) { 13070bbfda8aSnia XShapeCombineMask(dpy, win->icon->bm_w, ShapeBounding, 0, 0, 13080bbfda8aSnia win->icon->image->mask, ShapeSet); 13090bbfda8aSnia XShapeCombineMask(dpy, win->icon->w, ShapeBounding, x, 0, 13100bbfda8aSnia win->icon->image->mask, ShapeSet); 13110bbfda8aSnia } 13120bbfda8aSnia else if(win->icon->has_title) { 13130bbfda8aSnia rect.x = x; 13140bbfda8aSnia rect.y = 0; 13150bbfda8aSnia rect.width = win->icon->width; 13160bbfda8aSnia rect.height = win->icon->height; 13170bbfda8aSnia XShapeCombineRectangles(dpy, win->icon->w, ShapeBounding, 13180bbfda8aSnia 0, 0, &rect, 1, ShapeSet, 0); 13190bbfda8aSnia } 13200bbfda8aSnia if(win->icon->has_title) { 13210bbfda8aSnia if(Scr->ShrinkIconTitles && win->icon->title_shrunk) { 13220bbfda8aSnia rect.x = x; 13230bbfda8aSnia rect.y = win->icon->height; 13240bbfda8aSnia rect.width = win->icon->width; 13250bbfda8aSnia rect.height = win->icon->w_height - win->icon->height; 13260bbfda8aSnia } 13270bbfda8aSnia else { 13280bbfda8aSnia rect.x = 0; 13290bbfda8aSnia rect.y = win->icon->height; 13300bbfda8aSnia rect.width = win->icon->w_width; 13310bbfda8aSnia rect.height = win->icon->w_height - win->icon->height; 13320bbfda8aSnia } 13330bbfda8aSnia XShapeCombineRectangles(dpy, win->icon->w, ShapeBounding, 0, 13340bbfda8aSnia 0, &rect, 1, ShapeUnion, 0); 13350bbfda8aSnia } 13360bbfda8aSnia } 13370bbfda8aSnia if(Scr->ShrinkIconTitles && 13380bbfda8aSnia win->icon->title_shrunk && 13390bbfda8aSnia win->icon_on && (visible(win))) { 13400bbfda8aSnia IconDown(win); 13410bbfda8aSnia IconUp(win); 13420bbfda8aSnia } 13430bbfda8aSnia if(win->isicon) { 13440bbfda8aSnia XClearArea(dpy, win->icon->w, 0, 0, 0, 0, True); 13450bbfda8aSnia } 1346645f5050Syouri 13470bbfda8aSnia WMapUpdateIconName(win); 1348645f5050Syouri} 1349645f5050Syouri 13500bbfda8aSnia 13510bbfda8aSnia 13520bbfda8aSnia 13530bbfda8aSnia/* 13540bbfda8aSnia **************************************************************** 13550bbfda8aSnia * 13560bbfda8aSnia * Misc internal utils. 13570bbfda8aSnia * 13580bbfda8aSnia **************************************************************** 13590bbfda8aSnia */ 13600bbfda8aSnia 13610bbfda8aSnia 13620bbfda8aSnia/* 13630bbfda8aSnia * What it says on the tin. 13640bbfda8aSnia */ 13650bbfda8aSniastatic int 13660bbfda8aSniaroundUp(int v, int multiple) 1367645f5050Syouri{ 13680bbfda8aSnia return ((v + multiple - 1) / multiple) * multiple; 1369645f5050Syouri} 1370645f5050Syouri 13710bbfda8aSnia 13720bbfda8aSnia/* 13730bbfda8aSnia * Find the image set in Icons{} for a TwmWindow if possible. Return the 13740bbfda8aSnia * image, record its provenance inside *icon, and pass back what pattern 13750bbfda8aSnia * it matched in **pattern. 13760bbfda8aSnia */ 13770bbfda8aSniastatic Image * 13780bbfda8aSniaLookupIconNameOrClass(TwmWindow *tmp_win, Icon *icon, char **pattern) 13790bbfda8aSnia{ 13800bbfda8aSnia char *icon_name = NULL; 13810bbfda8aSnia Image *image; 13820bbfda8aSnia Matchtype matched = match_none; 13830bbfda8aSnia 13840bbfda8aSnia icon_name = LookInNameList(Scr->IconNames, tmp_win->icon_name); 13850bbfda8aSnia if(icon_name != NULL) { 13860bbfda8aSnia *pattern = LookPatternInNameList(Scr->IconNames, tmp_win->icon_name); 13870bbfda8aSnia matched = match_list; 13880bbfda8aSnia } 13890bbfda8aSnia 13900bbfda8aSnia if(matched == match_none) { 13910bbfda8aSnia icon_name = LookInNameList(Scr->IconNames, tmp_win->name); 13920bbfda8aSnia if(icon_name != NULL) { 13930bbfda8aSnia *pattern = LookPatternInNameList(Scr->IconNames, tmp_win->name); 13940bbfda8aSnia matched = match_list; 13950bbfda8aSnia } 13960bbfda8aSnia } 13970bbfda8aSnia 13980bbfda8aSnia if(matched == match_none) { 13990bbfda8aSnia icon_name = LookInList(Scr->IconNames, tmp_win->name, &tmp_win->class); 14000bbfda8aSnia if(icon_name != NULL) { 14010bbfda8aSnia *pattern = LookPatternInList(Scr->IconNames, tmp_win->name, 14020bbfda8aSnia &tmp_win->class); 14030bbfda8aSnia matched = match_list; 14040bbfda8aSnia } 14050bbfda8aSnia } 14060bbfda8aSnia 14070bbfda8aSnia if((image = GetImage(icon_name, icon->iconc)) != NULL) { 14080bbfda8aSnia icon->match = matched; 14090bbfda8aSnia icon->image = image; 14100bbfda8aSnia icon->width = image->width; 14110bbfda8aSnia icon->height = image->height; 14120bbfda8aSnia tmp_win->forced = true; 14130bbfda8aSnia } 14140bbfda8aSnia else { 14150bbfda8aSnia icon->match = match_none; 14160bbfda8aSnia *pattern = NULL; 14170bbfda8aSnia } 14180bbfda8aSnia 14190bbfda8aSnia return image; 14200bbfda8aSnia} 1421