enhanced icon highlighting in window switcher
[wmaker-crm.git] / src / switchpanel.c
blob43303b5b7ca525769d13d6ff9e6ea85a2257ede2
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2004 Alfredo K. Kojima
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.
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.
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.
22 #include "wconfig.h"
24 #include <stdlib.h>
26 #include "WindowMaker.h"
27 #include "screen.h"
28 #include "wcore.h"
29 #include "framewin.h"
30 #include "window.h"
31 #include "defaults.h"
32 #include "switchpanel.h"
33 #include "funcs.h"
34 #include "xinerama.h"
37 static char * tile_xpm[] = {
38 "64 64 2 1",
39 " c None",
40 ". c #FFFFFF",
41 " ................................................. ",
42 " ...................................................... ",
43 " ......................................................... ",
44 " ........................................................... ",
45 " ............................................................ ",
46 " .............................................................. ",
47 " .............................................................. ",
48 "............................................................... ",
49 "................................................................",
50 "................................................................",
51 "................................................................",
52 "................................................................",
53 "................................................................",
54 "................................................................",
55 "................................................................",
56 "................................................................",
57 "................................................................",
58 "................................................................",
59 "................................................................",
60 "................................................................",
61 "................................................................",
62 "................................................................",
63 "................................................................",
64 "................................................................",
65 "................................................................",
66 "................................................................",
67 "................................................................",
68 "................................................................",
69 "................................................................",
70 "................................................................",
71 "................................................................",
72 "................................................................",
73 "................................................................",
74 "................................................................",
75 "................................................................",
76 "................................................................",
77 "................................................................",
78 "................................................................",
79 "................................................................",
80 "................................................................",
81 "................................................................",
82 "................................................................",
83 "................................................................",
84 "................................................................",
85 "................................................................",
86 "................................................................",
87 "................................................................",
88 "................................................................",
89 "................................................................",
90 "................................................................",
91 "................................................................",
92 "................................................................",
93 "................................................................",
94 "................................................................",
95 "................................................................",
96 "................................................................",
97 " .............................................................. ",
98 " .............................................................. ",
99 " .............................................................. ",
100 " ............................................................ ",
101 " .......................................................... ",
102 " ........................................................ ",
103 " ...................................................... ",
104 " ................................................ "};
107 struct SwitchPanel {
108 WScreen *scr;
109 WMWindow *win;
110 WMBox *hbox;
111 WMLabel *label;
112 WMArray *icons;
113 WMArray *images;
114 WMArray *windows;
115 int current;
117 WMColor *normalColor;
118 WMColor *selectColor;
120 RImage *defIcon;
122 RImage *tile;
129 extern WPreferences wPreferences;
131 #define ICON_IDEAL_SIZE 48
132 #define ICON_EXTRASPACE 16
134 static void changeImage(WSwitchPanel *panel, int index, int selected)
136 WMPixmap *pixmap= NULL;
137 WMLabel *label = WMGetFromArray(panel->icons, index);
138 RImage *image= WMGetFromArray(panel->images, index);
139 WMScreen *wscr = WMWidgetScreen(label);
141 if (image) {
142 RColor bgColor;
143 RImage *back;
145 if (selected) {
146 back= RCloneImage(panel->tile);
147 RCombineArea(back, image, 0, 0, image->width, image->height,
148 (back->width - image->width)/2, (back->height - image->height)/2);
150 pixmap= WMCreatePixmapFromRImage(wscr, back, -1);
151 RReleaseImage(back);
152 } else {
153 bgColor.alpha= 100;
154 bgColor.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8;
155 bgColor.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8;
156 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8;
158 image= RCloneImage(image);
159 RCombineImageWithColor(image, &bgColor);
161 pixmap= WMCreatePixmapFromRImage(wscr, image, -1);
162 RReleaseImage(image);
166 if (pixmap) {
167 WMSetLabelImage(label, pixmap);
168 WMSetLabelImagePosition(label, WIPImageOnly);
169 WMReleasePixmap(pixmap);
174 static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth)
176 WMLabel *label= WMCreateLabel(panel->hbox);
177 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0);
178 RImage *image = NULL;
180 if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
181 image = RRetainImage(wwin->net_icon_image);
182 if (!image)
183 image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
185 if (!image && !panel->defIcon)
187 char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
188 if (file) {
189 char *path = FindImage(wPreferences.icon_path, file);
190 if (path) {
191 image = RLoadImage(panel->scr->rcontext, path, 0);
192 wfree(path);
196 if (!image && panel->defIcon)
197 image= RRetainImage(panel->defIcon);
199 if (image && (abs(image->width - iconWidth) > 2 || abs(image->height - iconWidth) > 2)) {
200 RImage *nimage;
201 nimage= RScaleImage(image, iconWidth, (image->height * iconWidth / image->width));
202 RReleaseImage(image);
203 image= nimage;
206 WMAddToArray(panel->images, image);
207 WMAddToArray(panel->icons, label);
211 WSwitchPanel *wInitSwitchPanel(WScreen *scr, int workspace)
213 WWindow *wwin;
214 WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel));
215 int i;
216 int width;
217 int height;
218 int iconWidth = ICON_IDEAL_SIZE;
219 WMBox *vbox;
221 panel->current= 0;
222 panel->defIcon= NULL;
224 panel->normalColor = WMGrayColor(scr->wmscreen);
225 panel->selectColor = WMWhiteColor(scr->wmscreen);
227 panel->scr= scr;
228 panel->windows= WMCreateArray(10);
230 for (wwin= scr->focused_window; wwin; wwin= wwin->prev) {
231 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
232 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
233 WMInsertInArray(panel->windows, 0, wwin);
237 width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows);
239 if (width > WMScreenWidth(scr->wmscreen))
241 width= WMScreenWidth(scr->wmscreen) - 100;
242 iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE;
245 if (iconWidth < 16 || WMGetArrayItemCount(panel->windows) == 0)
247 /* if there are too many windows, don't bother trying to show the panel */
248 WMFreeArray(panel->windows);
249 wfree(panel);
250 return NULL;
253 height= iconWidth + 20 + 10 + ICON_EXTRASPACE;
255 panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows));
256 panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows));
258 panel->win = WMCreateWindow(scr->wmscreen, "");
259 WMResizeWidget(panel->win, width + 10, height);
262 WMFrame *frame = WMCreateFrame(panel->win);
263 WMSetFrameRelief(frame, WRSimple);
264 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
266 vbox = WMCreateBox(panel->win);
268 WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5);
269 WMSetBoxHorizontal(vbox, False);
271 panel->label = WMCreateLabel(vbox);
272 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, 20, 0, 0);
273 if (scr->focused_window && scr->focused_window->frame->title)
274 WMSetLabelText(panel->label, scr->focused_window->frame->title);
275 else
276 WMSetLabelText(panel->label, "");
278 WMColor *color;
279 WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12);
281 WMSetLabelRelief(panel->label, WRSimple);
282 WMSetLabelFont(panel->label, boldFont);
283 color = WMDarkGrayColor(scr->wmscreen);
284 WMSetWidgetBackgroundColor(panel->label, color);
285 WMReleaseColor(color);
286 color = WMWhiteColor(scr->wmscreen);
287 WMSetLabelTextColor(panel->label, color);
288 WMReleaseColor(color);
290 WMReleaseFont(boldFont);
294 RImage *tmp= NULL;
295 RColor bgColor;
296 char *path = FindImage(wPreferences.pixmap_path, "swtile.png");
297 if (path) {
298 tmp = RLoadImage(panel->scr->rcontext, path, 0);
299 wfree(path);
302 if (!tmp)
303 tmp= RGetImageFromXPMData(scr->rcontext, tile_xpm);
305 panel->tile = RScaleImage(tmp, iconWidth+ICON_EXTRASPACE, iconWidth+ICON_EXTRASPACE);
307 bgColor.alpha = 255;
308 bgColor.red = WMRedComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
309 bgColor.green = WMGreenComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
310 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
312 RCombineImageWithColor(panel->tile, &bgColor);
314 RReleaseImage(tmp);
317 panel->hbox = WMCreateBox(vbox);
318 WMSetBoxHorizontal(panel->hbox, True);
319 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 2);
321 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
322 addIconForWindow(panel, wwin, iconWidth);
323 changeImage(panel, i, 0);
326 WMMapSubwidgets(panel->win);
327 WMRealizeWidget(panel->win);
328 WMMapWidget(panel->win);
330 WMPoint center;
332 center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
333 width+10, height);
334 WMMoveWidget(panel->win, center.x, center.y);
337 changeImage(panel, 0, 1);
339 return panel;
343 void wSwitchPanelDestroy(WSwitchPanel *panel)
345 int i;
346 RImage *image;
347 WM_ITERATE_ARRAY(panel->images, image, i) {
348 if (image)
349 RReleaseImage(image);
351 WMDestroyWidget(panel->win);
352 WMFreeArray(panel->icons);
353 WMFreeArray(panel->windows);
354 WMFreeArray(panel->images);
355 WMReleaseColor(panel->selectColor);
356 WMReleaseColor(panel->normalColor);
357 if (panel->defIcon)
358 RReleaseImage(panel->defIcon);
359 RReleaseImage(panel->tile);
360 wfree(panel);
364 WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
366 WWindow *wwin;
367 int count = WMGetArrayItemCount(panel->windows);
369 changeImage(panel, panel->current, 0);
371 if (!back)
372 panel->current = (count + panel->current - 1) % count;
373 else
374 panel->current = (panel->current + 1) % count;
376 wwin = WMGetFromArray(panel->windows, panel->current);
378 WMSetLabelText(panel->label, wwin->frame->title);
380 changeImage(panel, panel->current, 1);
382 return wwin;
387 WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
389 WMLabel *label;
390 int i;
392 printf("%i %i\n", event->xmotion.x, event->xmotion.y);
394 WM_ITERATE_ARRAY(panel->icons, label, i) {
395 if (WMWidgetXID(label) == event->xmotion.subwindow)
396 puts("HOORAY");
399 return NULL;