~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to src/switchpanel.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Window Maker window manager
 
3
 *
 
4
 *  Copyright (c) 1997-2004 Alfredo K. Kojima
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
19
 *  USA.
 
20
 */
 
21
 
 
22
#include "wconfig.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <sys/time.h>
 
27
 
 
28
#ifdef SHAPE
 
29
#include <X11/extensions/shape.h>
 
30
 
 
31
extern Bool wShapeSupported;
 
32
#endif
 
33
 
 
34
#include "WindowMaker.h"
 
35
#include "screen.h"
 
36
#include "wcore.h"
 
37
#include "framewin.h"
 
38
#include "window.h"
 
39
#include "defaults.h"
 
40
#include "switchpanel.h"
 
41
#include "funcs.h"
 
42
#include "xinerama.h"
 
43
 
 
44
struct SwitchPanel {
 
45
    WScreen *scr;
 
46
    WMWindow *win;
 
47
    WMFrame *iconBox;
 
48
    
 
49
    WMArray *icons;
 
50
    WMArray *images;
 
51
    WMArray *windows;
 
52
    RImage *bg;
 
53
    int current;
 
54
    int firstVisible;
 
55
    int visibleCount;
 
56
 
 
57
    WMLabel *label;
 
58
    
 
59
    RImage *defIcon;
 
60
    
 
61
    RImage *tileTmp;
 
62
    RImage *tile;
 
63
    
 
64
    WMFont *font;
 
65
    WMColor *white;
 
66
};
 
67
 
 
68
 
 
69
 
 
70
 
 
71
 
 
72
extern WPreferences wPreferences;
 
73
 
 
74
#define BORDER_SPACE 10
 
75
#define ICON_SIZE 48
 
76
#define ICON_TILE_SIZE 64
 
77
#define LABEL_HEIGHT 25
 
78
#define SCREEN_BORDER_SPACING 2*20
 
79
#define SCROLL_STEPS (ICON_TILE_SIZE/2)
 
80
 
 
81
static int canReceiveFocus(WWindow *wwin)
 
82
{
 
83
  if (wwin->frame->workspace != wwin->screen_ptr->current_workspace)
 
84
    return 0;
 
85
  if (!wwin->flags.mapped)
 
86
  {
 
87
    if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden)
 
88
      return 0;
 
89
    else
 
90
      return -1;
 
91
  }
 
92
  if (WFLAGP(wwin, no_focusable))
 
93
    return 0;
 
94
  return 1;
 
95
}
 
96
 
 
97
 
 
98
static void changeImage(WSwitchPanel *panel, int index, int selected)
 
99
{
 
100
    WMFrame *icon = WMGetFromArray(panel->icons, index);
 
101
    RImage *image= WMGetFromArray(panel->images, index);
 
102
 
 
103
    if (!panel->bg && !panel->tile) {
 
104
        if (!selected)
 
105
          WMSetFrameRelief(icon, WRFlat);
 
106
    }
 
107
 
 
108
    if (image && icon) {
 
109
        RImage *back;
 
110
        int opaq= 255;
 
111
        RImage *tile;
 
112
        WMPoint pos;
 
113
        Pixmap p;
 
114
 
 
115
        if (canReceiveFocus(WMGetFromArray(panel->windows, index)) < 0)
 
116
          opaq= 50;
 
117
 
 
118
        pos= WMGetViewPosition(WMWidgetView(icon));
 
119
        back= panel->tileTmp;
 
120
        if (panel->bg)
 
121
          RCopyArea(back, panel->bg,
 
122
                    BORDER_SPACE+pos.x-panel->firstVisible*ICON_TILE_SIZE, BORDER_SPACE+pos.y,
 
123
                    back->width, back->height,
 
124
                    0, 0);
 
125
        else
 
126
        {
 
127
            RColor color;
 
128
            WMScreen *wscr= WMWidgetScreen(icon);
 
129
            color.red= 255;
 
130
            color.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8;
 
131
            color.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8;
 
132
            color.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8;
 
133
            RFillImage(back, &color);
 
134
        }
 
135
        if (selected)
 
136
        {
 
137
            tile= panel->tile;
 
138
            RCombineArea(back, tile, 0, 0, tile->width, tile->height,
 
139
                         (back->width - tile->width)/2, (back->height - tile->height)/2);
 
140
        }
 
141
        RCombineAreaWithOpaqueness(back, image, 0, 0, image->width, image->height,
 
142
                                   (back->width - image->width)/2, (back->height - image->height)/2,
 
143
                                   opaq);
 
144
 
 
145
        RConvertImage(panel->scr->rcontext, back, &p);
 
146
        XSetWindowBackgroundPixmap(dpy, WMWidgetXID(icon), p);
 
147
        XClearWindow(dpy, WMWidgetXID(icon));
 
148
        XFreePixmap(dpy, p);
 
149
    }
 
150
 
 
151
    if (!panel->bg && !panel->tile) {
 
152
        if (selected)
 
153
          WMSetFrameRelief(icon, WRSimple);
 
154
    }
 
155
}
 
