- MacOS X style window switching panel (navigate through windows with Alt-Tab or
[wmaker-crm.git] / src / switchpanel.c
blob823dc11e1e7bbac4dbd10c930a170f18112e6e41
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"
35 struct SwitchPanel {
36 WScreen *scr;
37 WMWindow *win;
38 WMBox *hbox;
39 WMLabel *label;
40 WMArray *icons;
41 WMArray *windows;
42 int current;
44 WMColor *normalColor;
45 WMColor *selectColor;
47 WMPixmap *defIcon;
51 extern WPreferences wPreferences;
53 #define ICON_EXTRASPACE 4
55 static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth)
57 WMLabel *label= WMCreateLabel(panel->hbox);
58 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0);
59 RImage *image = NULL;
60 WMPixmap *pixmap;
61 WMScreen *wscr = WMWidgetScreen(label);
63 if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image)
64 image = RRetainImage(wwin->net_icon_image);
65 if (!image)
66 image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class);
67 if (!image)
69 if (image && (abs(image->width - iconWidth) > 4 || abs(image->height - iconWidth) > 4)) {
70 RImage *nimage;
72 nimage= RScaleImage(image, iconWidth, (image->height * iconWidth / image->width));
73 RReleaseImage(image);
74 image= nimage;
77 if (image) {
78 pixmap= WMCreatePixmapFromRImage(wscr, image, 100);
79 RReleaseImage(image);
80 } else {
81 if (!panel->defIcon)
83 char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False);
84 if (file) {
85 char *path = FindImage(wPreferences.icon_path, file);
86 if (path) {
87 image = RLoadImage(panel->scr->rcontext, path, 0);
88 wfree(path);
90 panel->defIcon= WMCreatePixmapFromRImage(wscr, image, 100);
91 RReleaseImage(image);
96 if (panel->defIcon)
97 pixmap= WMRetainPixmap(panel->defIcon);
98 else
99 pixmap= NULL;
102 if (pixmap) {
103 WMSetLabelImage(label, pixmap);
104 WMSetLabelImagePosition(label, WIPImageOnly);
105 WMReleasePixmap(pixmap);
108 WMAddToArray(panel->icons, label);
112 WSwitchPanel *wInitSwitchPanel(WScreen *scr, int workspace)
114 WWindow *wwin;
115 WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel));
116 int i;
117 int width;
118 int height;
119 int iconWidth = 48;
120 WMBox *vbox;
122 panel->current= 0;
123 panel->defIcon= NULL;
125 panel->normalColor = WMGrayColor(scr->wmscreen);
126 panel->selectColor = WMWhiteColor(scr->wmscreen);
128 panel->scr= scr;
129 panel->windows= WMCreateArray(10);
131 for (wwin= scr->focused_window; wwin; wwin= wwin->prev) {
132 if (wwin->frame->workspace == workspace && wWindowCanReceiveFocus(wwin) &&
133 (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) {
134 WMInsertInArray(panel->windows, 0, wwin);
138 width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows);
140 if (width > WMScreenWidth(scr->wmscreen))
142 width= WMScreenWidth(scr->wmscreen) - 100;
143 iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE;
146 if (iconWidth < 16)
148 /* if there are too many windows, don't bother trying to show the panel */
149 WMFreeArray(panel->windows);
150 wfree(panel);
151 return NULL;
154 height= 48 + 20 + 10 + ICON_EXTRASPACE;
156 panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows));
158 panel->win = WMCreateWindow(scr->wmscreen, "");
159 WMResizeWidget(panel->win, width + 10, height);
162 WMFrame *frame = WMCreateFrame(panel->win);
163 WMSetFrameRelief(frame, WRSimple);
164 WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0);
166 vbox = WMCreateBox(panel->win);
168 WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5);
169 WMSetBoxHorizontal(vbox, False);
171 panel->label = WMCreateLabel(vbox);
172 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, 20, 0, 0);
173 if (scr->focused_window && scr->focused_window->frame->title)
174 WMSetLabelText(panel->label, scr->focused_window->frame->title);
175 else
176 WMSetLabelText(panel->label, "");
178 WMColor *color;
179 WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12);
181 WMSetLabelRelief(panel->label, WRSimple);
182 WMSetLabelFont(panel->label, boldFont);
183 color = WMDarkGrayColor(scr->wmscreen);
184 WMSetWidgetBackgroundColor(panel->label, color);
185 WMReleaseColor(color);
186 color = WMWhiteColor(scr->wmscreen);
187 WMSetLabelTextColor(panel->label, color);
188 WMReleaseColor(color);
190 WMReleaseFont(boldFont);
193 panel->hbox = WMCreateBox(vbox);
194 WMSetBoxHorizontal(panel->hbox, True);
195 WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 2);
197 WM_ITERATE_ARRAY(panel->windows, wwin, i) {
198 addIconForWindow(panel, wwin, iconWidth);
201 WMMapSubwidgets(panel->win);
202 WMRealizeWidget(panel->win);
203 WMMapWidget(panel->win);
204 WMMoveWidget(panel->win,
205 (WMScreenWidth(scr->wmscreen) - (width+10))/2,
206 (WMScreenHeight(scr->wmscreen) - height)/2);
208 WMSetWidgetBackgroundColor(WMGetFromArray(panel->icons, 0),
209 panel->selectColor);
211 return panel;
215 void wSwitchPanelDestroy(WSwitchPanel *panel)
217 WMDestroyWidget(panel->win);
218 WMFreeArray(panel->icons);
219 WMFreeArray(panel->windows);
220 WMReleaseColor(panel->selectColor);
221 WMReleaseColor(panel->normalColor);
222 if (panel->defIcon)
223 WMReleasePixmap(panel->defIcon);
224 wfree(panel);
228 WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back)
230 WWindow *wwin;
231 int count = WMGetArrayItemCount(panel->windows);
232 WMLabel *label;
234 label= WMGetFromArray(panel->icons, panel->current);
235 WMSetWidgetBackgroundColor(label, panel->normalColor);
236 WMSetLabelRelief(label, WRFlat);
238 if (!back)
239 panel->current = (count + panel->current - 1) % count;
240 else
241 panel->current = (panel->current + 1) % count;
243 wwin = WMGetFromArray(panel->windows, panel->current);
245 WMSetLabelText(panel->label, wwin->frame->title);
247 label= WMGetFromArray(panel->icons, panel->current);
248 WMSetWidgetBackgroundColor(label, panel->selectColor);
249 WMSetLabelRelief(label, WRSimple);
251 return wwin;
256 WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event)
258 WMLabel *label;
259 int i;
261 printf("%i %i\n", event->xmotion.x, event->xmotion.y);
263 WM_ITERATE_ARRAY(panel->icons, label, i) {
264 if (WMWidgetXID(label) == event->xmotion.subwindow)
265 puts("HOORAY");
268 return NULL;