some documentation updates
[wmaker-crm.git] / src / switchpanel.c
blob3bfd5a0198376621c499f546d0f2d2fe41f71661
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
132 static void changeImage(WSwitchPanel *panel, int index, int selected)
134 WMPixmap *pixmap= NULL;
135 WMLabel *label = WMGetFromArray(panel->icons, index);
136 RImage *image= WMGetFromArray(panel->images, index);
137 WMScreen *wscr = WMWidgetScreen(label);
139 if (image) {
140 RColor bgColor;
141 RImage *back;
143 if (selected) {
144 back= RCloneImage(panel->tile);
145 RCombineArea(back, image, 0, 0, image->width, image->height,
146 (back->width - image->width)/2, (back->height - image->height)/2);
148 pixmap= WMCreatePixmapFromRImage(wscr, back, -1);
149 RReleaseImage(back);
150 } else {
151 bgColor.alpha= 100;
152 bgColor.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8;
153 bgColor.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8;
154 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8;
156 image= RCloneImage(image);
157 RCombineImageWithColor(image, &bgColor);
159 pixmap= WMCreatePixmapFromRImage(wscr, image, -1);
160 RReleaseImage(image);
164 if (pixmap) {
165 WMSetLabelImage(label, pixmap);
166 WMSetLabelImagePosition(label, WIPImageOnly);
167 WMReleasePixmap(pixmap);
172 static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth)
174 WMLabel *label= WMCreateLabel(panel->hbox);
175 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0);
176 RImage *image = NULL;
178 if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
179 image = RRetainImage(wwin->net_icon_image);
180 if (!image)
181 image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
183 if (!image && !panel->defIcon)
185 char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
186 if (file) {
187 char *path = FindImage(wPreferences.icon_path, file);
188 if (path) {
189 image = RLoadImage(panel->scr->rcontext, path, 0);
190 wfree(path);
194 if (!image && panel->defIcon)
195 image= RRetainImage(panel->defIcon);
197 if (image && ((image->width - iconWidth) > 2 || (image->height - iconWidth) > 2)) {
198 RImage *nimage;
199 nimage= RScaleImage(image, iconWidth, (image->height * iconWidth / image->width));
200 RReleaseImage(image);
201 image= nimage;
204 WMAddToArray(panel->images, image);
205 WMAddToArray(panel->icons, label);
209 WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace)
211 WWindow *wwin;
212 WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel));
213 int i;
214 int width;
215 int height;
216 int iconWidth = ICON_IDEAL_SIZE;
217 WMBox *vbox;
219 memset(panel, 0, sizeof(WSwitchPanel));
221 panel->scr= scr;
222 panel->windows= WMCreateArray(10);
224 for (wwin= curwin; wwin; wwin= wwin->prev) {
225 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
226 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
227 WMInsertInArray(panel->windows, 0, wwin);
230 wwin = curwin;
231 /* start over from the beginning of the list */
232 while (wwin->next)
233 wwin = wwin->next;
235 for (wwin= curwin; wwin && wwin != curwin; wwin= wwin->prev) {
236 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
237 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
238 WMInsertInArray(panel->windows, 0, wwin);
242 width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows);
244 if (width > WMScreenWidth(scr->wmscreen))
246 width= WMScreenWidth(scr->wmscreen) - 100;
247 iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE;
250 if (WMGetArrayItemCount(panel->windows) == 0) {
251 WMFreeArray(panel->windows);
252 wfree(panel);
253 return NULL;
256 if (iconWidth < 16) {
257 /* if there are too many windows, don't bother trying to show the panel */
259 return panel;
262 height= iconWidth + 20 + 10 + ICON_EXTRASPACE;
264 panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows));
265 panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows));
267 panel->win = WMCreateWindow(scr->wmscreen, "");
268 WMResizeWidget(panel->win, width + 10, height);
271 WMFrame *frame = WMCreateFrame(panel->win);
272 WMSetFrameRelief(frame, WRSimple);
273 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
275 vbox = WMCreateBox(panel->win);
277 WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5);
278 WMSetBoxHorizontal(vbox, False);
280 panel->label = WMCreateLabel(vbox);
281 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, 20, 0, 0);
282 if (scr->focused_window && scr->focused_window->frame->title)
283 WMSetLabelText(panel->label, scr->focused_window->frame->title);
284 else
285 WMSetLabelText(panel->label, "");
288 WMColor *color;
289 WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12);
291 WMSetLabelRelief(panel->label, WRSimple);
292 WMSetLabelFont(panel->label, boldFont);
293 color = WMDarkGrayColor(scr->wmscreen);
294 WMSetWidgetBackgroundColor(panel->label, color);
295 WMReleaseColor(color);
296 color = WMWhiteColor(scr->wmscreen);
297 WMSetLabelTextColor(panel->label, color);
298 WMReleaseColor(color);
300 WMReleaseFont(boldFont);
304 RImage *tmp= NULL;
305 RColor bgColor;
306 char *path = FindImage(wPreferences.pixmap_path, "swtile.png");
307 if (path) {
308 tmp = RLoadImage(panel->scr->rcontext, path, 0);
309 wfree(path);
312 if (!tmp)
313 tmp= RGetImageFromXPMData(scr->rcontext, tile_xpm);
315 panel->tile = RScaleImage(tmp, iconWidth+ICON_EXTRASPACE, iconWidth+ICON_EXTRASPACE);
317 bgColor.alpha = 255;
318 bgColor.red = WMRedComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
319 bgColor.green = WMGreenComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
320 bgColor.blue = WMBlueComponentOfColor(WMGrayColor(scr->wmscreen))>>8;
322 RCombineImageWithColor(panel->tile, &bgColor);
324 RReleaseImage(tmp);
327 panel->hbox = WMCreateBox(vbox);
328 WMSetBoxHorizontal(panel->hbox, True);
329 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 4);
331 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
332 addIconForWindow(panel, wwin, iconWidth);
333 changeImage(panel, i, 0);
336 WMMapSubwidgets(panel->win);
337 WMRealizeWidget(panel->win);
338 WMMapWidget(panel->win);
340 WMPoint center;
342 center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr),
343 width+10, height);
344 WMMoveWidget(panel->win, center.x, center.y);
347 panel->current= WMGetFirstInArray(panel->windows, curwin);
348 if (panel->current >= 0)
349 changeImage(panel, panel->current, 1);
351 return panel;
355 void wSwitchPanelDestroy(WSwitchPanel *panel)
357 int i;
358 RImage *image;
360 if (panel->images) {
361 WM_ITERATE_ARRAY(panel->images, image, i) {
362 if (image)
363 RReleaseImage(image);
365 WMFreeArray(panel->images);
367 if (panel->win)
368 WMDestroyWidget(panel->win);
369 if (panel->icons)
370 WMFreeArray(panel->icons);
371 WMFreeArray(panel->windows);
372 if (panel->defIcon)
373 RReleaseImage(panel->defIcon);
374 if (panel->tile)
375 RReleaseImage(panel->tile);
376 wfree(panel);
380 WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
382 WWindow *wwin;
383 int count = WMGetArrayItemCount(panel->windows);
385 if (count == 0)
386 return NULL;
388 if (panel->win)
389 changeImage(panel, panel->current, 0);
391 if (!back)
392 panel->current = (count + panel->current - 1) % count;
393 else
394 panel->current = (panel->current + 1) % count;
396 wwin = WMGetFromArray(panel->windows, panel->current);
398 if (panel->win) {
399 WMSetLabelText(panel->label, wwin->frame->title);
401 changeImage(panel, panel->current, 1);
403 return wwin;
408 WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
410 WMLabel *label;
411 int i;
413 printf("%i %i\n", event->xmotion.x, event->xmotion.y);
415 WM_ITERATE_ARRAY(panel->icons, label, i) {
416 if (WMWidgetXID(label) == event->xmotion.subwindow)
417 puts("HOORAY");
420 return NULL;