156
 
 
157
 
 
158
static RImage *scaleDownIfNeeded(RImage *image)
 
159
{
 
160
    if (image && ((image->width - ICON_SIZE) > 2 || (image->height - ICON_SIZE) > 2)) {
 
161
        RImage *nimage;
 
162
        nimage= RScaleImage(image, ICON_SIZE, (image->height * ICON_SIZE / image->width));
 
163
        RReleaseImage(image);
 
164
        image= nimage;
 
165
    }
 
166
    return image;
 
167
}
 
168
 
 
169
 
 
170
static void addIconForWindow(WSwitchPanel *panel, WMWidget *parent, WWindow *wwin,
 
171
                             int x, int y)
 
172
{
 
173
    WMFrame *icon= WMCreateFrame(parent);
 
174
    RImage *image = NULL;
 
175
 
 
176
    WMSetFrameRelief(icon, WRFlat);
 
177
    WMResizeWidget(icon, ICON_TILE_SIZE, ICON_TILE_SIZE);
 
178
    WMMoveWidget(icon, x, y);
 
179
    
 
180
    if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
 
181
      image = RRetainImage(wwin->net_icon_image);
 
182
    
 
183
    // Make this use a caching thing. When there are many windows,
 
184
    // it's very likely that most of them are instances of the same thing,
 
185
    // so caching them should get performance acceptable in these cases.
 
186
    if (!image)
 
187
      image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
 
188
    
 
189
    if (!image && !panel->defIcon) {
 
190
        char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
 
191
        if (file) {
 
192
            char *path = FindImage(wPreferences.icon_path, file);
 
193
            if (path) {
 
194
                image = RLoadImage(panel->scr->rcontext, path, 0);
 
195
                wfree(path);
 
196
            }
 
197
        }
 
198
        if (image)
 
199
          panel->defIcon= scaleDownIfNeeded(image);
 
200
        image= NULL;
 
201
    }
 
202
    if (!image && panel->defIcon)
 
203
      image= RRetainImage(panel->defIcon);
 
204
    
 
205
    image= scaleDownIfNeeded(image);
 
206
    
 
207
    WMAddToArray(panel->images, image);
 
208
    WMAddToArray(panel->icons, icon);
 
209
}
 
210
 
 
211
 
 
212
static void scrollIcons(WSwitchPanel *panel, int delta)
 
