3
Copyright 1989, 1998 The Open Group
5
Permission to use, copy, modify, distribute, and sell this software and its
6
documentation for any purpose is hereby granted without fee, provided that
7
the above copyright notice appear in all copies and that both that
8
copyright notice and this permission notice appear in supporting
11
The above copyright notice and this permission notice shall be included in
12
all copies or substantial portions of the Software.
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
Except as contained in this notice, the name of The Open Group shall not be
22
used in advertising or otherwise to promote the sale, use or other dealings
23
in this Software without prior written authorization from The Open Group.
25
/* $XFree86: xc/programs/twm/icons.c,v 1.7 2002/12/10 22:29:54 tsi Exp $ */
27
/**********************************************************************
29
* $Xorg: icons.c,v 1.4 2001/02/09 02:05:36 xorgcvs Exp $
31
* Icon releated routines
33
* 10-Apr-89 Tom LaStrange Initial Version.
35
**********************************************************************/
45
#define iconWidth(w) (Scr->IconBorderWidth * 2 + w->icon_w_width)
46
#define iconHeight(w) (Scr->IconBorderWidth * 2 + w->icon_w_height)
48
static void splitEntry ( IconEntry *ie, int grav1, int grav2, int w, int h );
49
static IconEntry * FindIconEntry ( TwmWindow *tmp_win, IconRegion **irp );
50
static IconEntry * prevIconEntry ( IconEntry *ie, IconRegion *ir );
51
static void mergeEntries ( IconEntry *old, IconEntry *ie );
54
splitEntry (ie, grav1, grav2, w, h)
65
splitEntry (ie, grav2, grav1, w, ie->h);
67
new = (IconEntry *)malloc (sizeof (IconEntry));
76
if (grav1 == D_SOUTH) {
78
ie->y = new->y + new->h;
80
new->y = ie->y + ie->h;
86
splitEntry (ie, grav2, grav1, ie->w, h);
88
new = (IconEntry *)malloc (sizeof (IconEntry));
97
if (grav1 == D_EAST) {
99
ie->x = new->x + new->w;
101
new->x = ie->x + ie->w;
108
roundUp (int v, int multiple)
110
return ((v + multiple - 1) / multiple) * multiple;
114
PlaceIcon(tmp_win, def_x, def_y, final_x, final_y)
117
int *final_x, *final_y;
124
for (ir = Scr->FirstRegion; ir; ir = ir->next) {
125
w = roundUp (iconWidth (tmp_win), ir->stepx);
126
h = roundUp (iconHeight (tmp_win), ir->stepy);
127
for (ie = ir->entries; ie; ie=ie->next) {
130
if (ie->w >= w && ie->h >= h)
137
splitEntry (ie, ir->grav1, ir->grav2, w, h);
139
ie->twm_win = tmp_win;
140
*final_x = ie->x + (ie->w - iconWidth (tmp_win)) / 2;
141
*final_y = ie->y + (ie->h - iconHeight (tmp_win)) / 2;
150
FindIconEntry (tmp_win, irp)
157
for (ir = Scr->FirstRegion; ir; ir = ir->next) {
158
for (ie = ir->entries; ie; ie=ie->next)
159
if (ie->twm_win == tmp_win) {
174
struct IconRegion *ir;
177
* If the client specified a particular location, let's use it (this might
178
* want to be an option at some point). Otherwise, try to fit within the
181
if (tmp_win->wmhints && (tmp_win->wmhints->flags & IconPositionHint))
184
if (tmp_win->icon_moved) {
185
if (!XGetGeometry (dpy, tmp_win->icon_w, &JunkRoot, &defx, &defy,
186
&JunkWidth, &JunkHeight, &JunkBW, &JunkDepth))
189
x = defx + ((int) JunkWidth) / 2;
190
y = defy + ((int) JunkHeight) / 2;
192
for (ir = Scr->FirstRegion; ir; ir = ir->next) {
193
if (x >= ir->x && x < (ir->x + ir->w) &&
194
y >= ir->y && y < (ir->y + ir->h))
197
if (!ir) return; /* outside icon regions, leave alone */
202
PlaceIcon(tmp_win, defx, defy, &x, &y);
203
if (x != defx || y != defy) {
204
XMoveWindow (dpy, tmp_win->icon_w, x, y);
205
tmp_win->icon_moved = FALSE; /* since we've restored it */
210
prevIconEntry (ie, ir)
216
if (ie == ir->entries)
218
for (ip = ir->entries; ip->next != ie; ip=ip->next)
223
/* old is being freed; and is adjacent to ie. Merge
228
mergeEntries (old, ie)
231
if (old->y == ie->y) {
232
ie->w = old->w + ie->w;
236
ie->h = old->h + ie->h;
246
IconEntry *ie, *ip, *in;
249
ie = FindIconEntry (tmp_win, &ir);
253
ip = prevIconEntry (ie, ir);
256
if (ip && ip->used == 0 &&
257
((ip->x == ie->x && ip->w == ie->w) ||
258
(ip->y == ie->y && ip->h == ie->h)))
261
mergeEntries (ie, ip);
264
ip = prevIconEntry (ip, ir);
265
} else if (in && in->used == 0 &&
266
((in->x == ie->x && in->w == ie->w) ||
267
(in->y == ie->y && in->h == ie->h)))
270
mergeEntries (in, ie);
280
AddIconRegion(geom, grav1, grav2, stepx, stepy)
288
ir = (IconRegion *)malloc(sizeof(IconRegion));
291
Scr->LastRegion->next = ir;
292
Scr->LastRegion = ir;
293
if (!Scr->FirstRegion)
294
Scr->FirstRegion = ir;
305
ir->x = ir->y = ir->w = ir->h = 0;
307
mask = XParseGeometry(geom, &ir->x, &ir->y, (unsigned int *)&ir->w, (unsigned int *)&ir->h);
309
if (mask & XNegative)
310
ir->x += Scr->MyDisplayWidth - ir->w;
312
if (mask & YNegative)
313
ir->y += Scr->MyDisplayHeight - ir->h;
314
ir->entries = (IconEntry *)malloc(sizeof(IconEntry));
315
ir->entries->next = 0;
316
ir->entries->x = ir->x;
317
ir->entries->y = ir->y;
318
ir->entries->w = ir->w;
319
ir->entries->h = ir->h;
320
ir->entries->twm_win = 0;
321
ir->entries->used = 0;
331
for (ie = ir->entries; ie; ie=tmp)
341
IconRegion *ir, *tmp;
343
for (ir = Scr->FirstRegion; ir != NULL;)
346
FreeIconEntries (ir);
350
Scr->FirstRegion = NULL;
351
Scr->LastRegion = NULL;
356
CreateIconWindow(tmp_win, def_x, def_y)
360
unsigned long event_mask;
361
unsigned long valuemask; /* mask for create windows */
362
XSetWindowAttributes attributes; /* attributes for create windows */
363
Pixmap pm = None; /* tmp pixmap variable */
364
int final_x, final_y;
368
FB(tmp_win->iconc.fore, tmp_win->iconc.back);
370
tmp_win->forced = FALSE;
371
tmp_win->icon_not_ours = FALSE;
373
/* now go through the steps to get an icon window, if ForceIcon is
374
* set, then no matter what else is defined, the bitmap from the
375
* .twmrc file is used
382
icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
383
if (icon_name == NULL)
384
icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
388
if (icon_name != NULL)
390
if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
392
if ((bm = GetBitmap (icon_name)) != None)
393
AddToList(&Scr->Icons, icon_name, (char *)bm);
399
XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
400
(unsigned int *) &tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
401
&JunkBW, &JunkDepth);
403
pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
404
tmp_win->icon_height, Scr->d_depth);
406
/* the copy plane works on color ! */
407
XCopyPlane(dpy, bm, pm, Scr->NormalGC,
408
0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
410
tmp_win->forced = TRUE;
414
/* if the pixmap is still NULL, we didn't get one from the above code,
415
* that could mean that ForceIcon was not set, or that the window
416
* was not in the Icons list, now check the WM hints for an icon
418
if (pm == None && tmp_win->wmhints &&
419
tmp_win->wmhints->flags & IconPixmapHint)
422
XGetGeometry(dpy, tmp_win->wmhints->icon_pixmap,
423
&JunkRoot, &JunkX, &JunkY,
424
(unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height, &JunkBW, &JunkDepth);
426
pm = XCreatePixmap(dpy, Scr->Root,
427
tmp_win->icon_width, tmp_win->icon_height,
430
XCopyPlane(dpy, tmp_win->wmhints->icon_pixmap, pm, Scr->NormalGC,
431
0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
434
/* if we still haven't got an icon, let's look in the Icon list
435
* if ForceIcon is not set
437
if (pm == None && !Scr->ForceIcon)
442
icon_name = LookInNameList(Scr->IconNames, tmp_win->full_name);
443
if (icon_name == NULL)
444
icon_name = LookInList(Scr->IconNames, tmp_win->full_name,
448
if (icon_name != NULL)
450
if ((bm = (Pixmap)LookInNameList(Scr->Icons, icon_name)) == None)
452
if ((bm = GetBitmap (icon_name)) != None)
453
AddToList(&Scr->Icons, icon_name, (char *)bm);
459
XGetGeometry(dpy, bm, &JunkRoot, &JunkX, &JunkY,
460
(unsigned int *)&tmp_win->icon_width, (unsigned int *)&tmp_win->icon_height,
461
&JunkBW, &JunkDepth);
463
pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
464
tmp_win->icon_height, Scr->d_depth);
466
/* the copy plane works on color ! */
467
XCopyPlane(dpy, bm, pm, Scr->NormalGC,
468
0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
472
/* if we still don't have an icon, assign the UnknownIcon */
474
if (pm == None && Scr->UnknownPm != None)
476
tmp_win->icon_width = Scr->UnknownWidth;
477
tmp_win->icon_height = Scr->UnknownHeight;
479
pm = XCreatePixmap(dpy, Scr->Root, tmp_win->icon_width,
480
tmp_win->icon_height, Scr->d_depth);
482
/* the copy plane works on color ! */
483
XCopyPlane(dpy, Scr->UnknownPm, pm, Scr->NormalGC,
484
0,0, tmp_win->icon_width, tmp_win->icon_height, 0, 0, 1 );
489
tmp_win->icon_height = 0;
490
tmp_win->icon_width = 0;
495
valuemask = CWBackPixmap;
496
attributes.background_pixmap = pm;
499
tmp_win->icon_w_width = MyFont_TextWidth(&Scr->IconFont,
500
tmp_win->icon_name, strlen(tmp_win->icon_name));
502
tmp_win->icon_w_width += 6;
503
if (tmp_win->icon_w_width < tmp_win->icon_width)
505
tmp_win->icon_x = (tmp_win->icon_width - tmp_win->icon_w_width)/2;
506
tmp_win->icon_x += 3;
507
tmp_win->icon_w_width = tmp_win->icon_width;
513
tmp_win->icon_y = tmp_win->icon_height + Scr->IconFont.height;
514
tmp_win->icon_w_height = tmp_win->icon_height + Scr->IconFont.height + 4;
517
if (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)
519
tmp_win->icon_w = tmp_win->wmhints->icon_window;
520
if (tmp_win->forced ||
521
XGetGeometry(dpy, tmp_win->icon_w, &JunkRoot, &JunkX, &JunkY,
522
(unsigned int *)&tmp_win->icon_w_width, (unsigned int *)&tmp_win->icon_w_height,
523
&JunkBW, &JunkDepth) == 0)
525
tmp_win->icon_w = None;
526
tmp_win->wmhints->flags &= ~IconWindowHint;
530
tmp_win->icon_not_ours = TRUE;
531
event_mask = EnterWindowMask | LeaveWindowMask;
536
tmp_win->icon_w = None;
539
if (tmp_win->icon_w == None)
541
tmp_win->icon_w = XCreateSimpleWindow(dpy, Scr->Root,
543
tmp_win->icon_w_width, tmp_win->icon_w_height,
544
Scr->IconBorderWidth, tmp_win->icon_border, tmp_win->iconc.back);
545
event_mask = ExposureMask;
548
XSelectInput (dpy, tmp_win->icon_w,
549
KeyPressMask | ButtonPressMask | ButtonReleaseMask |
552
tmp_win->icon_bm_w = None;
554
(! (tmp_win->wmhints && tmp_win->wmhints->flags & IconWindowHint)))
559
if (tmp_win->icon_w_width == tmp_win->icon_width)
562
x = (tmp_win->icon_w_width - tmp_win->icon_width)/2;
564
tmp_win->icon_bm_w = XCreateWindow (dpy, tmp_win->icon_w, x, y,
565
(unsigned int)tmp_win->icon_width,
566
(unsigned int)tmp_win->icon_height,
567
(unsigned int) 0, Scr->d_depth,
568
(unsigned int) CopyFromParent,
569
Scr->d_visual, valuemask,
573
/* I need to figure out where to put the icon window now, because
574
* getting here means that I am going to make the icon visible
576
if (tmp_win->wmhints &&
577
tmp_win->wmhints->flags & IconPositionHint)
579
final_x = tmp_win->wmhints->icon_x;
580
final_y = tmp_win->wmhints->icon_y;
584
PlaceIcon(tmp_win, def_x, def_y, &final_x, &final_y);
587
if (final_x > Scr->MyDisplayWidth)
588
final_x = Scr->MyDisplayWidth - tmp_win->icon_w_width -
589
(2 * Scr->IconBorderWidth);
591
if (final_y > Scr->MyDisplayHeight)
592
final_y = Scr->MyDisplayHeight - tmp_win->icon_height -
593
Scr->IconFont.height - 4 - (2 * Scr->IconBorderWidth);
595
XMoveWindow(dpy, tmp_win->icon_w, final_x, final_y);
596
tmp_win->iconified = TRUE;
598
XMapSubwindows(dpy, tmp_win->icon_w);
599
XSaveContext(dpy, tmp_win->icon_w, TwmContext, (caddr_t)tmp_win);
600
XSaveContext(dpy, tmp_win->icon_w, ScreenContext, (caddr_t)Scr);
601
XDefineCursor(dpy, tmp_win->icon_w, Scr->IconCursor);
602
if (pm) XFreePixmap (dpy, pm);