fixed bugs, re-enabled circulate raise
[wmaker-crm.git] / src / switchpanel.c
blob320e2c492d266a93d2756b123ed52d4a952b0a85
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>
25 #include <string.h>
27 #include "WindowMaker.h"
28 #include "screen.h"
29 #include "wcore.h"
30 #include "framewin.h"
31 #include "window.h"
32 #include "defaults.h"
33 #include "switchpanel.h"
34 #include "funcs.h"
35 #include "xinerama.h"
38 static char * tile_xpm[] = {
39 "64 64 2 1",
40 " c None",
41 ". c #FFFFFF",
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 " ...................................................... ",
105 " ................................................ "};
108 struct SwitchPanel {
109 WScreen *scr;
110 WMWindow *win;
111 WMBox *hbox;
112 WMLabel *label;
113 WMArray *icons;
114 WMArray *images;
115 WMArray *windows;
116 int current;
118 RImage *defIcon;
120 RImage *tile;
127 extern WPreferences wPreferences;
129 #define ICON_IDEAL_SIZE 48
130 #define ICON_EXTRASPACE 16
131 #define LABEL_HEIGHT 25
134 static int canReceiveFocus(WWindow *wwin)
136 if (wwin->frame->workspace != wwin->screen_ptr->current_workspace)
137 return 0;
138 if (!wwin->flags.mapped)
140 if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden)
141 return 0;
142 else
143 return -1;
145 if (WFLAGP(wwin, no_focusable))
146 return 0;
147 return 1;
151 static void changeImage(WSwitchPanel *panel, int index, int selected)
153 WMPixmap *pixmap= NULL;
154 WMLabel *label = WMGetFromArray(panel->icons, index);
155 RImage *image= WMGetFromArray(panel->images, index);
157 if (image && label) {
158 RColor bgColor;
159 RImage *back;
160 WMScreen *wscr= WMWidgetScreen(label);
161 int opaq= 255;
163 if (canReceiveFocus(WMGetFromArray(panel->windows, index)) < 0)
164 opaq= 50;
166 if (selected) {
167 back= RCloneImage(panel->tile);
168 RCombineAreaWithOpaqueness(back, image, 0, 0, image->width, image->height,
169 (back->width - image->width)/2, (back->height - image->height)/2,
170 opaq);
172 pixmap= WMCreatePixmapFromRImage(wscr, back, -1);
173 RReleaseImage(back);
174 } else {
175 bgColor.alpha= opaq;
176 bgColor.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8;
177 bgColor.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8;
178 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8;
180 back= RCreateImage(image->width, image->height, 1);
181 RFillImage(back, &bgColor);
183 RCombineImagesWithOpaqueness(back, image, opaq);
185 pixmap= WMCreatePixmapFromRImage(wscr, back, -1);
186 RReleaseImage(back);
190 if (pixmap && label) {
191 WMSetLabelImage(label, pixmap);
192 WMSetLabelImagePosition(label, WIPImageOnly);
193 WMReleasePixmap(pixmap);
198 static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth)
200 WMLabel *label= WMCreateLabel(panel->hbox);
201 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0);
202 RImage *image = NULL;
204 if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
205 image = RRetainImage(wwin->net_icon_image);
206 if (!image)
207 image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
209 if (!image && !panel->defIcon)
211 char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
212 if (file) {
213 char *path = FindImage(wPreferences.icon_path, file);
214 if (path) {
215 image = RLoadImage(panel->scr->rcontext, path, 0);
216 wfree(path);
220 if (!image && panel->defIcon)
221 image= RRetainImage(panel->defIcon);
223 if (image && ((image->width - iconWidth) > 2 || (image->height - iconWidth) > 2)) {
224 RImage *nimage;
225 nimage= RScaleImage(image, iconWidth, (image->height * iconWidth / image->width));
226 RReleaseImage(image);
227 image= nimage;
230 WMAddToArray(panel->images, image);
231 WMAddToArray(panel->icons, label);
235 WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace)
237 WWindow *wwin;
238 WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel));
239 int i;
240 int width;
241 int height;
242 int iconWidth = ICON_IDEAL_SIZE;
243 WMBox *vbox;
244 int fl;
246 memset(panel, 0, sizeof(WSwitchPanel));
248 panel->scr= scr;
249 panel->windows= WMCreateArray(10);
251 for (fl= 0; fl < 2; fl++) {
252 for (wwin= curwin; wwin; wwin= wwin->prev) {
253 if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
254 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
255 WMInsertInArray(panel->windows, 0, wwin);
258 wwin = curwin;
259 /* start over from the beginning of the list */
260 while (wwin->next)
261 wwin = wwin->next;
263 for (wwin= curwin; wwin && wwin != curwin; wwin= wwin->prev) {
264 if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) &&
265 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
266 WMInsertInArray(panel->windows, 0, wwin);
271 width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows);
273 if (width > WMScreenWidth(scr->wmscreen))
275 width= WMScreenWidth(scr->wmscreen) - 100;
276 iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE;
279 if (WMGetArrayItemCount(panel->windows) == 0) {
280 WMFreeArray(panel->windows);
281 wfree(panel);
282 return NULL;
285 if (iconWidth < 16) {
286 /* if there are too many windows, don't bother trying to show the panel */
288 return panel;
291 height= iconWidth + LABEL_HEIGHT + 10 + ICON_EXTRASPACE + 10;
293 panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows));
294 panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows));
296 panel->win = WMCreateWindow(scr->wmscreen, "");
297 WMResizeWidget(panel->win, width + 10, height);
300 WMFrame *frame = WMCreateFrame(panel->win);
301 WMSetFrameRelief(frame, WRSimple);
302 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
304 vbox = WMCreateBox(panel->win);
306 WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5);
307 WMSetBoxHorizontal(vbox, False);
309 panel->label = WMCreateLabel(vbox);
310 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, LABEL_HEIGHT, 0, 0);
311 if (scr->focused_window && scr->focused_window->frame->title)
312 WMSetLabelText(panel->label, scr->focused_window->frame->title);
313 else
314 WMSetLabelText(panel->label, "");
317 WMColor *color;
318 WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12);
320 WMSetLabelRelief(panel->label, WRSunken);
321 WMSetLabelFont(panel->label, boldFont);
322 color = WMDarkGrayColor(scr->wmscreen);
323 WMSetWidgetBackgroundColor(panel->label, color);
324 WMReleaseColor(color);
325 color = WMWhiteColor(scr->wmscreen);
326 WMSetLabelTextColor(panel->label, color);
327 WMReleaseColor(color);
329 WMReleaseFont(boldFont);
333 RImage *tmp= NULL;
334 RColor bgColor;
335 char *path = FindImage(wPreferences.pixmap_path, "swtile.png");
336 if (path) {
337 tmp = RLoadImage(panel->scr->rcontext, path, 0);
338 wfree(path);
341 if (!tmp)
342 tmp= RGetImageFromXPMData(scr->rcontext, tile_xpm);
344 panel->tile = RScaleImage(tmp, iconWidth+ICON_EXTRASPACE, iconWidth+ICON_EXTRASPACE);
346 bgColor.alpha = 255;
347 bgColor.red = WMRedComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
348 bgColor.green = WMGreenComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
349 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
351 RCombineImageWithColor(panel->tile, &bgColor);
353 RReleaseImage(tmp);
356 panel->hbox = WMCreateBox(vbox);
357 WMSetBoxHorizontal(panel->hbox, True);
358 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 4);
360 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
361 addIconForWindow(panel, wwin, iconWidth);
362 changeImage(panel, i, 0);
365 WMMapSubwidgets(panel->win);
366 WMRealizeWidget(panel->win);
368 WMPoint center;
370 center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
371 width+10, height);
372 WMMoveWidget(panel->win, center.x, center.y);
375 panel->current= WMGetFirstInArray(panel->windows, curwin);
376 if (panel->current >= 0)
377 changeImage(panel, panel->current, 1);
379 WMMapWidget(panel->win);
381 return panel;
385 void wSwitchPanelDestroy(WSwitchPanel *panel)
387 int i;
388 RImage *image;
390 if (panel->images) {
391 WM_ITERATE_ARRAY(panel->images, image, i) {
392 if (image)
393 RReleaseImage(image);
395 WMFreeArray(panel->images);
397 if (panel->win)
398 WMDestroyWidget(panel->win);
399 if (panel->icons)
400 WMFreeArray(panel->icons);
401 WMFreeArray(panel->windows);
402 if (panel->defIcon)
403 RReleaseImage(panel->defIcon);
404 if (panel->tile)
405 RReleaseImage(panel->tile);
406 wfree(panel);
410 WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
412 WWindow *wwin;
413 int count = WMGetArrayItemCount(panel->windows);
415 if (count == 0)
416 return NULL;
418 if (panel->win)
419 changeImage(panel, panel->current, 0);
421 if (!back)
422 panel->current = (count + panel->current - 1) % count;
423 else
424 panel->current = (panel->current + 1) % count;
426 wwin = WMGetFromArray(panel->windows, panel->current);
428 if (panel->win) {
429 WMSetLabelText(panel->label, wwin->frame->title);
431 changeImage(panel, panel->current, 1);
433 return wwin;
437 WWindow *wSwitchPanelSelectFirst(WSwitchPanel *panel, int back)
439 WWindow *wwin;
440 int count = WMGetArrayItemCount(panel->windows);
442 if (count == 0)
443 return NULL;
445 if (panel->win)
446 changeImage(panel, panel->current, 0);
448 if (!back)
449 panel->current = count-1;
450 else
451 panel->current = 0;
453 wwin = WMGetFromArray(panel->windows, panel->current);
455 if (panel->win) {
456 WMSetLabelText(panel->label, wwin->frame->title);
458 changeImage(panel, panel->current, 1);
460 return wwin;
464 WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
466 WMLabel *label;
467 int i;
469 printf("%i %i\n", event->xmotion.x, event->xmotion.y);
471 WM_ITERATE_ARRAY(panel->icons, label, i) {
472 if (WMWidgetXID(label) == event->xmotion.subwindow)
473 puts("HOORAY");
476 return NULL;
480 Window wSwitchPanelGetWindow(WSwitchPanel *swpanel)
482 return WMWidgetXID(swpanel->win);