Updating to version 0.20.2
[wmaker-crm.git] / src / switchmenu.c
blob03e65eafdd1935b11c63a0962a2f76703144c82f
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 wWorkspaceChange(menu->frame->screen_ptr, wwin->frame->workspace);
70 if (wwin->flags.shaded) {
71 wUnshadeWindow(wwin);
73 if (wwin->flags.hidden) {
74 wUnhideApplication(wApplicationOf(wwin->main_window), False, False);
75 } else if (wwin->flags.miniaturized) {
76 wDeiconifyWindow(wwin);
77 } else {
78 wSetFocusTo(menu->frame->screen_ptr, wwin);
79 wRaiseFrame(wwin->frame->core);
82 x = wwin->frame_x;
83 y = wwin->frame_y;
85 /* bring window back to visible area */
86 move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width,
87 wwin->frame->core->height);
89 if (move) {
90 wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
96 * Open switch menu
99 void
100 OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
102 WMenu *switchmenu = scr->switch_menu;
103 WWindow *wwin;
105 if (switchmenu) {
106 if (switchmenu->flags.mapped) {
107 if (!switchmenu->flags.buttoned) {
108 wMenuUnmap(switchmenu);
109 } else {
110 wRaiseFrame(switchmenu->frame->core);
112 if (keyboard)
113 wMenuMapAt(switchmenu, 0, 0, True);
114 else
115 wMenuMapCopyAt(switchmenu, x-switchmenu->frame->core->width/2,
116 y-switchmenu->frame->top_width/2);
118 } else {
119 wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
120 y-switchmenu->frame->top_width/2, keyboard);
122 return;
124 switchmenu = wMenuCreate(scr,_("Windows"),True);
125 scr->switch_menu = switchmenu;
128 wwin = scr->focused_window;
129 while (wwin) {
130 UpdateSwitchMenu(scr, wwin, ACTION_ADD);
132 wwin = wwin->prev;
135 if (switchmenu) {
136 if (!switchmenu->flags.realized)
137 wMenuRealize(switchmenu);
138 wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
139 y-switchmenu->frame->top_width/2, keyboard);
145 * Update switch menu
149 void
150 UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
152 WMenu *switchmenu = scr->switch_menu;
153 WMenuEntry *entry;
154 char title[MAX_MENU_TEXT_LENGTH+6];
155 int i;
156 int checkVisibility = 0;
158 if (!wwin->screen_ptr->switch_menu)
159 return;
161 * This menu is updated under the following conditions:
163 * 1. When a window is created.
164 * 2. When a window is destroyed.
166 * 3. When a window changes it's title.
168 if (action == ACTION_ADD) {
169 char *t;
170 if (wwin->flags.internal_window
171 || wwin->window_flags.skip_window_list)
172 return;
174 if (wwin->frame->title)
175 sprintf(title, "%s", wwin->frame->title);
176 else
177 sprintf(title, "%s", DEF_WINDOW_TITLE);
178 t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
179 entry = wMenuAddCallback(switchmenu, t, focusWindow, wwin);
180 free(t);
182 entry->flags.indicator = 1;
183 entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8);
184 if (wwin->window_flags.omnipresent)
185 sprintf(entry->rtext, "[*]");
186 else
187 sprintf(entry->rtext, "[%s]",
188 scr->workspaces[wwin->frame->workspace]->name);
190 if (wwin->flags.hidden) {
191 entry->flags.indicator_type = MI_HIDDEN;
192 entry->flags.indicator_on = 1;
193 } else if (wwin->flags.miniaturized) {
194 entry->flags.indicator_type = MI_MINIWINDOW;
195 entry->flags.indicator_on = 1;
196 } else if (wwin->flags.focused) {
197 entry->flags.indicator_type = MI_DIAMOND;
198 entry->flags.indicator_on = 1;
199 } else if (wwin->flags.shaded) {
200 entry->flags.indicator_type = MI_SHADED;
201 entry->flags.indicator_on = 1;
204 wMenuRealize(switchmenu);
205 checkVisibility = 1;
206 } else {
207 char *t;
208 for (i=0; i<switchmenu->entry_no; i++) {
209 entry = switchmenu->entries[i];
210 /* this is the entry that was changed */
211 if (entry->clientdata == wwin) {
212 switch (action) {
213 case ACTION_REMOVE:
214 wMenuRemoveItem(switchmenu, i);
215 wMenuRealize(switchmenu);
216 checkVisibility = 1;
217 break;
219 case ACTION_CHANGE:
220 if (entry->text)
221 free(entry->text);
223 if (wwin->frame->title)
224 sprintf(title, "%s", wwin->frame->title);
225 else
226 sprintf(title, "%s", DEF_WINDOW_TITLE);
228 t = ShrinkString(scr->menu_entry_font, title,
229 MAX_WINDOWLIST_WIDTH);
230 entry->text = t;
231 /* fall through to update workspace number */
232 case ACTION_CHANGE_WORKSPACE:
233 if (entry->rtext) {
234 if (wwin->window_flags.omnipresent)
235 sprintf(entry->rtext, "[*]");
236 else
237 sprintf(entry->rtext, "[%s]",
238 scr->workspaces[wwin->frame->workspace]->name);
240 wMenuRealize(switchmenu);
241 checkVisibility = 1;
242 break;
245 case ACTION_CHANGE_STATE:
246 if (wwin->flags.hidden) {
247 entry->flags.indicator_type = MI_HIDDEN;
248 entry->flags.indicator_on = 1;
249 } else if (wwin->flags.miniaturized) {
250 entry->flags.indicator_type = MI_MINIWINDOW;
251 entry->flags.indicator_on = 1;
252 } else if (wwin->flags.shaded && !wwin->flags.focused) {
253 entry->flags.indicator_type = MI_SHADED;
254 entry->flags.indicator_on = 1;
255 } else {
256 entry->flags.indicator_on = wwin->flags.focused;
257 entry->flags.indicator_type = MI_DIAMOND;
259 wMenuPaint(switchmenu);
260 break;
262 break;
266 if (checkVisibility) {
267 int tmp;
269 tmp = switchmenu->frame->top_width + 5;
270 /* if menu got unreachable, bring it to a visible place */
271 if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
272 wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
273 switchmenu->frame_y, False);
276 wMenuPaint(switchmenu);
281 void
282 UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
284 WMenu *menu = scr->switch_menu;
285 int i;
286 WWindow *wwin;
288 if (!menu)
289 return;
291 for (i=0; i<menu->entry_no; i++) {
292 wwin = (WWindow*)menu->entries[i]->clientdata;
294 if (wwin->frame->workspace==workspace
295 && !wwin->window_flags.omnipresent) {
296 if (wwin->window_flags.omnipresent)
297 sprintf(menu->entries[i]->rtext, "[*]");
298 else
299 sprintf(menu->entries[i]->rtext, "[%s]",
300 scr->workspaces[wwin->frame->workspace]->name);
301 menu->flags.realized = 0;
304 if (!menu->flags.realized)
305 wMenuRealize(menu);