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,
27 #include "WindowMaker.h"
33 #include "switchpanel.h"
38 static char * tile_xpm
[] = {
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 " ................................................ "};
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
)
138 if (!wwin
->flags
.mapped
)
140 if (!wwin
->flags
.shaded
&& !wwin
->flags
.miniaturized
&& !wwin
->flags
.hidden
)
145 if (WFLAGP(wwin
, no_focusable
))
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
) {
160 WMScreen
*wscr
= WMWidgetScreen(label
);
163 if (canReceiveFocus(WMGetFromArray(panel
->windows
, index
)) < 0)
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,
172 pixmap
= WMCreatePixmapFromRImage(wscr
, back
, -1);
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);
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
);
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
);
213 char *path
= FindImage(wPreferences
.icon_path
, file
);
215 image
= RLoadImage(panel
->scr
->rcontext
, path
, 0);
220 if (!image
&& panel
->defIcon
)
221 image
= RRetainImage(panel
->defIcon
);
223 if (image
&& ((image
->width
- iconWidth
) > 2 || (image
->height
- iconWidth
) > 2)) {
225 nimage
= RScaleImage(image
, iconWidth
, (image
->height
* iconWidth
/ image
->width
));
226 RReleaseImage(image
);
230 WMAddToArray(panel
->images
, image
);
231 WMAddToArray(panel
->icons
, label
);
235 WSwitchPanel
*wInitSwitchPanel(WScreen
*scr
, WWindow
*curwin
, int workspace
)
238 WSwitchPanel
*panel
= wmalloc(sizeof(WSwitchPanel
));
242 int iconWidth
= ICON_IDEAL_SIZE
;
246 memset(panel
, 0, sizeof(WSwitchPanel
));
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
);
259 /* start over from the beginning of the list */
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
);
285 if (iconWidth
< 16) {
286 /* if there are too many windows, don't bother trying to show the 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
);
314 WMSetLabelText(panel
->label
, "");
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
);
335 char *path
= FindImage(wPreferences
.pixmap_path
, "swtile.png");
337 tmp
= RLoadImage(panel
->scr
->rcontext
, path
, 0);
342 tmp
= RGetImageFromXPMData(scr
->rcontext
, tile_xpm
);
344 panel
->tile
= RScaleImage(tmp
, iconWidth
+ICON_EXTRASPACE
, iconWidth
+ICON_EXTRASPACE
);
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
);
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
);
370 center
= wGetPointToCenterRectInHead(scr
, wGetHeadForPointerLocation(scr
),
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
);
385 void wSwitchPanelDestroy(WSwitchPanel
*panel
)
391 WM_ITERATE_ARRAY(panel
->images
, image
, i
) {
393 RReleaseImage(image
);
395 WMFreeArray(panel
->images
);
398 WMDestroyWidget(panel
->win
);
400 WMFreeArray(panel
->icons
);
401 WMFreeArray(panel
->windows
);
403 RReleaseImage(panel
->defIcon
);
405 RReleaseImage(panel
->tile
);
410 WWindow
*wSwitchPanelSelectNext(WSwitchPanel
*panel
, int back
)
413 int count
= WMGetArrayItemCount(panel
->windows
);
419 changeImage(panel
, panel
->current
, 0);
422 panel
->current
= (count
+ panel
->current
- 1) % count
;
424 panel
->current
= (panel
->current
+ 1) % count
;
426 wwin
= WMGetFromArray(panel
->windows
, panel
->current
);
429 WMSetLabelText(panel
->label
, wwin
->frame
->title
);
431 changeImage(panel
, panel
->current
, 1);
437 WWindow
*wSwitchPanelSelectFirst(WSwitchPanel
*panel
, int back
)
440 int count
= WMGetArrayItemCount(panel
->windows
);
446 changeImage(panel
, panel
->current
, 0);
449 panel
->current
= count
-1;
453 wwin
= WMGetFromArray(panel
->windows
, panel
->current
);
456 WMSetLabelText(panel
->label
, wwin
->frame
->title
);
458 changeImage(panel
, panel
->current
, 1);
464 WWindow
*wSwitchPanelHandleEvent(WSwitchPanel
*panel
, XEvent
*event
)
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
)
480 Window
wSwitchPanelGetWindow(WSwitchPanel
*swpanel
)
482 return WMWidgetXID(swpanel
->win
);