Bug fixes for 0.20.3 pre-release 2
[wmaker-crm.git] / src / switchmenu.c
blobba13b3d903bb0355f1d9c7120e6866d8b43d02c9
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997 Shige Abe and
5 * Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
24 #include "wconfig.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
33 #include "WindowMaker.h"
34 #include "window.h"
35 #include "actions.h"
36 #include "client.h"
37 #include "funcs.h"
38 #include "stacking.h"
39 #include "workspace.h"
40 #include "framewin.h"
42 /********* Global Variables *******/
43 extern WPreferences wPreferences;
44 extern Time LastTimestamp;
48 * FocusWindow
50 * - Needs to check if already in the right workspace before
51 * calling wChangeWorkspace?
53 * Order:
54 * Switch to correct workspace
55 * Unshade if shaded
56 * If iconified then deiconify else focus/raise.
58 static void
59 focusWindow(WMenu *menu, WMenuEntry *entry)
61 WWindow *wwin;
62 WScreen *scr;
63 int x, y, move=0;
65 wwin = (WWindow*)entry->clientdata;
66 scr = wwin->screen_ptr;
68 wMakeWindowVisible(wwin);
70 x = wwin->frame_x;
71 y = wwin->frame_y;
73 /* bring window back to visible area */
74 move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width,
75 wwin->frame->core->height);
77 if (move) {
78 wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
84 * Open switch menu
87 void
88 OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
90 WMenu *switchmenu = scr->switch_menu;
91 WWindow *wwin;
93 if (switchmenu) {
94 if (switchmenu->flags.mapped) {
95 if (!switchmenu->flags.buttoned) {
96 wMenuUnmap(switchmenu);
97 } else {
98 wRaiseFrame(switchmenu->frame->core);
100 if (keyboard)
101 wMenuMapAt(switchmenu, 0, 0, True);
102 else
103 wMenuMapCopyAt(switchmenu, x-switchmenu->frame->core->width/2,
104 y-switchmenu->frame->top_width/2);
106 } else {
107 wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
108 y-switchmenu->frame->top_width/2, keyboard);
110 return;
112 switchmenu = wMenuCreate(scr,_("Windows"),True);
113 scr->switch_menu = switchmenu;
116 wwin = scr->focused_window;
117 while (wwin) {
118 UpdateSwitchMenu(scr, wwin, ACTION_ADD);
120 wwin = wwin->prev;
123 if (switchmenu) {
124 if (!switchmenu->flags.realized)
125 wMenuRealize(switchmenu);
126 wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
127 y-switchmenu->frame->top_width/2, keyboard);
133 * Update switch menu
137 void
138 UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
140 WMenu *switchmenu = scr->switch_menu;
141 WMenuEntry *entry;
142 char title[MAX_MENU_TEXT_LENGTH+6];
143 int i;
144 int checkVisibility = 0;
146 if (!wwin->screen_ptr->switch_menu)
147 return;
149 * This menu is updated under the following conditions:
151 * 1. When a window is created.
152 * 2. When a window is destroyed.
154 * 3. When a window changes it's title.
156 if (action == ACTION_ADD) {
157 char *t;
158 if (wwin->flags.internal_window
159 || wwin->window_flags.skip_window_list)
160 return;
162 if (wwin->frame->title)
163 sprintf(title, "%s", wwin->frame->title);
164 else
165 sprintf(title, "%s", DEF_WINDOW_TITLE);
166 t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
167 entry = wMenuAddCallback(switchmenu, t, focusWindow, wwin);
168 free(t);
170 entry->flags.indicator = 1;
171 entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8);
172 if (wwin->window_flags.omnipresent)
173 sprintf(entry->rtext, "[*]");
174 else
175 sprintf(entry->rtext, "[%s]",
176 scr->workspaces[wwin->frame->workspace]->name);
178 if (wwin->flags.hidden) {
179 entry->flags.indicator_type = MI_HIDDEN;
180 entry->flags.indicator_on = 1;
181 } else if (wwin->flags.miniaturized) {
182 entry->flags.indicator_type = MI_MINIWINDOW;
183 entry->flags.indicator_on = 1;
184 } else if (wwin->flags.focused) {
185 entry->flags.indicator_type = MI_DIAMOND;
186 entry->flags.indicator_on = 1;
187 } else if (wwin->flags.shaded) {
188 entry->flags.indicator_type = MI_SHADED;
189 entry->flags.indicator_on = 1;
192 wMenuRealize(switchmenu);
193 checkVisibility = 1;
194 } else {
195 char *t;
196 for (i=0; i<switchmenu->entry_no; i++) {
197 entry = switchmenu->entries[i];
198 /* this is the entry that was changed */
199 if (entry->clientdata == wwin) {
200 switch (action) {
201 case ACTION_REMOVE:
202 wMenuRemoveItem(switchmenu, i);
203 wMenuRealize(switchmenu);
204 checkVisibility = 1;
205 break;
207 case ACTION_CHANGE:
208 if (entry->text)
209 free(entry->text);
211 if (wwin->frame->title)
212 sprintf(title, "%s", wwin->frame->title);
213 else
214 sprintf(title, "%s", DEF_WINDOW_TITLE);
216 t = ShrinkString(scr->menu_entry_font, title,
217 MAX_WINDOWLIST_WIDTH);
218 entry->text = t;
219 /* fall through to update workspace number */
220 case ACTION_CHANGE_WORKSPACE:
221 if (entry->rtext) {
222 if (wwin->window_flags.omnipresent)
223 sprintf(entry->rtext, "[*]");
224 else
225 sprintf(entry->rtext, "[%s]",
226 scr->workspaces[wwin->frame->workspace]->name);
228 wMenuRealize(switchmenu);
229 checkVisibility = 1;
230 break;
233 case ACTION_CHANGE_STATE:
234 if (wwin->flags.hidden) {
235 entry->flags.indicator_type = MI_HIDDEN;
236 entry->flags.indicator_on = 1;
237 } else if (wwin->flags.miniaturized) {
238 entry->flags.indicator_type = MI_MINIWINDOW;
239 entry->flags.indicator_on = 1;
240 } else if (wwin->flags.shaded && !wwin->flags.focused) {
241 entry->flags.indicator_type = MI_SHADED;
242 entry->flags.indicator_on = 1;
243 } else {
244 entry->flags.indicator_on = wwin->flags.focused;
245 entry->flags.indicator_type = MI_DIAMOND;
247 wMenuPaint(switchmenu);
248 break;
250 break;
254 if (checkVisibility) {
255 int tmp;
257 tmp = switchmenu->frame->top_width + 5;
258 /* if menu got unreachable, bring it to a visible place */
259 if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
260 wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
261 switchmenu->frame_y, False);
264 wMenuPaint(switchmenu);
269 void
270 UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
272 WMenu *menu = scr->switch_menu;
273 int i;
274 WWindow *wwin;
276 if (!menu)
277 return;
279 for (i=0; i<menu->entry_no; i++) {
280 wwin = (WWindow*)menu->entries[i]->clientdata;
282 if (wwin->frame->workspace==workspace
283 && !wwin->window_flags.omnipresent) {
284 if (wwin->window_flags.omnipresent)
285 sprintf(menu->entries[i]->rtext, "[*]");
286 else
287 sprintf(menu->entries[i]->rtext, "[%s]",
288 scr->workspaces[wwin->frame->workspace]->name);
289 menu->flags.realized = 0;
292 if (!menu->flags.realized)
293 wMenuRealize(menu);