213
{
 
214
    int nfirst= panel->firstVisible + delta;
 
215
    int i;
 
216
    int count= WMGetArrayItemCount(panel->windows);
 
217
//    int nx, ox;
 
218
//    struct timeval tv1, tv2;
 
219
 
 
220
    if (count <= panel->visibleCount)
 
221
      return;
 
222
 
 
223
    if (nfirst < 0)
 
224
      nfirst= 0;
 
225
    else if (nfirst >= count-panel->visibleCount)
 
226
      nfirst= count-panel->visibleCount;
 
227
 
 
228
    if (nfirst == panel->firstVisible)
 
229
      return;
 
230
/*
 
231
    ox = -panel->firstVisible * ICON_TILE_SIZE;
 
232
    nx = -nfirst * ICON_TILE_SIZE;
 
233
    for (i= 0; i < SCROLL_STEPS; i++) {
 
234
        unsigned int diff;
 
235
        gettimeofday(&tv1, NULL);
 
236
        WMMoveWidget(panel->iconBox, (nx*i + ox*(SCROLL_STEPS-i))/(SCROLL_STEPS-1), 0);
 
237
        XSync(dpy, False);
 
238
        gettimeofday(&tv2, NULL);
 
239
        diff = (tv2.tv_sec-tv1.tv_sec)*10000+(tv2.tv_usec-tv1.tv_usec)/100;
 
240
        if (diff < 200)
 
241
          wusleep(300-diff);
 
242
    }
 
243
 */    
 
244
    WMMoveWidget(panel->iconBox, -nfirst*ICON_TILE_SIZE, 0);
 
245
 
 
246
    panel->firstVisible= nfirst;
 
247
    
 
248
    for (i= panel->firstVisible; i < panel->firstVisible+panel->visibleCount; i++) {
 
249
        changeImage(panel, i, i == panel->current);
 
250
    }
 
251
}
 
252
 
 
253
 
 
254
/*
 
255
 * 0 1 2
 
256
 * 3 4 5
 
257
 * 6 7 8
 
258
 */
 
259
static RImage *assemblePuzzleImage(RImage **images, int width, int height)
 
260
{
 
261
    RImage *img= RCreateImage(width, height, 1);
 
262
    RImage *tmp;
 
263
    int tw, th;
 
264
    RColor color;
 
265
    if (!img)
 
266
      return NULL;
 
267
 
 
268
    color.red= 0;
 
269
    color.green= 0;
 
270
    color.blue= 0;
 
271
    color.alpha= 255;
 
272
 
 
273
    RFillImage(img, &color);
 
274
 
 
275
    tw= width-images[0]->width-images[2]->width;
 
276
    th= height-images[0]->height-images[6]->height;
 
277
 
 
278
    if (tw <= 0 || th <= 0) {
 
279
        //XXX
 
280
        return NULL;
 
281
    }
 
282
 
 
283
    /* top */
 
284
    if (tw > 0) {
 
285
        tmp= RSmoothScaleImage(images[1], tw, images[1]->height);
 
286
        RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height,
 
287
                  images[0]->width, 0);
 
288
        RReleaseImage(tmp);
 
289
    }
 
290
    /* bottom */
 
291
    if (tw > 0) {
 
292
        tmp= RSmoothScaleImage(images[7], tw, images[7]->height);
 
293
        RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height,
 
294
                  images[6]->width, height-images[6]->height);
 
295
        RReleaseImage(tmp);
 
296
    }
 
297
    /* left */
 
298
    if (th > 0) {
 
299
        tmp= RSmoothScaleImage(images[3], images[3]->width, th);
 
300
        RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height,
 
301
                  0, images[0]->height);
 
302
        RReleaseImage(tmp);
 
303
    }
 
304
    /* right */
 
305
    if (th > 0) {
 
306
        tmp= RSmoothScaleImage(images[5], images[5]->width, th);
 
307
        RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height,
 
308
                  width-images[5]->width, images[2]->height);
 
309
        RReleaseImage(tmp);
 
310
    }
 
311
    /* center */
 
312
    if (tw > 0 && th > 0) {
 
313
        tmp= RSmoothScaleImage(images[4], tw, th);
 
314
        RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height,
 
315
                  images[0]->width, images[0]->height);
 
316
        RReleaseImage(tmp);
 
317
    }
 
318
 
 
319
    /* corners */
 
