Change to the linux kernel coding style
[wmaker-crm.git] / src / switchpanel.c
Commit [+]AuthorDateLineData
f54f0856 kojima2004-10-14 05:02:24 +00001/*
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>
cd36d738 kojima2004-10-15 00:27:36 +000025#include <string.h>
f274afdd kojima2004-10-25 00:07:51 +000026#include <sys/time.h>
27
f54f0856 kojima2004-10-14 05:02:24 +000028#include "WindowMaker.h"
29#include "screen.h"
30#include "wcore.h"
31#include "framewin.h"
32#include "window.h"
33#include "defaults.h"
34#include "switchpanel.h"
35#include "funcs.h"
5f4a3f67 kojima2004-10-14 19:12:26 +000036#include "xinerama.h"
37
e53ddd04 dan2004-10-30 07:17:49 +000038#ifdef SHAPE
39#include <X11/extensions/shape.h>
40
41extern Bool wShapeSupported;
42#endif
43
f54f0856 kojima2004-10-14 05:02:24 +000044struct SwitchPanel {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020045 WScreen *scr;
46 WMWindow *win;
47 WMFrame *iconBox;
f54f0856 kojima2004-10-14 05:02:24 +000048
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020049 WMArray *icons;
50 WMArray *images;
51 WMArray *windows;
52 RImage *bg;
53 int current;
54 int firstVisible;
55 int visibleCount;
f54f0856 kojima2004-10-14 05:02:24 +000056
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020057 WMLabel *label;
5f4a3f67 kojima2004-10-14 19:12:26 +000058
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020059 RImage *defIcon;
5f4a3f67 kojima2004-10-14 19:12:26 +000060
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020061 RImage *tileTmp;
62 RImage *tile;
63
64 WMFont *font;
65 WMColor *white;
66};
5f4a3f67 kojima2004-10-14 19:12:26 +000067
f54f0856 kojima2004-10-14 05:02:24 +000068extern WPreferences wPreferences;
69
f274afdd kojima2004-10-25 00:07:51 +000070#define BORDER_SPACE 10
71#define ICON_SIZE 48
72#define ICON_TILE_SIZE 64
f6682a9a kojima2004-10-20 03:31:14 +000073#define LABEL_HEIGHT 25
f274afdd kojima2004-10-25 00:07:51 +000074#define SCREEN_BORDER_SPACING 2*20
75#define SCROLL_STEPS (ICON_TILE_SIZE/2)
f6fb9fbb kojima2004-10-19 01:29:34 +000076
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020077static int canReceiveFocus(WWindow * wwin)
f6fb9fbb kojima2004-10-19 01:29:34 +000078{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020079 if (wwin->frame->workspace != wwin->screen_ptr->current_workspace)
80 return 0;
81 if (!wwin->flags.mapped) {
82 if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden)
83 return 0;
84 else
85 return -1;
86 }
87 if (WFLAGP(wwin, no_focusable))
88 return 0;
89 return 1;
f6fb9fbb kojima2004-10-19 01:29:34 +000090}
91
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020092static void changeImage(WSwitchPanel * panel, int idecks, int selected)
5f4a3f67 kojima2004-10-14 19:12:26 +000093{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020094 WMFrame *icon = WMGetFromArray(panel->icons, idecks);
95 RImage *image = WMGetFromArray(panel->images, idecks);
96
97 if (!panel->bg && !panel->tile) {
98 if (!selected)
99 WMSetFrameRelief(icon, WRFlat);
100 }
101
102 if (image && icon) {
103 RImage *back;
104 int opaq = 255;
105 RImage *tile;
106 WMPoint pos;
107 Pixmap p;
108
109 if (canReceiveFocus(WMGetFromArray(panel->windows, idecks)) < 0)
110 opaq = 50;
111
112 pos = WMGetViewPosition(WMWidgetView(icon));
113 back = panel->tileTmp;
114 if (panel->bg)
115 RCopyArea(back, panel->bg,
116 BORDER_SPACE + pos.x - panel->firstVisible * ICON_TILE_SIZE,
117 BORDER_SPACE + pos.y, back->width, back->height, 0, 0);
118 else {
119 RColor color;
120 WMScreen *wscr = WMWidgetScreen(icon);
121 color.red = 255;
122 color.red = WMRedComponentOfColor(WMGrayColor(wscr)) >> 8;
123 color.green = WMGreenComponentOfColor(WMGrayColor(wscr)) >> 8;
124 color.blue = WMBlueComponentOfColor(WMGrayColor(wscr)) >> 8;
125 RFillImage(back, &color);
126 }
127 if (selected) {
128 tile = panel->tile;
129 RCombineArea(back, tile, 0, 0, tile->width, tile->height,
130 (back->width - tile->width) / 2, (back->height - tile->height) / 2);
131 }
132 RCombineAreaWithOpaqueness(back, image, 0, 0, image->width, image->height,
133 (back->width - image->width) / 2, (back->height - image->height) / 2,
134 opaq);
135
136 RConvertImage(panel->scr->rcontext, back, &p);
137 XSetWindowBackgroundPixmap(dpy, WMWidgetXID(icon), p);
138 XClearWindow(dpy, WMWidgetXID(icon));
139 XFreePixmap(dpy, p);
140 }
141
142 if (!panel->bg && !panel->tile) {
143 if (selected)
144 WMSetFrameRelief(icon, WRSimple);
145 }
5f4a3f67 kojima2004-10-14 19:12:26 +0000146}
147
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200148static RImage *scaleDownIfNeeded(RImage * image)
f54f0856 kojima2004-10-14 05:02:24 +0000149{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200150 if (image && ((image->width - ICON_SIZE) > 2 || (image->height - ICON_SIZE) > 2)) {
151 RImage *nimage;
152 nimage = RScaleImage(image, ICON_SIZE, (image->height * ICON_SIZE / image->width));
153 RReleaseImage(image);
154 image = nimage;
155 }
156 return image;
f274afdd kojima2004-10-25 00:07:51 +0000157}
158
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200159static void addIconForWindow(WSwitchPanel * panel, WMWidget * parent, WWindow * wwin, int x, int y)
f274afdd kojima2004-10-25 00:07:51 +0000160{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200161 WMFrame *icon = WMCreateFrame(parent);
162 RImage *image = NULL;
163
164 WMSetFrameRelief(icon, WRFlat);
165 WMResizeWidget(icon, ICON_TILE_SIZE, ICON_TILE_SIZE);
166 WMMoveWidget(icon, x, y);
167
168 if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
169 image = RRetainImage(wwin->net_icon_image);
170
171 // Make this use a caching thing. When there are many windows,
172 // it's very likely that most of them are instances of the same thing,
173 // so caching them should get performance acceptable in these cases.
174 if (!image)
175 image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
176
177 if (!image && !panel->defIcon) {
178 char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
179 if (file) {
180 char *path = FindImage(wPreferences.icon_path, file);
181 if (path) {
182 image = RLoadImage(panel->scr->rcontext, path, 0);
183 wfree(path);
184 }
185 }
186 if (image)
187 panel->defIcon = scaleDownIfNeeded(image);
188 image = NULL;
189 }
190 if (!image && panel->defIcon)
191 image = RRetainImage(panel->defIcon);
192
193 image = scaleDownIfNeeded(image);
194
195 WMAddToArray(panel->images, image);
196 WMAddToArray(panel->icons, icon);
f274afdd kojima2004-10-25 00:07:51 +0000197}
5f4a3f67 kojima2004-10-14 19:12:26 +0000198
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200199static void scrollIcons(WSwitchPanel * panel, int delta)
f274afdd kojima2004-10-25 00:07:51 +0000200{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200201 int nfirst = panel->firstVisible + delta;
202 int i;
203 int count = WMGetArrayItemCount(panel->windows);
f274afdd kojima2004-10-25 00:07:51 +0000204// int nx, ox;
205// struct timeval tv1, tv2;
206
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200207 if (count <= panel->visibleCount)
208 return;
f274afdd kojima2004-10-25 00:07:51 +0000209
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200210 if (nfirst < 0)
211 nfirst = 0;
212 else if (nfirst >= count - panel->visibleCount)
213 nfirst = count - panel->visibleCount;
f274afdd kojima2004-10-25 00:07:51 +0000214
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200215 if (nfirst == panel->firstVisible)
216 return;
f274afdd kojima2004-10-25 00:07:51 +0000217/*
218 ox = -panel->firstVisible * ICON_TILE_SIZE;
219 nx = -nfirst * ICON_TILE_SIZE;
220 for (i= 0; i < SCROLL_STEPS; i++) {
221 unsigned int diff;
222 gettimeofday(&tv1, NULL);
223 WMMoveWidget(panel->iconBox, (nx*i + ox*(SCROLL_STEPS-i))/(SCROLL_STEPS-1), 0);
224 XSync(dpy, False);
225 gettimeofday(&tv2, NULL);
226 diff = (tv2.tv_sec-tv1.tv_sec)*10000+(tv2.tv_usec-tv1.tv_usec)/100;
227 if (diff < 200)
228 wusleep(300-diff);
5f4a3f67 kojima2004-10-14 19:12:26 +0000229 }
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200230 */
231 WMMoveWidget(panel->iconBox, -nfirst * ICON_TILE_SIZE, 0);
f54f0856 kojima2004-10-14 05:02:24 +0000232
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200233 panel->firstVisible = nfirst;
f54f0856 kojima2004-10-14 05:02:24 +0000234
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200235 for (i = panel->firstVisible; i < panel->firstVisible + panel->visibleCount; i++) {
236 changeImage(panel, i, i == panel->current);
237 }
238}
f54f0856 kojima2004-10-14 05:02:24 +0000239
f274afdd kojima2004-10-25 00:07:51 +0000240/*
241 * 0 1 2
242 * 3 4 5
243 * 6 7 8
244 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200245static RImage *assemblePuzzleImage(RImage ** images, int width, int height)
f54f0856 kojima2004-10-14 05:02:24 +0000246{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200247 RImage *img = RCreateImage(width, height, 1);
248 RImage *tmp;
249 int tw, th;
250 RColor color;
251 if (!img)
252 return NULL;
253
254 color.red = 0;
255 color.green = 0;
256 color.blue = 0;
257 color.alpha = 255;
258
259 RFillImage(img, &color);
260
261 tw = width - images[0]->width - images[2]->width;
262 th = height - images[0]->height - images[6]->height;
263
264 if (tw <= 0 || th <= 0) {
265 //XXX
266 return NULL;
267 }
268
269 /* top */
270 if (tw > 0) {
271 tmp = RSmoothScaleImage(images[1], tw, images[1]->height);
272 RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, images[0]->width, 0);
273 RReleaseImage(tmp);
274 }
275 /* bottom */
276 if (tw > 0) {
277 tmp = RSmoothScaleImage(images[7], tw, images[7]->height);
278 RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, images[6]->width, height - images[6]->height);
279 RReleaseImage(tmp);
280 }
281 /* left */
282 if (th > 0) {
283 tmp = RSmoothScaleImage(images[3], images[3]->width, th);
284 RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, 0, images[0]->height);
285 RReleaseImage(tmp);
286 }
287 /* right */
288 if (th > 0) {
289 tmp = RSmoothScaleImage(images[5], images[5]->width, th);
290 RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, width - images[5]->width, images[2]->height);
291 RReleaseImage(tmp);
292 }
293 /* center */
294 if (tw > 0 && th > 0) {
295 tmp = RSmoothScaleImage(images[4], tw, th);
296 RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, images[0]->width, images[0]->height);
297 RReleaseImage(tmp);
298 }
299
300 /* corners */
301 RCopyArea(img, images[0], 0, 0, images[0]->width, images[0]->height, 0, 0);
302
303 RCopyArea(img, images[2], 0, 0, images[2]->width, images[2]->height, width - images[2]->width, 0);
304
305 RCopyArea(img, images[6], 0, 0, images[6]->width, images[6]->height, 0, height - images[6]->height);
306
307 RCopyArea(img, images[8], 0, 0, images[8]->width, images[8]->height,
308 width - images[8]->width, height - images[8]->height);
309
310 return img;
311}
f274afdd kojima2004-10-25 00:07:51 +0000312
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200313static RImage *createBackImage(WScreen * scr, int width, int height)
314{
315 return assemblePuzzleImage(wPreferences.swbackImage, width, height);
316}
f274afdd kojima2004-10-25 00:07:51 +0000317
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200318static RImage *getTile(WSwitchPanel * panel)
319{
320 RImage *stile;
f274afdd kojima2004-10-25 00:07:51 +0000321
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200322 if (!wPreferences.swtileImage)
323 return NULL;
f274afdd kojima2004-10-25 00:07:51 +0000324
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200325 stile = RScaleImage(wPreferences.swtileImage, ICON_TILE_SIZE, ICON_TILE_SIZE);
326 if (!stile)
327 return wPreferences.swtileImage;
f274afdd kojima2004-10-25 00:07:51 +0000328
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200329 return stile;
f274afdd kojima2004-10-25 00:07:51 +0000330}
331
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200332static void drawTitle(WSwitchPanel * panel, int idecks, char *title)
f274afdd kojima2004-10-25 00:07:51 +0000333{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200334 char *ntitle;
335 int width = WMWidgetWidth(panel->win);
336 int x;
337
338 if (title)
339 ntitle = ShrinkString(panel->font, title, width - 2 * BORDER_SPACE);
340 else
341 ntitle = NULL;
342
343 if (panel->bg) {
344 if (ntitle) {
345 if (strcmp(ntitle, title) != 0)
346 x = BORDER_SPACE;
347 else {
348 int w = WMWidthOfString(panel->font, ntitle, strlen(ntitle));
349
350 x = BORDER_SPACE + (idecks - panel->firstVisible) * ICON_TILE_SIZE +
351 ICON_TILE_SIZE / 2 - w / 2;
352 if (x < BORDER_SPACE)
353 x = BORDER_SPACE;
354 else if (x + w > width - BORDER_SPACE)
355 x = width - BORDER_SPACE - w;
356 }
357 }
358 XClearWindow(dpy, WMWidgetXID(panel->win));
359 if (ntitle)
360 WMDrawString(panel->scr->wmscreen,
361 WMWidgetXID(panel->win),
362 panel->white, panel->font,
363 x,
364 WMWidgetHeight(panel->win) - BORDER_SPACE - LABEL_HEIGHT +
365 WMFontHeight(panel->font) / 2, ntitle, strlen(ntitle));
366 } else {
367 if (ntitle)
368 WMSetLabelText(panel->label, ntitle);
369 }
370 if (ntitle)
371 free(ntitle);
f274afdd kojima2004-10-25 00:07:51 +0000372}
373
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200374static WMArray *makeWindowListArray(WScreen * scr, WWindow * curwin, int workspace, int include_unmapped)
f274afdd kojima2004-10-25 00:07:51 +0000375{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200376 WMArray *windows = WMCreateArray(10);
377 int fl;
378 WWindow *wwin;
379
380 for (fl = 0; fl < 2; fl++) {
381 for (wwin = curwin; wwin; wwin = wwin->prev) {
382 if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
383 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window) &&
384 (wwin->flags.mapped || include_unmapped)) {
385 WMAddToArray(windows, wwin);
386 }
387 }
388 wwin = curwin;
389 /* start over from the beginning of the list */
390 while (wwin->next)
391 wwin = wwin->next;
392
393 for (wwin = curwin; wwin && wwin != curwin; wwin = wwin->prev) {
394 if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
395 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window) &&
396 (wwin->flags.mapped || include_unmapped)) {
397 WMAddToArray(windows, wwin);
398 }
399 }
400 }
401
402 return windows;
f274afdd kojima2004-10-25 00:07:51 +0000403}
404
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200405WSwitchPanel *wInitSwitchPanel(WScreen * scr, WWindow * curwin, int workspace)
f274afdd kojima2004-10-25 00:07:51 +0000406{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200407 WWindow *wwin;
408 WSwitchPanel *panel = wmalloc(sizeof(WSwitchPanel));
409 WMFrame *viewport;
410 int i;
411 int width, height;
412 int iconsThatFitCount;
413 int count;
414 WMRect rect;
415 rect = wGetRectForHead(scr, wGetHeadForPointerLocation(scr));
416
417 memset(panel, 0, sizeof(WSwitchPanel));
418
419 panel->scr = scr;
420
421 panel->windows = makeWindowListArray(scr, curwin, workspace, wPreferences.swtileImage != 0);
422 count = WMGetArrayItemCount(panel->windows);
423
424 if (count == 0) {
425 WMFreeArray(panel->windows);
426 wfree(panel);
427 return NULL;
428 }
429
430 width = ICON_TILE_SIZE * count;
431 iconsThatFitCount = count;
432
433 if (width > rect.size.width) {
434 iconsThatFitCount = (rect.size.width - SCREEN_BORDER_SPACING) / ICON_TILE_SIZE;
435 width = iconsThatFitCount * ICON_TILE_SIZE;
436 }
437
438 panel->visibleCount = iconsThatFitCount;
439
440 if (!wPreferences.swtileImage)
441 return panel;
442
443 height = LABEL_HEIGHT + ICON_TILE_SIZE;
444
445 panel->tileTmp = RCreateImage(ICON_TILE_SIZE, ICON_TILE_SIZE, 1);
446 panel->tile = getTile(panel);
447 if (panel->tile && wPreferences.swbackImage[8]) {
448 panel->bg = createBackImage(scr, width + 2 * BORDER_SPACE, height + 2 * BORDER_SPACE);
449 }
450 if (!panel->tileTmp || !panel->tile) {
451 if (panel->bg)
452 RReleaseImage(panel->bg);
453 panel->bg = NULL;
454 if (panel->tile)
455 RReleaseImage(panel->tile);
456 panel->tile = NULL;
457 if (panel->tileTmp)
458 RReleaseImage(panel->tileTmp);
459 panel->tileTmp = NULL;
460 }
461
462 panel->white = WMWhiteColor(scr->wmscreen);
463 panel->font = WMBoldSystemFontOfSize(scr->wmscreen, 12);
464 panel->icons = WMCreateArray(count);
465 panel->images = WMCreateArray(count);
466
467 panel->win = WMCreateWindow(scr->wmscreen, "");
468
469 if (!panel->bg) {
470 WMFrame *frame = WMCreateFrame(panel->win);
471 WMColor *darkGray = WMDarkGrayColor(scr->wmscreen);
472 WMSetFrameRelief(frame, WRSimple);
473 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
474
475 panel->label = WMCreateLabel(panel->win);
476 WMResizeWidget(panel->label, width, LABEL_HEIGHT);
477 WMMoveWidget(panel->label, BORDER_SPACE, BORDER_SPACE + ICON_TILE_SIZE + 5);
478 WMSetLabelRelief(panel->label, WRSimple);
479 WMSetWidgetBackgroundColor(panel->label, darkGray);
480 WMSetLabelFont(panel->label, panel->font);
481 WMSetLabelTextColor(panel->label, panel->white);
482
483 WMReleaseColor(darkGray);
484 height += 5;
485 }
486
487 WMResizeWidget(panel->win, width + 2 * BORDER_SPACE, height + 2 * BORDER_SPACE);
488
489 viewport = WMCreateFrame(panel->win);
490 WMResizeWidget(viewport, width, ICON_TILE_SIZE);
491 WMMoveWidget(viewport, BORDER_SPACE, BORDER_SPACE);
492 WMSetFrameRelief(viewport, WRFlat);
493
494 panel->iconBox = WMCreateFrame(viewport);
495 WMMoveWidget(panel->iconBox, 0, 0);
496 WMResizeWidget(panel->iconBox, ICON_TILE_SIZE * count, ICON_TILE_SIZE);
497 WMSetFrameRelief(panel->iconBox, WRFlat);
498
499 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
500 addIconForWindow(panel, panel->iconBox, wwin, i * ICON_TILE_SIZE, 0);
501 }
502
503 WMMapSubwidgets(panel->win);
504 WMRealizeWidget(panel->win);
505
506 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
507 changeImage(panel, i, 0);
508 }
509
510 if (panel->bg) {
511 Pixmap pixmap, mask;
512
513 RConvertImageMask(scr->rcontext, panel->bg, &pixmap, &mask, 250);
f274afdd kojima2004-10-25 00:07:51 +0000514
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200515 XSetWindowBackgroundPixmap(dpy, WMWidgetXID(panel->win), pixmap);
f274afdd kojima2004-10-25 00:07:51 +0000516
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200517#ifdef SHAPE
518 if (mask && wShapeSupported)
519 XShapeCombineMask(dpy, WMWidgetXID(panel->win), ShapeBounding, 0, 0, mask, ShapeSet);
520#endif
f274afdd kojima2004-10-25 00:07:51 +0000521
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200522 if (pixmap)
523 XFreePixmap(dpy, pixmap);
524 if (mask)
525 XFreePixmap(dpy, mask);
526 }
f54f0856 kojima2004-10-14 05:02:24 +0000527
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200528 {
529 WMPoint center;
530 center = wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
531 width + 2 * BORDER_SPACE, height + 2 * BORDER_SPACE);
532 WMMoveWidget(panel->win, center.x, center.y);
533 }
f274afdd kojima2004-10-25 00:07:51 +0000534
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200535 panel->current = WMGetFirstInArray(panel->windows, curwin);
536 if (panel->current >= 0)
537 changeImage(panel, panel->current, 1);
f274afdd kojima2004-10-25 00:07:51 +0000538
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200539 WMMapWidget(panel->win);
f274afdd kojima2004-10-25 00:07:51 +0000540
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200541 return panel;
542}
f274afdd kojima2004-10-25 00:07:51 +0000543
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200544void wSwitchPanelDestroy(WSwitchPanel * panel)
545{
546 int i;
547 RImage *image;
548
549 if (panel->win)
550 WMUnmapWidget(panel->win);
551
552 if (panel->images) {
553 WM_ITERATE_ARRAY(panel->images, image, i) {
554 if (image)
555 RReleaseImage(image);
556 }
557 WMFreeArray(panel->images);
558 }
559 if (panel->win)
560 WMDestroyWidget(panel->win);
561 if (panel->icons)
562 WMFreeArray(panel->icons);
563 WMFreeArray(panel->windows);
564 if (panel->defIcon)
565 RReleaseImage(panel->defIcon);
566 if (panel->tile)
567 RReleaseImage(panel->tile);
568 if (panel->tileTmp)
569 RReleaseImage(panel->tileTmp);
570 if (panel->bg)
571 RReleaseImage(panel->bg);
572 if (panel->font)
573 WMReleaseFont(panel->font);
574 if (panel->white)
575 WMReleaseColor(panel->white);
576 wfree(panel);
577}
f274afdd kojima2004-10-25 00:07:51 +0000578
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200579WWindow *wSwitchPanelSelectNext(WSwitchPanel * panel, int back)
f274afdd kojima2004-10-25 00:07:51 +0000580{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200581 WWindow *wwin;
582 int count = WMGetArrayItemCount(panel->windows);
cd36d738 kojima2004-10-15 00:27:36 +0000583
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200584 if (count == 0)
585 return NULL;
f274afdd kojima2004-10-25 00:07:51 +0000586
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200587 if (panel->win)
588 changeImage(panel, panel->current, 0);
f274afdd kojima2004-10-25 00:07:51 +0000589
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200590 if (back)
591 panel->current--;
592 else
593 panel->current++;
d63a0b48 kojima2004-10-27 02:54:32 +0000594
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200595 wwin = WMGetFromArray(panel->windows, (count + panel->current) % count);
f274afdd kojima2004-10-25 00:07:51 +0000596
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200597 if (back) {
598 if (panel->current < 0)
599 scrollIcons(panel, count);
600 else if (panel->current < panel->firstVisible)
601 scrollIcons(panel, -1);
602 } else {
603 if (panel->current >= count)
604 scrollIcons(panel, -count);
605 else if (panel->current - panel->firstVisible >= panel->visibleCount)
606 scrollIcons(panel, 1);
607 }
f274afdd kojima2004-10-25 00:07:51 +0000608
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200609 panel->current = (count + panel->current) % count;
f274afdd kojima2004-10-25 00:07:51 +0000610
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200611 if (panel->win) {
612 drawTitle(panel, panel->current, wwin->frame->title);
f274afdd kojima2004-10-25 00:07:51 +0000613
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200614 changeImage(panel, panel->current, 1);
615 }
f274afdd kojima2004-10-25 00:07:51 +0000616
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200617 return wwin;
618}
f274afdd kojima2004-10-25 00:07:51 +0000619
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200620WWindow *wSwitchPanelSelectFirst(WSwitchPanel * panel, int back)
621{
622 WWindow *wwin;
623 int count = WMGetArrayItemCount(panel->windows);
f274afdd kojima2004-10-25 00:07:51 +0000624
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200625 if (count == 0)
626 return NULL;
f54f0856 kojima2004-10-14 05:02:24 +0000627
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200628 if (panel->win)
629 changeImage(panel, panel->current, 0);
7908c9a6 kojima2004-10-19 01:53:11 +0000630
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200631 if (back) {
632 panel->current = count - 1;
633 scrollIcons(panel, count);
634 } else {
635 panel->current = 0;
636 scrollIcons(panel, -count);
637 }
7908c9a6 kojima2004-10-19 01:53:11 +0000638
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200639 wwin = WMGetFromArray(panel->windows, panel->current);
f54f0856 kojima2004-10-14 05:02:24 +0000640
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200641 if (panel->win) {
642 drawTitle(panel, panel->current, wwin->frame->title);
f54f0856 kojima2004-10-14 05:02:24 +0000643
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200644 changeImage(panel, panel->current, 1);
645 }
646 return wwin;
f54f0856 kojima2004-10-14 05:02:24 +0000647}
648
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200649WWindow *wSwitchPanelHandleEvent(WSwitchPanel * panel, XEvent * event)
f54f0856 kojima2004-10-14 05:02:24 +0000650{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200651 WMFrame *icon;
652 int i;
653 int focus = -1;
cd36d738 kojima2004-10-15 00:27:36 +0000654
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200655 if (!panel->win)
656 return NULL;
f274afdd kojima2004-10-25 00:07:51 +0000657
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200658 /* if (event->type == LeaveNotify) {
659 if (event->xcrossing.window == WMWidgetXID(panel->win))
660 focus= 0;
661 } else */ if (event->type == MotionNotify) {
f54f0856 kojima2004-10-14 05:02:24 +0000662
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200663 WM_ITERATE_ARRAY(panel->icons, icon, i) {
664 if (WMWidgetXID(icon) == event->xmotion.window) {
665 focus = i;
666 break;
667 }
668 }
669 }
670 if (focus >= 0 && panel->current != focus) {
671 WWindow *wwin;
f54f0856 kojima2004-10-14 05:02:24 +0000672
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200673 changeImage(panel, panel->current, 0);
674 changeImage(panel, focus, 1);
675 panel->current = focus;
7908c9a6 kojima2004-10-19 01:53:11 +0000676
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200677 wwin = WMGetFromArray(panel->windows, focus);
7908c9a6 kojima2004-10-19 01:53:11 +0000678
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200679 drawTitle(panel, panel->current, wwin->frame->title);
f54f0856 kojima2004-10-14 05:02:24 +0000680
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200681 return wwin;
682 }
b034bb07 kojima2004-10-22 22:57:14 +0000683
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200684 return NULL;
f54f0856 kojima2004-10-14 05:02:24 +0000685}
686
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200687Window wSwitchPanelGetWindow(WSwitchPanel * swpanel)
f6682a9a kojima2004-10-20 03:31:14 +0000688{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200689 if (!swpanel->win)
690 return None;
691 return WMWidgetXID(swpanel->win);
f6682a9a kojima2004-10-20 03:31:14 +0000692}