fixed cycling
[wmaker-crm.git] / src / switchpanel.c
blob08efffed1bb0bc4f5bc66af3d1b8c0868ca6d29e
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, WWindow *curwin, 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->defIcon= NULL;
223 panel->normalColor = WMGrayColor(scr->wmscreen);
224 panel->selectColor = WMWhiteColor(scr->wmscreen);
226 panel->scr= scr;
227 panel->windows= WMCreateArray(10);
229 for (wwin= curwin; wwin; wwin= wwin->prev) {
230 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
231 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
232 WMInsertInArray(panel->windows, 0, wwin);
235 wwin = curwin;
236 /* start over from the beginning of the list */
237 while (wwin->next)
238 wwin = wwin->next;
240 for (wwin= curwin; wwin && wwin != curwin; wwin= wwin->prev) {
241 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
242 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
243 WMInsertInArray(panel->windows, 0, wwin);
247 width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows);
249 if (width > WMScreenWidth(scr->wmscreen))
251 width= WMScreenWidth(scr->wmscreen) - 100;
252 iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE;
255 if (iconWidth < 16 || WMGetArrayItemCount(panel->windows) == 0)
257 /* if there are too many windows, don't bother trying to show the panel */
258 WMFreeArray(panel->windows);
259 wfree(panel);
260 return NULL;
263 height= iconWidth + 20 + 10 + ICON_EXTRASPACE;
265 panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows));
266 panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows));
268 panel->win = WMCreateWindow(scr->wmscreen, "");
269 WMResizeWidget(panel->win, width + 10, height);
272 WMFrame *frame = WMCreateFrame(panel->win);
273 WMSetFrameRelief(frame, WRSimple);
274 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
276 vbox = WMCreateBox(panel->win);
278 WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5);
279 WMSetBoxHorizontal(vbox, False);
281 panel->label = WMCreateLabel(vbox);
282 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, 20, 0, 0);
283 if (scr->focused_window && scr->focused_window->frame->title)
284 WMSetLabelText(panel->label, scr->focused_window->frame->title);
285 else
286 WMSetLabelText(panel->label, "");
289 WMColor *color;
290 WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12);
292 WMSetLabelRelief(panel->label, WRSimple);
293 WMSetLabelFont(panel->label, boldFont);
294 color = WMDarkGrayColor(scr->wmscreen);
295 WMSetWidgetBackgroundColor(panel->label, color);
296 WMReleaseColor(color);
297 color = WMWhiteColor(scr->wmscreen);
298 WMSetLabelTextColor(panel->label, color);
299 WMReleaseColor(color);
301 WMReleaseFont(boldFont);
305 RImage *tmp= NULL;
306 RColor bgColor;
307 char *path = FindImage(wPreferences.pixmap_path, "swtile.png");
308 if (path) {
309 tmp = RLoadImage(panel->scr->rcontext, path, 0);
310 wfree(path);
313 if (!tmp)
314 tmp= RGetImageFromXPMData(scr->rcontext, tile_xpm);
316 panel->tile = RScaleImage(tmp, iconWidth+ICON_EXTRASPACE, iconWidth+ICON_EXTRASPACE);
318 bgColor.alpha = 255;
319 bgColor.red = WMRedComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
320 bgColor.green = WMGreenComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
321 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
323 RCombineImageWithColor(panel->tile, &bgColor);
325 RReleaseImage(tmp);
328 panel->hbox = WMCreateBox(vbox);
329 WMSetBoxHorizontal(panel->hbox, True);
330 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 4);
332 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
333 addIconForWindow(panel, wwin, iconWidth);
334 changeImage(panel, i, 0);
337 WMMapSubwidgets(panel->win);
338 WMRealizeWidget(panel->win);
339 WMMapWidget(panel->win);
341 WMPoint center;
343 center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
344 width+10, height);
345 WMMoveWidget(panel->win, center.x, center.y);
348 panel->current= WMGetFirstInArray(panel->windows, curwin);
349 changeImage(panel, panel->current, 1);
351 return panel;
355 void wSwitchPanelDestroy(WSwitchPanel *panel)
357 int i;
358 RImage *image;
359 WM_ITERATE_ARRAY(panel->images, image, i) {
360 if (image)
361 RReleaseImage(image);
363 WMDestroyWidget(panel->win);
364 WMFreeArray(panel->icons);
365 WMFreeArray(panel->windows);
366 WMFreeArray(panel->images);
367 WMReleaseColor(panel->selectColor);
368 WMReleaseColor(panel->normalColor);
369 if (panel->defIcon)
370 RReleaseImage(panel->defIcon);
371 RReleaseImage(panel->tile);
372 wfree(panel);
376 WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
378 WWindow *wwin;
379 int count = WMGetArrayItemCount(panel->windows);
381 changeImage(panel, panel->current, 0);
383 if (!back)
384 panel->current = (count + panel->current - 1) % count;
385 else
386 panel->current = (panel->current + 1) % count;
388 wwin = WMGetFromArray(panel->windows, panel->current);
390 WMSetLabelText(panel->label, wwin->frame->title);
392 changeImage(panel, panel->current, 1);
394 return wwin;
399 WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
401 WMLabel *label;
402 int i;
404 printf("%i %i\n", event->xmotion.x, event->xmotion.y);
406 WM_ITERATE_ARRAY(panel->icons, label, i) {
407 if (WMWidgetXID(label) == event->xmotion.subwindow)
408 puts("HOORAY");
411 return NULL;