320
    RCopyArea(img, images[0], 0, 0, images[0]->width, images[0]->height,
 
321
              0, 0);
 
322
 
 
323
    RCopyArea(img, images[2], 0, 0, images[2]->width, images[2]->height,
 
324
              width-images[2]->width, 0);
 
325
 
 
326
    RCopyArea(img, images[6], 0, 0, images[6]->width, images[6]->height,
 
327
              0, height-images[6]->height);
 
328
 
 
329
    RCopyArea(img, images[8], 0, 0, images[8]->width, images[8]->height,
 
330
              width-images[8]->width, height-images[8]->height);
 
331
 
 
332
    return img;
 
333
}
 
334
 
 
335
static RImage *createBackImage(WScreen *scr, int width, int height)
 
336
{
 
337
    return assemblePuzzleImage(wPreferences.swbackImage, width, height);
 
338
}
 
339
 
 
340
 
 
341
static RImage *getTile(WSwitchPanel *panel)
 
342
{
 
343
    RImage *stile;
 
344
 
 
345
    if (!wPreferences.swtileImage)
 
346
        return NULL;
 
347
 
 
348
    stile = RScaleImage(wPreferences.swtileImage, ICON_TILE_SIZE, ICON_TILE_SIZE);
 
349
    if (!stile)
 
350
        return wPreferences.swtileImage;
 
351
    
 
352
    return stile;
 
353
}
 
354
 
 
355
 
 
356
static void
 
357
drawTitle(WSwitchPanel *panel, int index, char *title)
 
358
{
 
359
    char *ntitle;
 
360
    int width= WMWidgetWidth(panel->win);
 
361
    int x;
 
362
 
 
363
    ntitle= ShrinkString(panel->font, title, width-2*BORDER_SPACE);
 
364
 
 
365
    if (panel->bg) {
 
366
        if (strcmp(ntitle, title)!=0)
 
367
          x= BORDER_SPACE;
 
368
        else
 
369
        {
 
370
            int w= WMWidthOfString(panel->font, ntitle, strlen(ntitle));
 
371
            
 
372
            x= BORDER_SPACE+(index-panel->firstVisible)*ICON_TILE_SIZE + ICON_TILE_SIZE/2 - w/2;
 
373
            if (x < BORDER_SPACE)
 
374
              x= BORDER_SPACE;
 
375
            else if (x + w > width-BORDER_SPACE)
 
376
              x= width-BORDER_SPACE-w;
 
377
        }
 
378
        
 
379
        XClearWindow(dpy, WMWidgetXID(panel->win));
 
380
        WMDrawString(panel->scr->wmscreen, 
 
381
                     WMWidgetXID(panel->win),
 
382
                     panel->white, panel->font,
 
383
                     x, WMWidgetHeight(panel->win) - BORDER_SPACE - LABEL_HEIGHT + WMFontHeight(panel->font)/2,
 
384
                     ntitle, strlen(ntitle));
 
385
    } else {
 
386
        WMSetLabelText(panel->label, ntitle);
 
387
    }
 
388
    free(ntitle);
 
389
}
 
390
 
 
391
 
 
392
 
 
393
static WMArray *makeWindowListArray(WScreen *scr, WWindow *curwin, int workspace)
 
394
{
 
395
    WMArray *windows= WMCreateArray(10);
 
396
    int fl;
 
397
    WWindow *wwin;
 
398
 
 
399
    for (fl= 0; fl < 2; fl++) {
 
400
        for (wwin= curwin; wwin; wwin= wwin->prev) {
 
401
            if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
 
402
                (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
 
403
                WMAddToArray(windows, wwin);
 
404
            }
 
405
        }
 
406
        wwin = curwin;
 
407
        /* start over from the beginning of the list */
 
408
        while (wwin->next)
 
409
          wwin = wwin->next;
 
410
        
 
411
        for (wwin= curwin; wwin && wwin != curwin; wwin= wwin->prev) {
 
412
            if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
 
413
                (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
 
414
                WMAddToArray(windows, wwin);
 
415
            }
 
416
        }
 
417
    }
 
418
 
 
419
    return windows;
 
420
}
 
