/* * Window Maker window manager * * Copyright (c) 1997 Shige Abe and * Alfredo K. Kojima * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ #include "wconfig.h" #ifndef LITE #include #include #include #include #include #include "WindowMaker.h" #include "window.h" #include "actions.h" #include "client.h" #include "funcs.h" #include "stacking.h" #include "workspace.h" #include "framewin.h" /********* Global Variables *******/ extern WPreferences wPreferences; extern Time LastTimestamp; /* * FocusWindow * * - Needs to check if already in the right workspace before * calling wChangeWorkspace? * * Order: * Switch to correct workspace * Unshade if shaded * If iconified then deiconify else focus/raise. */ static void focusWindow(WMenu *menu, WMenuEntry *entry) { WWindow *wwin; WScreen *scr; int x, y, move=0; wwin = (WWindow*)entry->clientdata; scr = wwin->screen_ptr; wMakeWindowVisible(wwin); x = wwin->frame_x; y = wwin->frame_y; /* bring window back to visible area */ move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width, wwin->frame->core->height); if (move) { wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height); } } /* * * Open switch menu * */ void OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard) { WMenu *switchmenu = scr->switch_menu; WWindow *wwin; if (switchmenu) { if (switchmenu->flags.mapped) { if (!switchmenu->flags.buttoned) { wMenuUnmap(switchmenu); } else { wRaiseFrame(switchmenu->frame->core); if (keyboard) wMenuMapAt(switchmenu, 0, 0, True); else wMenuMapCopyAt(switchmenu, x-switchmenu->frame->core->width/2, y); } } else { wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y, keyboard); } return; } switchmenu = wMenuCreate(scr,_("Windows"),True); scr->switch_menu = switchmenu; wwin = scr->focused_window; while (wwin) { UpdateSwitchMenu(scr, wwin, ACTION_ADD); wwin = wwin->prev; } if (switchmenu) { if (!switchmenu->flags.realized) wMenuRealize(switchmenu); wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y, keyboard); } } static int menuIndexForWindow(WMenu *menu, WWindow *wwin, int old_pos) { int idx; if (menu->entry_no == 0) return -1; #define WS(i) ((WWindow*)menu->entries[i]->clientdata)->frame->workspace if (old_pos >= 0) { if (WS(old_pos) >= wwin->frame->workspace && (old_pos == 0 || WS(old_pos-1) <= wwin->frame->workspace)) { return old_pos; } } #undef WS for (idx = 0; idx < menu->entry_no; idx++) { WWindow *tw = (WWindow*)menu->entries[idx]->clientdata; if (!IS_OMNIPRESENT(tw) && tw->frame->workspace > wwin->frame->workspace) { break; } } return idx; } /* * Update switch menu */ void UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action) { WMenu *switchmenu = scr->switch_menu; WMenuEntry *entry; char title[MAX_MENU_TEXT_LENGTH+6]; int i; int checkVisibility = 0; if (!wwin->screen_ptr->switch_menu) return; /* * This menu is updated under the following conditions: * * 1. When a window is created. * 2. When a window is destroyed. * * 3. When a window changes it's title. * 4. When a window changes its workspace. */ if (action == ACTION_ADD) { char *t; int idx; if (wwin->flags.internal_window || WFLAGP(wwin, skip_window_list)) return; if (wwin->frame->title) sprintf(title, "%s", wwin->frame->title); else sprintf(title, "%s", DEF_WINDOW_TITLE); t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH); if (IS_OMNIPRESENT(wwin)) idx = -1; else { idx = menuIndexForWindow(switchmenu, wwin, -1); } entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin); wfree(t); entry->flags.indicator = 1; entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8); if (IS_OMNIPRESENT(wwin)) sprintf(entry->rtext, "[*]"); else sprintf(entry->rtext, "[%s]", scr->workspaces[wwin->frame->workspace]->name); if (wwin->flags.hidden) { entry->flags.indicator_type = MI_HIDDEN; entry->flags.indicator_on = 1; } else if (wwin->flags.miniaturized) { entry->flags.indicator_type = MI_MINIWINDOW; entry->flags.indicator_on = 1; } else if (wwin->flags.focused) { entry->flags.indicator_type = MI_DIAMOND; entry->flags.indicator_on = 1; } else if (wwin->flags.shaded) { entry->flags.indicator_type = MI_SHADED; entry->flags.indicator_on = 1; } wMenuRealize(switchmenu); checkVisibility = 1; } else { char *t; for (i=0; ientry_no; i++) { entry = switchmenu->entries[i]; /* this is the entry that was changed */ if (entry->clientdata == wwin) { switch (action) { case ACTION_REMOVE: wMenuRemoveItem(switchmenu, i); wMenuRealize(switchmenu); checkVisibility = 1; break; case ACTION_CHANGE: if (entry->text) wfree(entry->text); if (wwin->frame->title) sprintf(title, "%s", wwin->frame->title); else sprintf(title, "%s", DEF_WINDOW_TITLE); t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH); entry->text = t; wMenuRealize(switchmenu); checkVisibility = 1; break; case ACTION_CHANGE_WORKSPACE: if (entry->rtext) { int idx = -1; char *t, *rt; int it, ion; if (IS_OMNIPRESENT(wwin)) { sprintf(entry->rtext, "[*]"); } else { sprintf(entry->rtext, "[%s]", scr->workspaces[wwin->frame->workspace]->name); } rt = entry->rtext; entry->rtext = NULL; t = entry->text; entry->text = NULL; it = entry->flags.indicator_type; ion = entry->flags.indicator_on; wMenuRemoveItem(switchmenu, i); if (!IS_OMNIPRESENT(wwin) && idx < 0) { idx = menuIndexForWindow(switchmenu, wwin, i); } entry = wMenuInsertCallback(switchmenu, idx, t, focusWindow, wwin); wfree(t); entry->rtext = rt; entry->flags.indicator = 1; entry->flags.indicator_type = it; entry->flags.indicator_on = ion; } wMenuRealize(switchmenu); checkVisibility = 1; break; case ACTION_CHANGE_STATE: if (wwin->flags.hidden) { entry->flags.indicator_type = MI_HIDDEN; entry->flags.indicator_on = 1; } else if (wwin->flags.miniaturized) { entry->flags.indicator_type = MI_MINIWINDOW; entry->flags.indicator_on = 1; } else if (wwin->flags.shaded && !wwin->flags.focused) { entry->flags.indicator_type = MI_SHADED; entry->flags.indicator_on = 1; } else { entry->flags.indicator_on = wwin->flags.focused; entry->flags.indicator_type = MI_DIAMOND; } break; } break; } } } if (checkVisibility) { int tmp; tmp = switchmenu->frame->top_width + 5; /* if menu got unreachable, bring it to a visible place */ if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) { wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width, switchmenu->frame_y, False); } } wMenuPaint(switchmenu); } void UpdateSwitchMenuWorkspace(WScreen *scr, int workspace) { WMenu *menu = scr->switch_menu; int i; WWindow *wwin; if (!menu) return; for (i=0; ientry_no; i++) { wwin = (WWindow*)menu->entries[i]->clientdata; if (wwin->frame->workspace==workspace && !IS_OMNIPRESENT(wwin)) { if (IS_OMNIPRESENT(wwin)) sprintf(menu->entries[i]->rtext, "[*]"); else sprintf(menu->entries[i]->rtext, "[%s]", scr->workspaces[wwin->frame->workspace]->name); menu->flags.realized = 0; } } if (!menu->flags.realized) wMenuRealize(menu); } #endif /* !LITE */