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