421
 
 
422
 
 
423
 
 
424
 
 
425
 
 
426
WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace)
 
427
{
 
428
    WWindow *wwin;
 
429
    WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel));
 
430
    WMFrame *viewport;
 
431
    int i;
 
432
    int width, height;
 
433
    int iconsThatFitCount;
 
434
    int count;
 
435
    WMRect rect;
 
436
    rect= wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
 
437
 
 
438
    memset(panel, 0, sizeof(WSwitchPanel));
 
439
 
 
440
    panel->scr= scr;
 
441
 
 
442
    panel->windows= makeWindowListArray(scr, curwin, workspace);
 
443
    count= WMGetArrayItemCount(panel->windows);
 
444
    
 
445
    if (count == 0) {
 
446
        WMFreeArray(panel->windows);
 
447
        wfree(panel);
 
448
        return NULL;
 
449
    }
 
450
 
 
451
    width= ICON_TILE_SIZE*count;
 
452
    iconsThatFitCount= count;
 
453
 
 
454
    if (width > rect.size.width) {
 
455
        iconsThatFitCount = (WMScreenWidth(scr->wmscreen)-SCREEN_BORDER_SPACING)/ICON_TILE_SIZE;
 
456
        width= iconsThatFitCount*ICON_TILE_SIZE;
 
457
    }
 
458
    
 
459
    panel->visibleCount= iconsThatFitCount;
 
460
 
 
461
    height= LABEL_HEIGHT + ICON_TILE_SIZE;
 
462
 
 
463
    panel->tileTmp= RCreateImage(ICON_TILE_SIZE, ICON_TILE_SIZE, 1);
 
464
    panel->tile= getTile(panel);
 
465
    if (panel->tile && wPreferences.swbackImage[8]) {
 
466
        panel->bg= createBackImage(scr, width+2*BORDER_SPACE, height+2*BORDER_SPACE);
 
467
    }
 
468
    if (!panel->tileTmp || !panel->tile) {
 
469
        if (panel->bg)
 
470
          RReleaseImage(panel->bg);
 
471
        panel->bg= NULL;
 
472
        if (panel->tile)
 
473
          RReleaseImage(panel->tile);
 
474
        panel->tile= NULL;
 
475
        if (panel->tileTmp)
 
476
          RReleaseImage(panel->tileTmp);
 
477
        panel->tileTmp= NULL;
 
478
    }
 
479
 
 
480
    panel->white= WMWhiteColor(scr->wmscreen);
 
481
    panel->font= WMBoldSystemFontOfSize(scr->wmscreen, 12);
 
482
    panel->icons= WMCreateArray(count);
 
483
    panel->images= WMCreateArray(count);
 
484
 
 
485
    panel->win = WMCreateWindow(scr->wmscreen, "");
 
486
 
 
487
    if (!panel->bg) {
 
488
        WMFrame *frame = WMCreateFrame(panel->win);
 
489
        WMSetFrameRelief(frame, WRSimple);
 
490
        WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
 
491
        
 
492
        panel->label = WMCreateLabel(panel->win);
 
493
        WMResizeWidget(panel->label, width, LABEL_HEIGHT);
 
494
        WMMoveWidget(panel->label, BORDER_SPACE, BORDER_SPACE+ICON_TILE_SIZE+5);
 
495
        WMSetLabelRelief(panel->label, WRSimple);
 
496
        WMSetWidgetBackgroundColor(panel->label, WMDarkGrayColor(scr->wmscreen));
 
497
        WMSetLabelFont(panel->label, panel->font);
 
498
        WMSetLabelTextColor(panel->label, panel->white);
 
499
        
 
500
        height+= 5;
 
501
    }
 
502
    
 
503
    WMResizeWidget(panel->win, width + 2*BORDER_SPACE, height + 2*BORDER_SPACE);
 
504
    
 
505
    viewport= WMCreateFrame(panel->win);
 
506
    WMResizeWidget(viewport, width, ICON_TILE_SIZE);
 
507
    WMMoveWidget(viewport, BORDER_SPACE, BORDER_SPACE);
 
508
    WMSetFrameRelief(viewport, WRFlat);
 
509
    
 
510
    panel->iconBox= WMCreateFrame(viewport);
 
511
    WMMoveWidget(panel->iconBox, 0, 0);
 
512
    WMResizeWidget(panel->iconBox, ICON_TILE_SIZE*count, ICON_TILE_SIZE);
 
513
    WMSetFrameRelief(panel->iconBox, WRFlat);
 
514
    
 
515
    WM_ITERATE_ARRAY(panel->windows, wwin, i) {
 
516
        addIconForWindow(panel, panel->iconBox, wwin, i*ICON_TILE_SIZE, 0);
 
517
    }
 
518
 
 
519
    WMMapSubwidgets(panel->win);
 
520
    WMRealizeWidget(panel->win);
 
521
    
 
522
    WM_ITERATE_ARRAY(panel->windows, wwin, i) {
 
523
        changeImage(panel, i, 0);
 
524
    }
 
525
    
 
526
    if (panel->bg) {
 
527
        Pixmap pixmap, mask;
 
528
 
 
529
        RConvertImageMask(scr->rcontext, panel->bg, &pixmap, &mask, 250);
 
530
 
 
531
        XSetWindowBackgroundPixmap(dpy, WMWidgetXID(panel->win), pixmap);
 
532
 
 
533
#ifdef SHAPE
 
534
        if (mask && wShapeSupported)
 
535
          XShapeCombineMask(dpy, WMWidgetXID(panel->win),
 
536
                            ShapeBounding, 0, 0, mask, ShapeSet);
 
537
#endif
 
538
        
 
539
        if (pixmap)
 
540
          XFreePixmap(dpy, pixmap);
 
541
        if (mask)
 
542
          XFreePixmap(dpy, mask);
 
543
    }
 
544
 
 
545
    {
 
546
        WMPoint center;
 
547
        center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
 
548
                                            width+2*BORDER_SPACE, height+2*BORDER_SPACE);
 
549
        WMMoveWidget(panel->win, center.x, center.y);
 
550
    }
 
551
 
 
552
    panel->current= WMGetFirstInArray(panel->windows, curwin);
 
553
    if (panel->current >= 0)
 
554
        changeImage(panel, panel->current, 1);
 
555
 
 
556
    WMMapWidget(panel->win);
 
557
 
 
558
    return panel;
 
559
}
 
560
 
 
561
 
 
562
void wSwitchPanelDestroy(WSwitchPanel *panel)
 
563
{
 
564
    int i;
 
565
    RImage *image;
 
566
    
 
567
    if (panel->win)
 
568
      WMUnmapWidget(panel->win);
 
569
 
 
570
    if (panel->images) {
 
571
        WM_ITERATE_ARRAY(panel->images, image, i) {
 
572
            if (image)
 
573
              RReleaseImage(image);
 
574
        }
 
575
        WMFreeArray(panel->images);
 
576
    }
 
577
    if (panel->win)
 
578
      WMDestroyWidget(panel->win);
 
579
    if (panel->icons)
 
580
      WMFreeArray(panel->icons);
 
581
    WMFreeArray(panel->windows);
 
582
    if (panel->defIcon)
 
583
      RReleaseImage(panel->defIcon);
 
584
    if (panel->tile)
 
585
      RReleaseImage(panel->tile);
 
586
    if (panel->tileTmp)
 
587
      RReleaseImage(panel->tileTmp);
 
588
    if (panel->bg)
 
589
      RReleaseImage(panel->bg);
 
590
    if (panel->font)
 
591
      WMReleaseFont(panel->font);
 
592
    wfree(panel);
 
593
}
 
594
 
 
595
 
 
596
WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
 
597
{
 
598
    WWindow *wwin;
 
599
    int count = WMGetArrayItemCount(panel->windows);
 
600
    
 
601
    if (count == 0)
 
602
      return NULL;
 
603
    
 
604
    if (panel->win)
 
605
      changeImage(panel, panel->current, 0);
 
606
    
 
607
    if (back)
 
608
      panel->current--;
 
609
    else
 
610
      panel->current++;
 
611
 
 
612
    wwin = WMGetFromArray(panel->windows, (count+panel->current)%count);
 
613
 
 
614
    if (back)
 
615
    {
 
616
        if (panel->current < 0)
 
617
          scrollIcons(panel, count);
 
618
        else if (panel->current < panel->firstVisible)
 
619
          scrollIcons(panel, -1);
 
620
    }
 
621
    else
 
622
    {
 
623
        if (panel->current >= count)
 
624
          scrollIcons(panel, -count);
 
625
        else if (panel->current - panel->firstVisible >= panel->visibleCount)
 
626
          scrollIcons(panel, 1);
 
627
    }
 
628
 
 
629
    panel->current= (count+panel->current)%count;
 
630
 
 
631
    if (panel->win) {
 
632
        drawTitle(panel, panel->current, wwin->frame->title);
 
633
 
 
634
        changeImage(panel, panel->current, 1);
 
635
    }
 
636
 
 
637
    return wwin;
 
638
}
 
639
 
 
640
 
 
641
WWindow *wSwitchPanelSelectFirst(WSwitchPanel *panel, int back)
 
642
{
 
643
    WWindow *wwin;
 
644
    int count = WMGetArrayItemCount(panel->windows);
 
645
 
 
646
    if (count == 0)
 
647
      return NULL;
 
648
 
 
649
    if (panel->win)
 
650
      changeImage(panel, panel->current, 0);
 
651
    
 
652
    if (back) {
 
653
        panel->current = count-1;
 
654
        scrollIcons(panel, count);
 
655
    } else {
 
656
        panel->current = 0;
 
657
        scrollIcons(panel, -count);
 
658
    }
 
659
    
 
660
    wwin = WMGetFromArray(panel->windows, panel->current);
 
661
    
 
662
    if (panel->win) {
 
663
        drawTitle(panel, panel->current, wwin->frame->title);
 
664
 
 
665
        changeImage(panel, panel->current, 1);
 
666
    }
 
667
    return wwin;
 
668
}
 
669
 
 
670
 
 
671
WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
 
672
{
 
673
    WMFrame *icon;
 
674
    int i;
 
675
    
 
676
    if (!panel->win)
 
677
      return NULL;
 
678
 
 
679
    if (event->type == MotionNotify) {
 
680
        int focus= -1;
 
681
 
 
682
        WM_ITERATE_ARRAY(panel->icons, icon, i) {
 
683
            if (WMWidgetXID(icon) == event->xmotion.window) {
 
684
                focus= i;
 
685
                break;
 
686
            }
 
687
        }
 
688
 
 
689
        if (focus < 0)
 
690
          focus= 0;
 
691
        
 
692
        if (focus >= 0 && panel->current != focus) {
 
693
            WWindow *wwin;
 
694
            
 
695
            changeImage(panel, panel->current, 0);
 
696
            changeImage(panel, focus, 1);
 
697
            panel->current= focus;
 
698
            
 
699
            wwin= WMGetFromArray(panel->windows, focus);
 
700
            
 
701
            drawTitle(panel, panel->current, wwin->frame->title);
 
702
            
 
703
            return wwin;
 
704
        }
 
705
    }
 
706
 
 
707
    return NULL;
 
708
}
 
709
 
 
710
 
 
711
Window wSwitchPanelGetWindow(WSwitchPanel *swpanel)
 
712
{
 
713
    if (!swpanel->win)
 
714
      return None;
 
715
    return WMWidgetXID(swpanel->win);
 
716
}